summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/akismet/.htaccess6
-rw-r--r--plugins/akismet/admin.php27
-rw-r--r--plugins/akismet/akismet.js12
-rw-r--r--plugins/akismet/akismet.php39
-rw-r--r--plugins/akismet/readme.txt13
-rw-r--r--plugins/jetpack/_inc/gallery-settings.js19
-rw-r--r--plugins/jetpack/_inc/images/module-icons-sprite-2x.pngbin37559 -> 72735 bytes
-rw-r--r--plugins/jetpack/_inc/images/module-icons-sprite.pngbin11465 -> 31542 bytes
-rw-r--r--plugins/jetpack/_inc/images/publicize.pngbin0 -> 113219 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/carousel.pngbin0 -> 361672 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/custom-css.pngbin0 -> 43048 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/likes.pngbin0 -> 48953 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpgbin0 -> 29830 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/mobile-theme.pngbin0 -> 37559 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/notes.pngbin0 -> 27450 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/post-by-email.pngbin0 -> 28349 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/publicize.pngbin0 -> 113219 bytes
-rw-r--r--plugins/jetpack/_inc/images/screenshots/tiled-gallery.pngbin0 -> 192182 bytes
-rw-r--r--plugins/jetpack/_inc/jetpack.css247
-rw-r--r--plugins/jetpack/_inc/jetpack.js58
-rw-r--r--plugins/jetpack/_inc/jquery.inview.js143
-rw-r--r--plugins/jetpack/_inc/jquery.jetpack-resize.js275
-rw-r--r--plugins/jetpack/_inc/jquery.spin.js86
-rw-r--r--plugins/jetpack/_inc/postmessage.js438
-rw-r--r--plugins/jetpack/_inc/spin.js301
-rw-r--r--plugins/jetpack/class.jetpack-ixr-client.php2
-rw-r--r--plugins/jetpack/class.jetpack-post-images.php440
-rw-r--r--plugins/jetpack/class.jetpack-signature.php24
-rw-r--r--plugins/jetpack/class.jetpack-user-agent.php1331
-rw-r--r--plugins/jetpack/class.jetpack-xmlrpc-server.php225
-rw-r--r--plugins/jetpack/class.json-api-endpoints.php3912
-rw-r--r--plugins/jetpack/class.json-api.php443
-rw-r--r--plugins/jetpack/class.photon.php554
-rw-r--r--plugins/jetpack/functions.compat.php15
-rw-r--r--plugins/jetpack/functions.gallery.php50
-rw-r--r--plugins/jetpack/functions.opengraph.php158
-rw-r--r--plugins/jetpack/functions.photon.php160
-rw-r--r--plugins/jetpack/jetpack.php2107
-rw-r--r--plugins/jetpack/languages/jetpack-ar.mobin0 -> 14004 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-az.mobin2398 -> 2886 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-bs_BA.mobin59865 -> 76528 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-ca.mobin52959 -> 76602 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-cs_CZ.mobin5260 -> 8242 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-da_DK.mobin48806 -> 44830 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-de_DE.mobin43096 -> 117625 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-el.mobin0 -> 8337 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-es_ES.mobin45191 -> 49121 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-fa_IR.mobin32814 -> 47862 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-fi.mobin21934 -> 27526 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-fr_FR.mobin69552 -> 113684 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-gl_ES.mobin30784 -> 33955 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-he_IL.mobin62301 -> 75590 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-hr.mobin31130 -> 35895 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-hu_HU.mobin30043 -> 77710 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-id_ID.mobin49894 -> 52347 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-it_IT.mobin33628 -> 50000 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-ja.mobin67264 -> 116549 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-ko_KR.mobin0 -> 110462 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-lt_LT.mobin0 -> 12440 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-mk_MK.mobin22392 -> 23594 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-my_MM.mobin5741 -> 11071 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-nb_NO.mobin64081 -> 88203 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-nl_NL.mobin32682 -> 38043 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-nn_NO.mobin9040 -> 14701 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-pl_PL.mobin5948 -> 11997 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-pt_BR.mobin62629 -> 107473 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-pt_PT.mobin40066 -> 46165 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-ro_RO.mobin6675 -> 10652 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-ru_RU.mobin41905 -> 49300 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-sa_IN.mobin1008 -> 1006 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-sk_SK.mobin7567 -> 10517 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-sq.mobin56036 -> 112583 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-sr_RS.mobin36803 -> 44079 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-sv_SE.mobin19356 -> 24534 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-th.mobin0 -> 18421 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-tr_TR.mobin23475 -> 35311 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-zh_CN.mobin0 -> 7637 bytes
-rw-r--r--plugins/jetpack/languages/jetpack-zh_TW.mobin0 -> 93742 bytes
-rw-r--r--plugins/jetpack/locales.php139
-rw-r--r--plugins/jetpack/modules/after-the-deadline.php2
-rw-r--r--plugins/jetpack/modules/after-the-deadline/config-options.php4
-rw-r--r--plugins/jetpack/modules/carousel/jetpack-carousel-ie8fix.css8
-rw-r--r--plugins/jetpack/modules/carousel/jetpack-carousel.css89
-rw-r--r--plugins/jetpack/modules/carousel/jetpack-carousel.js344
-rw-r--r--plugins/jetpack/modules/carousel/jetpack-carousel.php85
-rw-r--r--plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css1106
-rw-r--r--plugins/jetpack/modules/comments.php9
-rw-r--r--plugins/jetpack/modules/comments/base.php47
-rw-r--r--plugins/jetpack/modules/comments/comments.php134
-rw-r--r--plugins/jetpack/modules/contact-form/admin.php245
-rw-r--r--plugins/jetpack/modules/contact-form/css/grunion.css7
-rw-r--r--plugins/jetpack/modules/contact-form/grunion-contact-form.php1866
-rw-r--r--plugins/jetpack/modules/contact-form/images/grunion-menu-2x.pngbin541 -> 53439 bytes
-rw-r--r--plugins/jetpack/modules/contact-form/images/grunion-menu-hover-2x.pngbin697 -> 51427 bytes
-rw-r--r--plugins/jetpack/modules/contact-form/images/grunion-remove-field-2x.pngbin201 -> 47832 bytes
-rw-r--r--plugins/jetpack/modules/contact-form/images/grunion-remove-field-hover-2x.pngbin207 -> 47745 bytes
-rw-r--r--plugins/jetpack/modules/contact-form/js/grunion.js60
-rw-r--r--plugins/jetpack/modules/custom-css.php26
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php1241
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/class.csstidy_ctype.php46
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/class.csstidy_optimise.php936
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/class.csstidy_print.php408
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/cssparse.css118
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/cssparsed.css29
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/data-wp.inc.php75
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/data.inc.php661
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/lang.inc.php311
-rw-r--r--plugins/jetpack/modules/custom-css/csstidy/wordpress-standard.tpl10
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css.php1468
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/blank.css1
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/js/ace/ace.js11
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-css.js1
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/js/ace/readme.txt1
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/js/ace/theme-textmate.js1
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/js/ace/worker-css.js1
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/js/safecss-ace.js69
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/preprocessors.php57
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/preprocessors/lessc.inc.php3359
-rw-r--r--plugins/jetpack/modules/custom-css/custom-css/preprocessors/scss.inc.php3759
-rw-r--r--plugins/jetpack/modules/enhanced-distribution.php23
-rw-r--r--plugins/jetpack/modules/featured-content/featured-content.php454
-rw-r--r--plugins/jetpack/modules/gravatar-hovercards.php17
-rw-r--r--plugins/jetpack/modules/holiday-snow.php72
-rw-r--r--plugins/jetpack/modules/holiday-snow/snowstorm.js539
-rw-r--r--plugins/jetpack/modules/infinite-scroll.php196
-rw-r--r--plugins/jetpack/modules/infinite-scroll/infinity.css137
-rw-r--r--plugins/jetpack/modules/infinite-scroll/infinity.js490
-rw-r--r--plugins/jetpack/modules/infinite-scroll/infinity.php945
-rw-r--r--plugins/jetpack/modules/infinite-scroll/themes/twentyeleven.css45
-rw-r--r--plugins/jetpack/modules/infinite-scroll/themes/twentyeleven.php27
-rw-r--r--plugins/jetpack/modules/infinite-scroll/themes/twentyten.css25
-rw-r--r--plugins/jetpack/modules/infinite-scroll/themes/twentyten.php48
-rw-r--r--plugins/jetpack/modules/infinite-scroll/themes/twentytwelve.css33
-rw-r--r--plugins/jetpack/modules/infinite-scroll/themes/twentytwelve.php46
-rw-r--r--plugins/jetpack/modules/json-api.php19
-rw-r--r--plugins/jetpack/modules/latex.php6
-rw-r--r--plugins/jetpack/modules/likes.php970
-rw-r--r--plugins/jetpack/modules/likes/style.css189
-rw-r--r--plugins/jetpack/modules/minileven.php108
-rw-r--r--plugins/jetpack/modules/minileven/images/wp-app-devices.pngbin0 -> 1865 bytes
-rw-r--r--plugins/jetpack/modules/minileven/minileven.php313
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/comments.php52
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/content-gallery.php78
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/content.php60
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/footer.php36
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/functions.php152
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/header.php49
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/image.php98
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/inc/custom-header.php101
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/inc/template-tags.php99
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/inc/tweaks.php94
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/index.php73
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/js/small-menu.js41
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/page.php42
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/rtl.css582
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/screenshot.pngbin0 -> 59059 bytes
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/searchform.php12
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/sidebar.php12
-rw-r--r--plugins/jetpack/modules/minileven/theme/pub/minileven/style.css1437
-rw-r--r--plugins/jetpack/modules/mobile-push.php11
-rw-r--r--plugins/jetpack/modules/module-extras.php58
-rw-r--r--plugins/jetpack/modules/module-info.php347
-rw-r--r--plugins/jetpack/modules/notes.php195
-rw-r--r--plugins/jetpack/modules/photon.php9
-rw-r--r--plugins/jetpack/modules/photon/photon.js42
-rw-r--r--plugins/jetpack/modules/post-by-email.php240
-rw-r--r--plugins/jetpack/modules/post-by-email/post-by-email.css6
-rw-r--r--plugins/jetpack/modules/post-by-email/post-by-email.js129
-rw-r--r--plugins/jetpack/modules/publicize.php283
-rw-r--r--plugins/jetpack/modules/publicize/assets/connected.gifbin0 -> 1681 bytes
-rw-r--r--plugins/jetpack/modules/publicize/assets/facebook-logo.pngbin0 -> 37624 bytes
-rw-r--r--plugins/jetpack/modules/publicize/assets/linkedin-logo.pngbin0 -> 6882 bytes
-rw-r--r--plugins/jetpack/modules/publicize/assets/publicize.css175
-rw-r--r--plugins/jetpack/modules/publicize/assets/publicize.js108
-rw-r--r--plugins/jetpack/modules/publicize/assets/rtl/publicize-rtl.css177
-rw-r--r--plugins/jetpack/modules/publicize/assets/spinner.gifbin0 -> 457 bytes
-rw-r--r--plugins/jetpack/modules/publicize/assets/tumblr-logo.pngbin0 -> 9001 bytes
-rw-r--r--plugins/jetpack/modules/publicize/assets/twitter-logo.pngbin0 -> 4623 bytes
-rw-r--r--plugins/jetpack/modules/publicize/assets/yahoo-logo.pngbin0 -> 9675 bytes
-rw-r--r--plugins/jetpack/modules/publicize/publicize-jetpack.php578
-rw-r--r--plugins/jetpack/modules/publicize/publicize.php328
-rw-r--r--plugins/jetpack/modules/publicize/ui.php545
-rw-r--r--plugins/jetpack/modules/sharedaddy.php2
-rw-r--r--plugins/jetpack/modules/sharedaddy/admin-sharing.css140
-rw-r--r--plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.pngbin0 -> 671 bytes
-rw-r--r--plugins/jetpack/modules/sharedaddy/images/icon-facebook.pngbin0 -> 887 bytes
-rw-r--r--plugins/jetpack/modules/sharedaddy/images/icon-twitter-2x.pngbin0 -> 1451 bytes
-rw-r--r--plugins/jetpack/modules/sharedaddy/images/icon-twitter.pngbin0 -> 523 bytes
-rw-r--r--plugins/jetpack/modules/sharedaddy/images/icon-wordpress-2x.pngbin0 -> 657 bytes
-rw-r--r--plugins/jetpack/modules/sharedaddy/images/icon-wordpress.pngbin0 -> 775 bytes
-rw-r--r--plugins/jetpack/modules/sharedaddy/sharedaddy.php57
-rw-r--r--plugins/jetpack/modules/sharedaddy/sharing-service.php217
-rw-r--r--plugins/jetpack/modules/sharedaddy/sharing-sources.php566
-rw-r--r--plugins/jetpack/modules/sharedaddy/sharing.css142
-rw-r--r--plugins/jetpack/modules/sharedaddy/sharing.js123
-rw-r--r--plugins/jetpack/modules/sharedaddy/sharing.php128
-rw-r--r--plugins/jetpack/modules/shortcodes/audio.php45
-rw-r--r--plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css131
-rw-r--r--plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css129
-rw-r--r--plugins/jetpack/modules/shortcodes/googlemaps.php2
-rw-r--r--plugins/jetpack/modules/shortcodes/img/slideshow-controls-2x.pngbin0 -> 1944 bytes
-rw-r--r--plugins/jetpack/modules/shortcodes/img/slideshow-controls.pngbin0 -> 1009 bytes
-rw-r--r--plugins/jetpack/modules/shortcodes/img/slideshow-loader.gifbin0 -> 13545 bytes
-rw-r--r--plugins/jetpack/modules/shortcodes/js/audio-shortcode.js154
-rw-r--r--plugins/jetpack/modules/shortcodes/js/jquery.cycle.js1551
-rw-r--r--plugins/jetpack/modules/shortcodes/js/slideshow-shortcode.js187
-rw-r--r--plugins/jetpack/modules/shortcodes/polldaddy.php6
-rw-r--r--plugins/jetpack/modules/shortcodes/slideshow.php208
-rw-r--r--plugins/jetpack/modules/shortcodes/soundcloud.php246
-rw-r--r--plugins/jetpack/modules/shortcodes/ted.php68
-rw-r--r--plugins/jetpack/modules/shortcodes/videopress.php51
-rw-r--r--plugins/jetpack/modules/shortcodes/vimeo.php20
-rw-r--r--plugins/jetpack/modules/shortcodes/youtube.php10
-rw-r--r--plugins/jetpack/modules/stats.php172
-rw-r--r--plugins/jetpack/modules/subscriptions.php289
-rw-r--r--plugins/jetpack/modules/tiled-gallery.php25
-rw-r--r--plugins/jetpack/modules/tiled-gallery/math/class-constrained-array-rounding.php75
-rw-r--r--plugins/jetpack/modules/tiled-gallery/tiled-gallery.php588
-rw-r--r--plugins/jetpack/modules/tiled-gallery/tiled-gallery/rtl/tiled-gallery-rtl.css88
-rw-r--r--plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.css85
-rw-r--r--plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.js150
-rw-r--r--plugins/jetpack/modules/widgets.php21
-rw-r--r--plugins/jetpack/modules/widgets/facebook-likebox.php57
-rw-r--r--plugins/jetpack/modules/widgets/gravatar-profile.css15
-rw-r--r--plugins/jetpack/modules/widgets/gravatar-profile.php128
-rw-r--r--plugins/jetpack/modules/widgets/image-widget.php2
-rw-r--r--plugins/jetpack/modules/widgets/readmill.php138
-rw-r--r--plugins/jetpack/modules/widgets/top-posts.php295
-rw-r--r--plugins/jetpack/modules/widgets/twitter.php407
-rw-r--r--plugins/jetpack/modules/widgets/widget-grid-and-list.css110
-rw-r--r--plugins/jetpack/modules/widgets/widgets.css13
-rw-r--r--plugins/jetpack/readme.txt251
-rw-r--r--plugins/openid/admin_panels.php3
-rw-r--r--plugins/openid/common.php8
-rw-r--r--plugins/openid/consumer.php6
-rw-r--r--plugins/openid/lib/Auth/OpenID.php563
-rw-r--r--plugins/openid/lib/Auth/OpenID/AX.php1022
-rw-r--r--plugins/openid/lib/Auth/OpenID/Association.php610
-rw-r--r--plugins/openid/lib/Auth/OpenID/BigMath.php451
-rw-r--r--plugins/openid/lib/Auth/OpenID/Consumer.php2236
-rw-r--r--plugins/openid/lib/Auth/OpenID/CryptUtil.php122
-rw-r--r--plugins/openid/lib/Auth/OpenID/DatabaseConnection.php130
-rw-r--r--plugins/openid/lib/Auth/OpenID/DiffieHellman.php113
-rw-r--r--plugins/openid/lib/Auth/OpenID/Discover.php606
-rw-r--r--plugins/openid/lib/Auth/OpenID/DumbStore.php99
-rw-r--r--plugins/openid/lib/Auth/OpenID/Extension.php61
-rw-r--r--plugins/openid/lib/Auth/OpenID/FileStore.php618
-rw-r--r--plugins/openid/lib/Auth/OpenID/HMAC.php105
-rw-r--r--plugins/openid/lib/Auth/OpenID/Interface.php196
-rw-r--r--plugins/openid/lib/Auth/OpenID/KVForm.php111
-rw-r--r--plugins/openid/lib/Auth/OpenID/MDB2Store.php413
-rw-r--r--plugins/openid/lib/Auth/OpenID/MemcachedStore.php207
-rw-r--r--plugins/openid/lib/Auth/OpenID/Message.php920
-rw-r--r--plugins/openid/lib/Auth/OpenID/MySQLStore.php77
-rw-r--r--plugins/openid/lib/Auth/OpenID/Nonce.php108
-rw-r--r--plugins/openid/lib/Auth/OpenID/PAPE.php300
-rw-r--r--plugins/openid/lib/Auth/OpenID/Parse.php381
-rw-r--r--plugins/openid/lib/Auth/OpenID/PostgreSQLStore.php112
-rw-r--r--plugins/openid/lib/Auth/OpenID/SQLStore.php557
-rw-r--r--plugins/openid/lib/Auth/OpenID/SQLiteStore.php70
-rw-r--r--plugins/openid/lib/Auth/OpenID/SReg.php521
-rw-r--r--plugins/openid/lib/Auth/OpenID/Server.php1765
-rw-r--r--plugins/openid/lib/Auth/OpenID/ServerRequest.php36
-rw-r--r--plugins/openid/lib/Auth/OpenID/TrustRoot.php461
-rw-r--r--plugins/openid/lib/Auth/OpenID/URINorm.php249
-rw-r--r--plugins/openid/lib/Auth/Yadis/HTTPFetcher.php174
-rw-r--r--plugins/openid/lib/Auth/Yadis/Manager.php523
-rw-r--r--plugins/openid/lib/Auth/Yadis/Misc.php58
-rw-r--r--plugins/openid/lib/Auth/Yadis/ParanoidHTTPFetcher.php273
-rw-r--r--plugins/openid/lib/Auth/Yadis/ParseHTML.php258
-rw-r--r--plugins/openid/lib/Auth/Yadis/PlainHTTPFetcher.php248
-rw-r--r--plugins/openid/lib/Auth/Yadis/XML.php352
-rw-r--r--plugins/openid/lib/Auth/Yadis/XRDS.php478
-rw-r--r--plugins/openid/lib/Auth/Yadis/XRI.php234
-rw-r--r--plugins/openid/lib/Auth/Yadis/XRIRes.php72
-rw-r--r--plugins/openid/lib/Auth/Yadis/Yadis.php382
-rw-r--r--plugins/openid/openid.php25
-rw-r--r--plugins/openid/readme.txt9
-rw-r--r--plugins/openid/server.php21
-rw-r--r--plugins/wp-syntax/README.txt89
-rw-r--r--plugins/wp-syntax/css/wp-syntax.css98
-rw-r--r--plugins/wp-syntax/geshi/geshi.php9534
-rw-r--r--plugins/wp-syntax/geshi/geshi/4cs.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/6502acme.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/6502kickass.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/6502tasm.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/68000devpac.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/abap.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/actionscript.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/actionscript3.php6
-rw-r--r--plugins/wp-syntax/geshi/geshi/ada.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/algol68.php287
-rw-r--r--plugins/wp-syntax/geshi/geshi/apache.php5
-rw-r--r--plugins/wp-syntax/geshi/geshi/applescript.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/apt_sources.php12
-rw-r--r--plugins/wp-syntax/geshi/geshi/arm.php3318
-rw-r--r--plugins/wp-syntax/geshi/geshi/asm.php536
-rw-r--r--plugins/wp-syntax/geshi/geshi/asp.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/asymptote.php194
-rw-r--r--plugins/wp-syntax/geshi/geshi/autoconf.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/autohotkey.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/autoit.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/avisynth.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/awk.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/bascomavr.php185
-rw-r--r--plugins/wp-syntax/geshi/geshi/bash.php141
-rw-r--r--plugins/wp-syntax/geshi/geshi/basic4gl.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/bf.php15
-rw-r--r--plugins/wp-syntax/geshi/geshi/bibtex.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/blitzbasic.php4
-rw-r--r--plugins/wp-syntax/geshi/geshi/bnf.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/boo.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/c.php85
-rw-r--r--plugins/wp-syntax/geshi/geshi/c_loadrunner.php323
-rw-r--r--plugins/wp-syntax/geshi/geshi/c_mac.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/caddcl.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/cadlisp.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/cfdg.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/cfm.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/chaiscript.php4
-rw-r--r--plugins/wp-syntax/geshi/geshi/cil.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/clojure.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/cmake.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/cobol.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/coffeescript.php146
-rw-r--r--plugins/wp-syntax/geshi/geshi/cpp-qt.php8
-rw-r--r--plugins/wp-syntax/geshi/geshi/cpp.php4
-rw-r--r--plugins/wp-syntax/geshi/geshi/csharp.php19
-rw-r--r--plugins/wp-syntax/geshi/geshi/css.php22
-rw-r--r--plugins/wp-syntax/geshi/geshi/cuesheet.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/d.php68
-rw-r--r--plugins/wp-syntax/geshi/geshi/dcl.php192
-rw-r--r--plugins/wp-syntax/geshi/geshi/dcpu16.php131
-rw-r--r--plugins/wp-syntax/geshi/geshi/dcs.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/delphi.php46
-rw-r--r--plugins/wp-syntax/geshi/geshi/diff.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/div.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/dos.php8
-rw-r--r--plugins/wp-syntax/geshi/geshi/dot.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/e.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/ecmascript.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/eiffel.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/email.php26
-rw-r--r--plugins/wp-syntax/geshi/geshi/epc.php154
-rw-r--r--plugins/wp-syntax/geshi/geshi/erlang.php10
-rw-r--r--plugins/wp-syntax/geshi/geshi/euphoria.php140
-rw-r--r--plugins/wp-syntax/geshi/geshi/f1.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/falcon.php218
-rw-r--r--plugins/wp-syntax/geshi/geshi/fo.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/fortran.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/freebasic.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/freeswitch.php168
-rw-r--r--plugins/wp-syntax/geshi/geshi/fsharp.php8
-rw-r--r--plugins/wp-syntax/geshi/geshi/gambas.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/gdb.php63
-rw-r--r--plugins/wp-syntax/geshi/geshi/genero.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/genie.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/gettext.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/glsl.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/gml.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/gnuplot.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/go.php47
-rw-r--r--plugins/wp-syntax/geshi/geshi/groovy.php18
-rw-r--r--plugins/wp-syntax/geshi/geshi/gwbasic.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/haskell.php8
-rw-r--r--plugins/wp-syntax/geshi/geshi/haxe.php161
-rw-r--r--plugins/wp-syntax/geshi/geshi/hicest.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/hq9plus.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/html4strict.php29
-rw-r--r--plugins/wp-syntax/geshi/geshi/html5.php212
-rw-r--r--plugins/wp-syntax/geshi/geshi/icon.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/idl.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/ini.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/inno.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/intercal.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/io.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/j.php73
-rw-r--r--plugins/wp-syntax/geshi/geshi/java.php4
-rw-r--r--plugins/wp-syntax/geshi/geshi/java5.php328
-rw-r--r--plugins/wp-syntax/geshi/geshi/javascript.php70
-rw-r--r--plugins/wp-syntax/geshi/geshi/jquery.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/kixtart.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/klonec.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/klonecpp.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/latex.php8
-rw-r--r--plugins/wp-syntax/geshi/geshi/lb.php16
-rw-r--r--plugins/wp-syntax/geshi/geshi/ldif.php116
-rw-r--r--plugins/wp-syntax/geshi/geshi/lisp.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/llvm.php385
-rw-r--r--plugins/wp-syntax/geshi/geshi/locobasic.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/logtalk.php35
-rw-r--r--plugins/wp-syntax/geshi/geshi/lolcode.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/lotusformulas.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/lotusscript.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/lscript.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/lsl2.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/lua.php62
-rw-r--r--plugins/wp-syntax/geshi/geshi/m68k.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/magiksf.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/make.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/mapbasic.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/matlab.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/mirc.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/mmix.php66
-rw-r--r--plugins/wp-syntax/geshi/geshi/modula2.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/modula3.php4
-rw-r--r--plugins/wp-syntax/geshi/geshi/mpasm.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/mxml.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/mysql.php34
-rw-r--r--plugins/wp-syntax/geshi/geshi/nagios.php225
-rw-r--r--plugins/wp-syntax/geshi/geshi/netrexx.php163
-rw-r--r--plugins/wp-syntax/geshi/geshi/newlisp.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/nsis.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/oberon2.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/objc.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/objeck.php10
-rw-r--r--plugins/wp-syntax/geshi/geshi/ocaml-brief.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/ocaml.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/octave.php515
-rw-r--r--plugins/wp-syntax/geshi/geshi/oobas.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/oorexx.php171
-rw-r--r--plugins/wp-syntax/geshi/geshi/oracle11.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/oracle8.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/oxygene.php6
-rw-r--r--plugins/wp-syntax/geshi/geshi/oz.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/parasail.php133
-rw-r--r--plugins/wp-syntax/geshi/geshi/parigp.php277
-rw-r--r--plugins/wp-syntax/geshi/geshi/pascal.php53
-rw-r--r--plugins/wp-syntax/geshi/geshi/pcre.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/per.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/perl.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/perl6.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/pf.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/php-brief.php4
-rw-r--r--plugins/wp-syntax/geshi/geshi/php.php21
-rw-r--r--plugins/wp-syntax/geshi/geshi/pic16.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/pike.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/pixelbender.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/pli.php200
-rw-r--r--plugins/wp-syntax/geshi/geshi/plsql.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/postgresql.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/povray.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/powerbuilder.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/powershell.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/proftpd.php374
-rw-r--r--plugins/wp-syntax/geshi/geshi/progress.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/prolog.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/properties.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/providex.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/purebasic.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/pycon.php64
-rw-r--r--plugins/wp-syntax/geshi/geshi/pys60.php273
-rw-r--r--plugins/wp-syntax/geshi/geshi/python.php17
-rw-r--r--plugins/wp-syntax/geshi/geshi/q.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/qbasic.php6
-rw-r--r--plugins/wp-syntax/geshi/geshi/rails.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/rebol.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/reg.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/rexx.php162
-rw-r--r--plugins/wp-syntax/geshi/geshi/robots.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/rpmspec.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/rsplus.php20
-rw-r--r--plugins/wp-syntax/geshi/geshi/ruby.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/sas.php6
-rw-r--r--plugins/wp-syntax/geshi/geshi/scala.php26
-rw-r--r--plugins/wp-syntax/geshi/geshi/scheme.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/scilab.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/sdlbasic.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/smalltalk.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/smarty.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/spark.php132
-rw-r--r--plugins/wp-syntax/geshi/geshi/sparql.php155
-rw-r--r--plugins/wp-syntax/geshi/geshi/sql.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/stonescript.php307
-rw-r--r--plugins/wp-syntax/geshi/geshi/systemverilog.php8
-rw-r--r--plugins/wp-syntax/geshi/geshi/tcl.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/teraterm.php147
-rw-r--r--plugins/wp-syntax/geshi/geshi/text.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/thinbasic.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/tsql.php6
-rw-r--r--plugins/wp-syntax/geshi/geshi/typoscript.php20
-rw-r--r--plugins/wp-syntax/geshi/geshi/unicon.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/upc.php270
-rw-r--r--plugins/wp-syntax/geshi/geshi/urbi.php200
-rw-r--r--plugins/wp-syntax/geshi/geshi/uscript.php299
-rw-r--r--plugins/wp-syntax/geshi/geshi/vala.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/vb.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/vbnet.php127
-rw-r--r--plugins/wp-syntax/geshi/geshi/vedit.php103
-rw-r--r--plugins/wp-syntax/geshi/geshi/verilog.php4
-rw-r--r--plugins/wp-syntax/geshi/geshi/vhdl.php105
-rw-r--r--plugins/wp-syntax/geshi/geshi/vim.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/visualfoxpro.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/visualprolog.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/whitespace.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/whois.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/winbatch.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/xbasic.php3
-rw-r--r--plugins/wp-syntax/geshi/geshi/xml.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/xorg_conf.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/xpp.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/yaml.php150
-rw-r--r--plugins/wp-syntax/geshi/geshi/z80.php2
-rw-r--r--plugins/wp-syntax/geshi/geshi/zxbasic.php2
-rw-r--r--plugins/wp-syntax/js/wp-syntax.js34
-rw-r--r--plugins/wp-syntax/wp-syntax.php563
506 files changed, 76912 insertions, 8864 deletions
diff --git a/plugins/akismet/.htaccess b/plugins/akismet/.htaccess
new file mode 100644
index 00000000..18eed640
--- /dev/null
+++ b/plugins/akismet/.htaccess
@@ -0,0 +1,6 @@
+Order Deny,Allow
+Deny from all
+
+<FilesMatch "^akismet\.(css|js)$">
+ Allow from all
+</FilesMatch> \ No newline at end of file
diff --git a/plugins/akismet/admin.php b/plugins/akismet/admin.php
index aa30cde7..9d7673f5 100644
--- a/plugins/akismet/admin.php
+++ b/plugins/akismet/admin.php
@@ -23,7 +23,6 @@ function akismet_admin_init() {
$hook = get_plugin_page_hook( 'akismet-stats-display', 'index.php' );
else
$hook = 'dashboard_page_akismet-stats-display';
- add_action('admin_head-'.$hook, 'akismet_stats_script');
add_meta_box('akismet-status', __('Comment History'), 'akismet_comment_status_meta_box', 'comment', 'normal');
}
add_action('admin_init', 'akismet_admin_init');
@@ -56,7 +55,7 @@ $akismet_nonce = 'akismet-update-key';
function akismet_plugin_action_links( $links, $file ) {
if ( $file == plugin_basename( dirname(__FILE__).'/akismet.php' ) ) {
- $links[] = '<a href="admin.php?page=akismet-key-config">'.__('Settings').'</a>';
+ $links[] = '<a href="' . admin_url( 'admin.php?page=akismet-key-config' ) . '">'.__( 'Settings' ).'</a>';
}
return $links;
@@ -240,23 +239,6 @@ function akismet_conf() {
<?php
}
-function akismet_stats_script() {
- ?>
-<script type="text/javascript">
-function resizeIframe() {
-
- document.getElementById('akismet-stats-frame').style.height = "2500px";
-
-};
-function resizeIframeInit() {
- document.getElementById('akismet-stats-frame').onload = resizeIframe;
- window.onresize = resizeIframe;
-}
-addLoadEvent(resizeIframeInit);
-</script><?php
-}
-
-
function akismet_stats_display() {
global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
$blog = urlencode( get_bloginfo('url') );
@@ -269,7 +251,7 @@ function akismet_stats_display() {
$url .= "?blog={$blog}&api_key=" . akismet_get_key();
?>
<div class="wrap">
- <iframe src="<?php echo $url; ?>" width="100%" height="100%" frameborder="0" id="akismet-stats-frame"></iframe>
+ <iframe src="<?php echo $url; ?>" width="100%" height="2500px" frameborder="0" id="akismet-stats-frame"></iframe>
</div>
<?php
}
@@ -329,7 +311,7 @@ function akismet_admin_warnings() {
function akismet_warning() {
global $wpdb;
akismet_fix_scheduled_recheck();
- $waiting = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->commentmeta WHERE meta_key = 'akismet_error'" ) );
+ $waiting = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->commentmeta WHERE meta_key = 'akismet_error'" );
$next_check = wp_next_scheduled('akismet_schedule_cron_recheck');
if ( $waiting > 0 && $next_check > time() )
echo "
@@ -741,7 +723,8 @@ function akismet_recheck_queue() {
delete_comment_meta( $c['comment_ID'], 'akismet_rechecking' );
}
- wp_safe_redirect( $_SERVER['HTTP_REFERER'] );
+ $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : admin_url( 'edit-comments.php' );
+ wp_safe_redirect( $redirect_to );
exit;
}
diff --git a/plugins/akismet/akismet.js b/plugins/akismet/akismet.js
index 839fe6bc..8925c51f 100644
--- a/plugins/akismet/akismet.js
+++ b/plugins/akismet/akismet.js
@@ -74,6 +74,7 @@ jQuery(document).ready(function () {
return false;
});
jQuery('a[id^="author_comment_url"]').mouseover(function () {
+ var wpcomProtocol = ( 'https:' === location.protocol ) ? 'https://' : 'http://';
// Need to determine size of author column
var thisParentWidth = jQuery(this).parent().width();
// It changes based on if there is a gravatar present
@@ -83,12 +84,12 @@ jQuery(document).ready(function () {
jQuery('.widefat td').css('overflow', 'visible');
jQuery(this).css('position', 'relative');
var thisHref = jQuery.URLEncode(jQuery(this).attr('href'));
- jQuery(this).append('<div class="mShot mshot-container" style="left: '+thisParentWidth+'"><div class="mshot-arrow"></div><img src="http://s.wordpress.com/mshots/v1/'+thisHref+'?w=450" width="450" class="mshot-image_'+thisId+'" style="margin: 0;" /></div>');
+ jQuery(this).append('<div class="mShot mshot-container" style="left: '+thisParentWidth+'"><div class="mshot-arrow"></div><img src="'+wpcomProtocol+'s0.wordpress.com/mshots/v1/'+thisHref+'?w=450" width="450" class="mshot-image_'+thisId+'" style="margin: 0;" /></div>');
setTimeout(function () {
- jQuery('.mshot-image_'+thisId).attr('src', 'http://s.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=2');
+ jQuery('.mshot-image_'+thisId).attr('src', wpcomProtocol+'s0.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=2');
}, 6000);
setTimeout(function () {
- jQuery('.mshot-image_'+thisId).attr('src', 'http://s.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=3');
+ jQuery('.mshot-image_'+thisId).attr('src', wpcomProtocol+'s0.wordpress.com/mshots/v1/'+thisHref+'?w=450&r=3');
}, 12000);
} else {
jQuery(this).find('.mShot').css('left', thisParentWidth).show();
@@ -106,7 +107,8 @@ jQuery.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a
});
// Preload mshot images after everything else has loaded
jQuery(window).load(function() {
+ var wpcomProtocol = ( 'https:' === location.protocol ) ? 'https://' : 'http://';
jQuery('a[id^="author_comment_url"]').each(function () {
- jQuery.get('http://s.wordpress.com/mshots/v1/'+jQuery.URLEncode(jQuery(this).attr('href'))+'?w=450');
+ jQuery.get(wpcomProtocol+'s0.wordpress.com/mshots/v1/'+jQuery.URLEncode(jQuery(this).attr('href'))+'?w=450');
});
-}); \ No newline at end of file
+});
diff --git a/plugins/akismet/akismet.php b/plugins/akismet/akismet.php
index 48fa3c3a..4c3aef71 100644
--- a/plugins/akismet/akismet.php
+++ b/plugins/akismet/akismet.php
@@ -5,8 +5,8 @@
/*
Plugin Name: Akismet
Plugin URI: http://akismet.com/?return=true
-Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from comment and trackback spam</strong>. It keeps your site protected from spam even while you sleep. To get started: 1) Click the "Activate" link to the left of this description, 2) <a href="http://akismet.com/get/?return=true">Sign up for an Akismet API key</a>, and 3) Go to your <a href="admin.php?page=akismet-key-config">Akismet configuration</a> page, and save your API key.
-Version: 2.5.6
+Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from comment and trackback spam</strong>. It keeps your site protected from spam even while you sleep. To get started: 1) Click the "Activate" link to the left of this description, 2) <a href="http://akismet.com/get/?return=true">Sign up for an Akismet API key</a>, and 3) Go to your Akismet configuration page, and save your API key.
+Version: 2.5.7
Author: Automattic
Author URI: http://automattic.com/wordpress-plugins/
License: GPLv2 or later
@@ -28,7 +28,13 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-define('AKISMET_VERSION', '2.5.6');
+// Make sure we don't expose any info if called directly
+if ( !function_exists( 'add_action' ) ) {
+ echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
+ exit;
+}
+
+define('AKISMET_VERSION', '2.5.7');
define('AKISMET_PLUGIN_URL', plugin_dir_url( __FILE__ ));
/** If you hardcode a WP.com API key here, all key config screens will be hidden */
@@ -38,12 +44,6 @@ else
$wpcom_api_key = '';
include '/var/www/blogs.gentoo.org/secrets/wp-apikey.php';
-// Make sure we don't expose any info if called directly
-if ( !function_exists( 'add_action' ) ) {
- echo "Hi there! I'm just a plugin, not much I can do when called directly.";
- exit;
-}
-
if ( isset($wp_db_version) && $wp_db_version <= 9872 )
include_once dirname( __FILE__ ) . '/legacy.php';
@@ -111,7 +111,7 @@ function akismet_test_mode() {
}
// return a comma-separated list of role names for the given user
-function akismet_get_user_roles($user_id ) {
+function akismet_get_user_roles( $user_id ) {
$roles = false;
if ( !class_exists('WP_User') )
@@ -278,10 +278,13 @@ function akismet_auto_check_update_meta( $id, $comment ) {
if ( !function_exists('add_comment_meta') )
return false;
+ if ( !isset( $akismet_last_comment['comment_author_email'] ) )
+ $akismet_last_comment['comment_author_email'] = '';
+
// wp_insert_comment() might be called in other contexts, so make sure this is the same comment
// as was checked by akismet_auto_check_comment
if ( is_object($comment) && !empty($akismet_last_comment) && is_array($akismet_last_comment) ) {
- if ( intval($akismet_last_comment['comment_post_ID']) == intval($comment->comment_post_ID)
+ if ( isset($akismet_last_comment['comment_post_ID']) && intval($akismet_last_comment['comment_post_ID']) == intval($comment->comment_post_ID)
&& $akismet_last_comment['comment_author'] == $comment->comment_author
&& $akismet_last_comment['comment_author_email'] == $comment->comment_author_email ) {
// normal result: true or false
@@ -320,15 +323,15 @@ function akismet_auto_check_comment( $commentdata ) {
$comment = $commentdata;
$comment['user_ip'] = $_SERVER['REMOTE_ADDR'];
- $comment['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
- $comment['referrer'] = $_SERVER['HTTP_REFERER'];
+ $comment['user_agent'] = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
+ $comment['referrer'] = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
$comment['blog'] = get_option('home');
$comment['blog_lang'] = get_locale();
$comment['blog_charset'] = get_option('blog_charset');
$comment['permalink'] = get_permalink($comment['comment_post_ID']);
if ( !empty( $comment['user_ID'] ) ) {
- $comment['user_role'] = akismet_get_user_roles($comment['user_ID']);
+ $comment['user_role'] = akismet_get_user_roles( $comment['user_ID'] );
}
$akismet_nonce_option = apply_filters( 'akismet_comment_nonce', get_option( 'akismet_comment_nonce' ) );
@@ -371,6 +374,7 @@ function akismet_auto_check_comment( $commentdata ) {
$commentdata['comment_as_submitted'] = $comment;
$response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
+ do_action( 'akismet_comment_check_response', $response );
akismet_update_alert( $response );
$commentdata['akismet_result'] = $response[1];
if ( 'true' == $response[1] ) {
@@ -387,7 +391,8 @@ function akismet_auto_check_comment( $commentdata ) {
// akismet_result_spam() won't be called so bump the counter here
if ( $incr = apply_filters('akismet_spam_count_incr', 1) )
update_option( 'akismet_spam_count', get_option('akismet_spam_count') + $incr );
- wp_safe_redirect( $_SERVER['HTTP_REFERER'] );
+ $redirect_to = isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : get_permalink( $post );
+ wp_safe_redirect( $redirect_to );
die();
}
}
@@ -499,7 +504,7 @@ function akismet_check_db_comment( $id, $recheck_reason = 'recheck_queue' ) {
$query_string .= $key . '=' . urlencode( stripslashes($data) ) . '&';
$response = akismet_http_post($query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port);
- return $response[1];
+ return ( is_array( $response ) && isset( $response[1] ) ) ? $response[1] : false;
}
function akismet_cron_recheck() {
@@ -566,7 +571,7 @@ function akismet_cron_recheck() {
delete_comment_meta( $comment_id, 'akismet_rechecking' );
}
- $remaining = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->commentmeta WHERE meta_key = 'akismet_error'" ) );
+ $remaining = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->commentmeta WHERE meta_key = 'akismet_error'" );
if ( $remaining && !wp_next_scheduled('akismet_schedule_cron_recheck') ) {
wp_schedule_single_event( time() + 1200, 'akismet_schedule_cron_recheck' );
}
diff --git a/plugins/akismet/readme.txt b/plugins/akismet/readme.txt
index 227fad95..4d61fe9d 100644
--- a/plugins/akismet/readme.txt
+++ b/plugins/akismet/readme.txt
@@ -2,8 +2,8 @@
Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, automattic
Tags: akismet, comments, spam
Requires at least: 3.0
-Tested up to: 3.4
-Stable tag: 2.5.6
+Tested up to: 3.5
+Stable tag: 2.5.7
License: GPLv2 or later
Akismet checks your comments against the Akismet web service to see if they look like spam or not.
@@ -31,6 +31,15 @@ Upload the Akismet plugin to your blog, Activate it, then enter your [Akismet.co
== Changelog ==
+= 2.5.7 =
+* FireFox Stats iframe preview bug
+* Fix mshots preview when using https
+* Add .htaccess to block direct access to files
+* Prevent some PHP notices
+* Fix Check For Spam return location when referrer is empty
+* Fix Settings links for network admins
+* Fix prepare() warnings in WP 3.5
+
= 2.5.6 =
* Prevent retry scheduling problems on sites where wp_cron is misbehaving
* Preload mshot previews
diff --git a/plugins/jetpack/_inc/gallery-settings.js b/plugins/jetpack/_inc/gallery-settings.js
new file mode 100644
index 00000000..0ce38f0b
--- /dev/null
+++ b/plugins/jetpack/_inc/gallery-settings.js
@@ -0,0 +1,19 @@
+/**
+ * Jetpack Gallery Settings
+ */
+(function($) {
+ var media = wp.media;
+
+ // Wrap the render() function to append controls.
+ media.view.Settings.Gallery = media.view.Settings.Gallery.extend({
+ render: function() {
+ media.view.Settings.prototype.render.apply( this, arguments );
+
+ // Append the type template and update the settings.
+ this.$el.append( media.template( 'jetpack-gallery-settings' ) );
+ media.gallery.defaults.type = 'default'; // lil hack that lets media know there's a type attribute.
+ this.update.apply( this, ['type'] );
+ return this;
+ }
+ });
+})(jQuery); \ No newline at end of file
diff --git a/plugins/jetpack/_inc/images/module-icons-sprite-2x.png b/plugins/jetpack/_inc/images/module-icons-sprite-2x.png
index db87b2d5..11f42042 100644
--- a/plugins/jetpack/_inc/images/module-icons-sprite-2x.png
+++ b/plugins/jetpack/_inc/images/module-icons-sprite-2x.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/module-icons-sprite.png b/plugins/jetpack/_inc/images/module-icons-sprite.png
index 44de3b9e..c6979f67 100644
--- a/plugins/jetpack/_inc/images/module-icons-sprite.png
+++ b/plugins/jetpack/_inc/images/module-icons-sprite.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/publicize.png b/plugins/jetpack/_inc/images/publicize.png
new file mode 100644
index 00000000..428b886c
--- /dev/null
+++ b/plugins/jetpack/_inc/images/publicize.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/carousel.png b/plugins/jetpack/_inc/images/screenshots/carousel.png
new file mode 100644
index 00000000..5bcc94cd
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/carousel.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/custom-css.png b/plugins/jetpack/_inc/images/screenshots/custom-css.png
new file mode 100644
index 00000000..4be5cb22
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/custom-css.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/likes.png b/plugins/jetpack/_inc/images/screenshots/likes.png
new file mode 100644
index 00000000..1c7670a3
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/likes.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpg b/plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpg
new file mode 100644
index 00000000..94ca6dd6
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpg
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/mobile-theme.png b/plugins/jetpack/_inc/images/screenshots/mobile-theme.png
new file mode 100644
index 00000000..88bad2d6
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/mobile-theme.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/notes.png b/plugins/jetpack/_inc/images/screenshots/notes.png
new file mode 100644
index 00000000..4506db17
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/notes.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/post-by-email.png b/plugins/jetpack/_inc/images/screenshots/post-by-email.png
new file mode 100644
index 00000000..b114088c
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/post-by-email.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/publicize.png b/plugins/jetpack/_inc/images/screenshots/publicize.png
new file mode 100644
index 00000000..428b886c
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/publicize.png
Binary files differ
diff --git a/plugins/jetpack/_inc/images/screenshots/tiled-gallery.png b/plugins/jetpack/_inc/images/screenshots/tiled-gallery.png
new file mode 100644
index 00000000..8168590d
--- /dev/null
+++ b/plugins/jetpack/_inc/images/screenshots/tiled-gallery.png
Binary files differ
diff --git a/plugins/jetpack/_inc/jetpack.css b/plugins/jetpack/_inc/jetpack.css
index 0b6c340e..b684f7c7 100644
--- a/plugins/jetpack/_inc/jetpack.css
+++ b/plugins/jetpack/_inc/jetpack.css
@@ -21,20 +21,27 @@
height: 70px;
}
- #jp-header #jp-clouds #jp-disconnect {
+
+ #jp-header #jp-clouds #jp-disconnectors {
font-size: 12px;
color: #fff;
float: right;
- margin: -35px 25px 0 0;
- text-align: right;
+ margin-top: -35px;
+ text-align: left;
+ position: relative;
+ left: -45px;
}
- #jp-header #jp-clouds #jp-disconnect a {
+ #jp-header #jp-clouds .jp-disconnect a {
background: #8caa46 url( images/status-light.png ) 3px 85% no-repeat;
display: inline-block;
- padding: 4px 10px 3px 30px;
+ position: relative;
+ width: 100%;
+ height: 1.7em;
+ overflow: hidden;
+ padding: 4px 0 3px 30px;
+ margin: 0 -20px 3px 0;
color: #fff;
- text-align: center;
text-decoration: none;
border: 1px solid #7a943d;
-moz-border-radius: 5px;
@@ -45,14 +52,23 @@
box-shadow: inset 0 0 2px rgba( 255, 255, 255, 0.4 );
text-shadow: 0px -1px 0px rgba( 0,0,0,0.3 );
}
- #jp-header #jp-clouds #jp-disconnect a:hover {
- background: #8caa46 url( images/status-light.png ) 3px 5% no-repeat;
+ #jp-header #jp-clouds .jp-disconnect a:hover {
+ background: #8caa46 url( images/status-light.png ) 3px -2% no-repeat;
background-color: #839f40;
border-color: #6a8037;
}
- #jp-header #jp-clouds #jp-disconnect span { display: none; }
-
+ #jp-header #jp-clouds .jp-disconnect div {
+ position: relative;
+ line-height: 1.7em;
+ height: 1.7em;
+ }
+
+ #jp-header #jp-clouds .jp-disconnect a:hover div,
+ #jp-header #jp-clouds .jp-disconnect a.clicked div {
+ top: -1.7em;
+ }
+
/* Retina Header Clouds & Status Light */
@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) {
#jp-header #jp-clouds {
@@ -63,18 +79,18 @@
background: transparent url( images/header-clouds-small-2x.png ) -120px 100% repeat-x;
background-size:980px 140px;
}
-
- #jp-header #jp-clouds #jp-disconnect a {
+
+ #jp-header #jp-clouds .jp-disconnect a {
background: #8caa46 url( images/status-light-2x.png ) 3px 85% no-repeat;
background-size:25px 57px;
}
- #jp-header #jp-clouds #jp-disconnect a:hover {
- background: #8caa46 url( images/status-light-2x.png ) 3px 5% no-repeat;
+ #jp-header #jp-clouds .jp-disconnect a:hover {
+ background: #8caa46 url( images/status-light-2x.png ) 3px -2% no-repeat;
background-size:25px 57px;
}
}
-
-
+
+
#jp-header h3 {
position: relative;
background: transparent url( images/logo.png ) top left no-repeat;
@@ -93,7 +109,7 @@
height: 120px;
top: -35px;
}
-
+
/* Retina Logo */
@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) {
#jp-header h3 {
@@ -105,9 +121,9 @@
background-size:150px 120px;
}
}
-
-
-
+
+
+
#jp-header p {
position: absolute;
left: 390px;
@@ -237,11 +253,11 @@
color: #fff;
text-decoration: underline;
}
-
+
.jetpack-message .squeezer a:hover {
color: #f0a000;
}
-
+
.jetpack-message code, .jetpack-err p {
background: rgba( 0,0,0,0.2 );
font-size: 14px;
@@ -309,7 +325,7 @@
-moz-box-shadow: inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
box-shadow: inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
}
-
+
/* Retina moreinfo bg clouds */
@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) {
.more-info {
@@ -317,8 +333,8 @@
background-size:980px 140px;
}
}
-
-
+
+
.more-info h4 {
padding: 0;
background: none;
@@ -340,7 +356,7 @@
left: 0;
background: url( images/arrow.png ) top left no-repeat;
}
-
+
/* Retina module more info arrow */
@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) {
.more-info .arrow {
@@ -534,13 +550,13 @@ p.jp-help {
border-bottom-left-radius: 3px;
background-repeat: no-repeat;
background-image: url( images/module-icons-sprite.png );
+ background-size: 2555px 50px; /* remember to update this every time a new module is added! */
}
@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) {
.jetpack-module div.module-image {
background-image: url( images/module-icons-sprite-2x.png );
- background-size: 1450px 50px;
}
}
@@ -586,6 +602,40 @@ p.jp-help {
#carousel.jetpack-module div.module-image {
background-position: -1325px 5px;
}
+ #custom-css.jetpack-module div.module-image {
+ background-position: -1459px 5px;
+ }
+ #minileven.jetpack-module div.module-image {
+ background-position: -1570px 5px;
+ }
+ #notes.jetpack-module div.module-image {
+ background-position: -1806px 5px;
+ }
+ #json-api.jetpack-module div.module-image {
+ background-position: -1689px 5px;
+ }
+ #mobile-push.jetpack-module div.module-image {
+ background-position: -1925px 5px;
+ }
+ #publicize.jetpack-module div.module-image {
+ background-position: -2136px 5px;
+ }
+ #post-by-email.jetpack-module div.module-image {
+ background-position: -2025px 5px;
+ }
+ #infinite-scroll.jetpack-module div.module-image {
+ background-position: -2230px 5px;
+ }
+ #photon.jetpack-module div.module-image {
+ background-position: -2320px 5px;
+ }
+ #tiled-gallery.jetpack-module div.module-image {
+ background-position: -2400px 5px;
+ }
+
+ #likes.jetpack-module div.module-image {
+ background-position: -2471px 5px;
+ }
.jetpack-module div.module-image p {
background-color: #b4d278;
@@ -725,7 +775,7 @@ p.jp-help {
margin-right: 15px;
box-shadow: none;
}
-
+
@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) {
.placeholder h3 {
background: transparent url(images/icon-comingsoon-2x.png) top center no-repeat;
@@ -822,34 +872,10 @@ p#news-sub {
margin-top: 15px;
}
-#jetpack-settings .button, #jetpack-settings .button-primary {
- -moz-border-radius: 5px !important;
- -webkit-border-radius: 5px !important;
- border-radius: 5px !important;
- padding: 5px 10px !important;
- -moz-box-shadow: inset 0 0 2px #fff, 0 0 3px rgba(0,0,0,0.1);
- -webkit-box-shadow: inset 0 0 2px #fff, 0 0 3px rgba(0,0,0,0.1);
- box-shadow: inset 0 0 2px #fff, 0 0 3px rgba(0,0,0,0.1);
-}
-
#jetpack-settings .button-primary {
- color: #bceaff !important;
-}
-
-#jetpack-settings .button-primary:hover {
color: #fff !important;
}
-#jetpack-settings .button:hover {
- color: #298cba !important;
- border-color: #69acce !important;
- -moz-box-shadow: 0 0 2px rgba(105,172,206,1);
- -webkit-box-shadow: 0 0 2px rgba(105,172,206,1);
- box-shadow: 0 0 2px rgba(105,172,206,1);
- -webkit-transition-duration: .3s;
- -moz-transition-duration: .3s;
-}
-
.jp-survey {
position: relative;
z-index: 100;
@@ -889,91 +915,6 @@ p#news-sub {
display: block;
}
-.jp-survey a {
- color: #000;
- text-decoration: underline;
- -webkit-transition-duration: .3s;
- -moz-transition-duration: .3s;
- -o-transition-duration: .3s;
- -ms-transition-duration: .3s;
- transition-duration: .3s;
-}
-
-.jp-survey a:hover {
- color: #555;
- text-decoration: none;
-}
-
-#jetpack-settings .jp-survey p a.button-primary {
- font-size: 16px !important;
- display: inline-block;
- padding: 8px 15px;
- color: #fff!important;
- text-align: center;
- font-size: 20px;
- text-decoration: none;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- border: 1px solid #2A8CBA;
- background: #6AAFCF;
- -moz-box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
- -webkit-box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
- box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
- text-shadow: 0px -1px 0px rgba( 0,0,0,0.3);
- -webkit-transition-duration: .3s;
- -moz-transition-duration: .3s;
- -o-transition-duration: .3s;
- -ms-transition-duration: .3s;
- transition-duration: .3s;
- cursor: pointer;
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-}
-
-#jetpack-settings .jp-survey p a.button-primary:hover, #jetpack-settings .jp-survey p a.button-primary:active {
- background-color: #f0a000;
- border-color: #c87800;
- -webkit-transition-duration: .3s;
- outline: none;
-}
-
-.jp-survey p a.button-secondary {
- font-size: 16px !important;
- display: inline-block;
- padding: 8px 15px;
- color: #fff;
- text-align: center;
- font-size: 20px;
- text-decoration: none;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- border: 1px solid #8caa46;
- background: #b4d278;
- -moz-box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
- -webkit-box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
- box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
- text-shadow: 0px -1px 0px rgba( 0,0,0,0.3);
- -webkit-transition-duration: .3s;
- -moz-transition-duration: .3s;
- -o-transition-duration: .3s;
- -ms-transition-duration: .3s;
- transition-duration: .3s;
- cursor: pointer;
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-}
-
-.jp-survey p a.button-secondary:hover, .jp-survey p a.button-secondary:active {
- background-color: #f0a000;
- border-color: #c87800;
- -webkit-transition-duration: .3s;
- -moz-transition-duration: .3s;
- -o-transition-duration: .3s;
- -ms-transition-duration: .3s;
- transition-duration: .3s;
- outline: none;
-}
-
.jp-survey-container {
overflow: hidden;
padding: 0 20px 8px 0;
@@ -1095,3 +1036,35 @@ p#news-sub {
box-shadow: inset 0 0 2px #fff, 0 1px 7spx rgba(240,160,0,0.5);
}
+.jetpack-inline-error, .jetpack-inline-message {
+ padding: .5em 1em .5em 1em;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ border-width: 1px;
+ border-style: solid;
+ color: #333;
+}
+
+.jetpack-inline-error {
+ background-color: #ffebe8;
+ border-color: #c00;
+}
+
+.jetpack-inline-message {
+ background-color: #ffffe0;
+ border-color: #e6db55;
+}
+
+.jetpack-targetable {
+ border-top: 28px solid transparent;
+ margin-top: -28px;
+}
+
+.jetpack-targetable:target {
+ background-color: #ffffe0;
+ background-clip: padding-box;
+ padding: 0 10px;
+ margin-left: -10px;
+ margin-right: -10px;
+}
diff --git a/plugins/jetpack/_inc/jetpack.js b/plugins/jetpack/_inc/jetpack.js
index 69a86c13..6ef9de8d 100644
--- a/plugins/jetpack/_inc/jetpack.js
+++ b/plugins/jetpack/_inc/jetpack.js
@@ -57,36 +57,23 @@ jetpack = {
});
var widerWidth = 0;
- jQuery( '#jp-disconnect' ).hover( function() {
- var t = jQuery( this ),
- a = t.find( 'a' ),
- width = t.width(),
- changeWidth = widerWidth == 0;
-
- if ( changeWidth && widerWidth < width ) {
- widerWidth = width;
- }
- jetpack.statusText = a.html();
- a.html( jQuery( '#jp-disconnect span' ).html() );
- width = t.width();
- if ( changeWidth && widerWidth < width ) {
- widerWidth = width + 15;
- }
- if ( changeWidth ) {
- t.width( widerWidth );
- }
- a.hide().fadeIn(100);
- }, function() {
- var a = jQuery( 'a', this );
- a.html( jetpack.statusText );
- a.hide().fadeIn(100);
- jetpack.statusText = null;
- } ).find( 'a' ).click( function() {
+ jQuery( '#jp-disconnect a' ).click( function() {
if ( confirm( jetpackL10n.ays_disconnect ) ) {
- jQuery( '#jp-disconnect' ).unbind( 'mouseenter mouseleave' );
+ jQuery( this ).addClass( 'clicked' ).css( {
+ "background-image": 'url( ' + userSettings.url + 'wp-admin/images/wpspin_light.gif )',
+ "background-position": '9px 5px',
+ "background-size": '16px 16px'
+ } ).unbind( 'click' ).click( function() { return false; } );
+ } else {
+ return false;
+ }
+ } );
+ jQuery( '#jp-unlink a' ).click( function() {
+ if ( confirm( jetpackL10n.ays_unlink ) ) {
jQuery( this ).css( {
- "background-image": 'url( ' + userSettings.url + 'wp-admin/images/wpspin_dark.gif )',
+ "background-image": 'url( ' + userSettings.url + 'wp-admin/images/wpspin_light.gif )',
"background-position": '9px 5px',
+ "background-size": '16px 16px'
} ).unbind( 'click' ).click( function() { return false; } );
} else {
return false;
@@ -108,7 +95,7 @@ jetpack = {
jQuery( 'div.placeholder' ).show();
var containerWidth = jetpack.container.width(),
- needed = 4 * parseInt( containerWidth / 242, 10 ) - jetpack.numModules
+ needed = 5 * parseInt( containerWidth / 242, 10 ) - jetpack.numModules
if ( jetpack.numModules * 242 > containerWidth )
jQuery( 'div.placeholder' ).slice( needed ).hide();
@@ -155,12 +142,15 @@ jetpack = {
jQuery( window ).scrollTo( ( jQuery( 'div.more-info' ).prev().offset().top ) - 70, 600, function() { if ( typeof callback == 'function' ) callback.call( this ); } );
} else {
jQuery( 'div.more-info div.jp-content' ).hide();
- jQuery( 'div.more-info' ).slideUp( 200, function() {
- jQuery(this).detach().insertAfter( el );
+ jQuery( 'div.more-info' ).css( { height: '230px', minHeight: 0 } ).slideUp( 200, function() {
+ var $this = jQuery(this);
+ $this.detach().insertAfter( el );
jQuery( 'div.more-info div.jp-content' ).hide();
jetpack.learn_more_content( jQuery(card).attr( 'id' ) );
- jQuery( 'div.more-info' ).slideDown( 300 );
- jQuery( window ).scrollTo( ( jQuery( 'div.more-info' ).prev().offset().top ) - 70, 600, function() { if ( typeof callback == 'function' ) callback.call( this ); } );
+ $this.css( { height: '230px', minHeight: 0 } ).slideDown( 300, function() {
+ $this.css( { height: 'auto', minHeight: '230px' } );
+ } );
+ jQuery( window ).scrollTo( ( $this.prev().offset().top ) - 70, 600, function() { if ( typeof callback == 'function' ) callback.call( this ); } );
} );
}
@@ -170,7 +160,9 @@ jetpack = {
jQuery( el ).after( '<div id="message" class="more-info jetpack-message"><div class="arrow"></div><div class="jp-content"></div><div class="jp-close">&times;</div><div class="clear"></div></div>' );
// Show the box
+ jQuery( 'div.more-info' ).css( { height: '230px', minHeight: 0 } );
jQuery( 'div.more-info', 'div.module-container' ).hide().slideDown( 400, function() {
+ jQuery( 'div.more-info' ).css( { height: 'auto', minHeight: '230px' } );
// Load the content and scroll to it
jetpack.learn_more_content( jQuery(card).attr( 'id' ) );
jQuery( window ).scrollTo( ( jQuery( 'div.more-info' ).prev().offset().top ) - 70, 600 );
@@ -226,7 +218,7 @@ jetpack = {
close_learn_more: function( callback ) {
jQuery( 'div.more-info div.jp-content' ).hide();
- jQuery( 'div.more-info' ).slideUp( 200, function() {
+ jQuery( 'div.more-info' ).css( { height: '230px', minHeight: 0 } ).slideUp( 200, function() {
jQuery( this ).remove();
jQuery( 'a.jetpack-deactivate-button' ).hide();
jetpack.linkClicked.parents( 'div.jetpack-module' ).children( '.jetpack-module-actions' ).children( 'a.jetpack-configure-button' ).show();
diff --git a/plugins/jetpack/_inc/jquery.inview.js b/plugins/jetpack/_inc/jquery.inview.js
new file mode 100644
index 00000000..45f71c4c
--- /dev/null
+++ b/plugins/jetpack/_inc/jquery.inview.js
@@ -0,0 +1,143 @@
+/**
+ * author Christopher Blum
+ * - based on the idea of Remy Sharp, http://remysharp.com/2009/01/26/element-in-view-event-plugin/
+ * - forked from http://github.com/zuk/jquery.inview/
+ */
+(function ($) {
+ var inviewObjects = {}, viewportSize, viewportOffset,
+ d = document, w = window, documentElement = d.documentElement, expando = $.expando;
+
+ $.event.special.inview = {
+ add: function(data) {
+ inviewObjects[data.guid + "-" + this[expando]] = { data: data, $element: $(this) };
+ },
+
+ remove: function(data) {
+ try { delete inviewObjects[data.guid + "-" + this[expando]]; } catch(e) {}
+ }
+ };
+
+ function getViewportSize() {
+ var mode, domObject, size = { height: w.innerHeight, width: w.innerWidth };
+
+ // if this is correct then return it. iPad has compat Mode, so will
+ // go into check clientHeight/clientWidth (which has the wrong value).
+ if (!size.height) {
+ mode = d.compatMode;
+ if (mode || !$.support.boxModel) { // IE, Gecko
+ domObject = mode === 'CSS1Compat' ?
+ documentElement : // Standards
+ d.body; // Quirks
+ size = {
+ height: domObject.clientHeight,
+ width: domObject.clientWidth
+ };
+ }
+ }
+
+ return size;
+ }
+
+ function getViewportOffset() {
+ return {
+ top: w.pageYOffset || documentElement.scrollTop || d.body.scrollTop,
+ left: w.pageXOffset || documentElement.scrollLeft || d.body.scrollLeft
+ };
+ }
+
+ function checkInView() {
+ var $elements = $(), elementsLength, i = 0;
+
+ $.each(inviewObjects, function(i, inviewObject) {
+ var selector = inviewObject.data.selector,
+ $element = inviewObject.$element;
+ $elements = $elements.add(selector ? $element.find(selector) : $element);
+ });
+
+ elementsLength = $elements.length;
+ if (elementsLength) {
+ viewportSize = viewportSize || getViewportSize();
+ viewportOffset = viewportOffset || getViewportOffset();
+
+ for (; i<elementsLength; i++) {
+ // Ignore elements that are not in the DOM tree
+ if (!$.contains(documentElement, $elements[i])) {
+ continue;
+ }
+
+ var element = $elements[i],
+ $element = $(element),
+ elementSize = {},
+ elementOffset = {},
+ inView = $element.data('inview'),
+ visiblePartX,
+ visiblePartY,
+ visiblePartsMerged;
+
+ // for the case where 'display:none' is used in place of 'visibility:hidden'
+ // count and sum the above items to get and move closer to the correct values
+ // IMPORTANT :: insert element into container empty
+ if($element.css('display') == 'none')
+ {
+ var parentElement = $element.parent();
+
+ elementOffset.top = parentElement.offset().top;
+ elementOffset.left = parentElement.offset().left;
+ elementSize.height = parentElement.height();
+ elementSize.width = parentElement.width();
+ } else {
+ elementSize = { height: $element.height(), width: $element.width() }
+ elementOffset = $element.offset();
+ }
+
+ // Don't ask me why because I haven't figured out yet:
+ // viewportOffset and viewportSize are sometimes suddenly null in Firefox 5.
+ // Even though it sounds weird:
+ // It seems that the execution of this function is interferred by the onresize/onscroll event
+ // where viewportOffset and viewportSize are unset
+ if (!viewportOffset || !viewportSize) {
+ return;
+ }
+
+ if (element.offsetWidth >= 0 && element.offsetHeight >= 0 && element.style.display != "none" &&
+ elementOffset.top + elementSize.height > viewportOffset.top &&
+ elementOffset.top < viewportOffset.top + viewportSize.height &&
+ elementOffset.left + elementSize.width > viewportOffset.left &&
+ elementOffset.left < viewportOffset.left + viewportSize.width) {
+ visiblePartX = (viewportOffset.left > elementOffset.left ?
+ 'right' : (viewportOffset.left + viewportSize.width) < (elementOffset.left + elementSize.width) ?
+ 'left' : 'both');
+ visiblePartY = (viewportOffset.top > elementOffset.top ?
+ 'bottom' : (viewportOffset.top + viewportSize.height) < (elementOffset.top + elementSize.height) ?
+ 'top' : 'both');
+ visiblePartsMerged = visiblePartX + "-" + visiblePartY;
+ if (!inView || inView !== visiblePartsMerged) {
+ $element.data('inview', visiblePartsMerged).trigger('inview', [true, visiblePartX, visiblePartY]);
+ }
+ } else if (inView) {
+ $element.data('inview', false).trigger('inview', [false]);
+ }
+ }
+ }
+ }
+
+ $(w).bind("scroll resize", function() {
+ viewportSize = viewportOffset = null;
+ });
+
+ // IE < 9 scrolls to focused elements without firing the "scroll" event
+ if (!documentElement.addEventListener && documentElement.attachEvent) {
+ documentElement.attachEvent("onfocusin", function() {
+ viewportOffset = null;
+ });
+ }
+
+ // Use setInterval in order to also make sure this captures elements within
+ // "overflow:scroll" elements or elements that appeared in the dom tree due to
+ // dom manipulation and reflow
+ // old: $(window).scroll(checkInView);
+ //
+ // By the way, iOS (iPad, iPhone, ...) seems to not execute, or at least delays
+ // intervals while the user scrolls. Therefore the inview event might fire a bit late there
+ setInterval(checkInView, 250);
+})(jQuery); \ No newline at end of file
diff --git a/plugins/jetpack/_inc/jquery.jetpack-resize.js b/plugins/jetpack/_inc/jquery.jetpack-resize.js
new file mode 100644
index 00000000..e1adb22d
--- /dev/null
+++ b/plugins/jetpack/_inc/jquery.jetpack-resize.js
@@ -0,0 +1,275 @@
+/**
+ * Resizeable Iframes.
+ *
+ * Start listening to resize postMessage events for selected iframes:
+ * $( selector ).Jetpack( 'resizeable' );
+ * - OR -
+ * Jetpack.resizeable( 'on', context );
+ *
+ * Resize selected iframes:
+ * $( selector ).Jetpack( 'resizeable', 'resize', { width: 100, height: 200 } );
+ * - OR -
+ * Jetpack.resizeable( 'resize', { width: 100, height: 200 }, context );
+ *
+ * Stop listening to resize postMessage events for selected iframes:
+ * $( selector ).Jetpack( 'resizeable', 'off' );
+ * - OR -
+ * Jetpack.resizeable( 'off', context );
+ *
+ * Stop listening to all resize postMessage events:
+ * Jetpack.resizeable( 'off' );
+ */
+(function($) {
+ var listening = false, // Are we listening for resize postMessage events
+ sourceOrigins = [], // What origins are allowed to send resize postMessage events
+ $sources = false, // What iframe elements are we tracking resize postMessage events from
+
+ URLtoOrigin, // Utility to convert URLs into origins
+ setupListener, // Binds global resize postMessage event handler
+ destroyListener, // Unbinds global resize postMessage event handler
+
+ methods; // Jetpack.resizeable methods
+
+ // Setup the Jetpack global
+ if ( 'undefined' === typeof window.Jetpack ) {
+ window.Jetpack = {
+ /**
+ * Handles the two different calling methods:
+ * $( selector ).Jetpack( 'namespace', 'method', context ) // here, context is optional and is used to filter the collection
+ * - vs. -
+ * Jetpack.namespace( 'method', context ) // here context defines the collection
+ *
+ * @internal
+ *
+ * Call as: Jetpack.getTarget.call( this, context )
+ *
+ * @param string context: jQuery selector
+ * @return jQuery|undefined object on which to perform operations or undefined when context cannot be determined
+ */
+ getTarget: function( context ) {
+ if ( this instanceof jQuery ) {
+ return context ? this.filter( context ) : this;
+ }
+
+ return context ? $( context ) : context;
+ }
+ };
+ }
+
+ // Setup the Jetpack jQuery method
+ if ( 'undefined' === typeof $.fn.Jetpack ) {
+ /**
+ * Dispatches calls to the correct namespace
+ *
+ * @param string namespace
+ * @param ...
+ * @return mixed|jQuery (chainable)
+ */
+ $.fn.Jetpack = function( namespace ) {
+ if ( 'function' === typeof Jetpack[namespace] ) {
+ // Send the call to the correct Jetpack.namespace
+ return Jetpack[namespace].apply( this, Array.prototype.slice.call( arguments, 1 ) );
+ } else {
+ $.error( 'Namespace "' + namespace + '" does not exist on jQuery.Jetpack' );
+ }
+ };
+ }
+
+ // Define Jetpack.resizeable() namespace to just always bail if no postMessage
+ if ( 'function' !== typeof window.postMessage ) {
+ $.extend( window.Jetpack, {
+ /**
+ * Defines the Jetpack.resizeable() namespace.
+ * See below for non-trivial definition for browsers with postMessage.
+ */
+ resizeable: function() {
+ $.error( 'Browser does not support window.postMessage' );
+ }
+ } );
+
+ return;
+ }
+
+ /**
+ * Utility to convert URLs into origins
+ *
+ * http://example.com:port/path?query#fragment -> http://example.com:port
+ *
+ * @param string URL
+ * @return string origin
+ */
+ URLtoOrigin = function( URL ) {
+ if ( ! URL.match( /^https?:\/\// ) ) {
+ URL = document.location.href;
+ }
+ return URL.split( '/' ).slice( 0, 3 ).join( '/' );
+ };
+
+ /**
+ * Binds global resize postMessage event handler
+ */
+ setupListener = function() {
+ listening = true;
+
+ $( window ).on( 'message.JetpackResizeableIframe', function( e ) {
+ var event = e.originalEvent,
+ data;
+
+ // Ensure origin is allowed
+ if ( -1 === $.inArray( event.origin, sourceOrigins ) ) {
+ return;
+ }
+
+ // Some browsers send structured data, some send JSON strings
+ if ( 'object' === typeof event.data ) {
+ data = event.data;
+ } else {
+ try {
+ data = JSON.parse( event.data );
+ } catch ( err ) {
+ data = false;
+ }
+ }
+
+ if ( !data ) {
+ return;
+ }
+
+ // Is it a resize event?
+ if ( 'undefined' === typeof data.action || 'resize' !== data.action ) {
+ return;
+ }
+
+ // Find the correct iframe and resize it
+ $sources.filter( function() {
+ if ( 'undefined' !== typeof data.name )
+ return this.name === data.name;
+ else
+ return event.source === this.contentWindow;
+ } ).first().Jetpack( 'resizeable', 'resize', data );
+ } );
+ };
+
+ /**
+ * Unbinds global resize postMessage event handler
+ */
+ destroyListener = function() {
+ listening = false;
+ $( window ).off( 'message.JetpackResizeableIframe' );
+
+ sourceOrigins = [];
+ $( '.jetpack-resizeable' ).removeClass( 'jetpack-resizeable' );
+ $sources = false;
+ };
+
+ // Methods for Jetpack.resizeable() namespace
+ methods = {
+ /**
+ * Start listening for resize postMessage events on the given iframes
+ *
+ * Call statically as: Jetpack.resizeable( 'on', context )
+ * Call as: $( selector ).Jetpack( 'resizeable', 'on', context ) // context optional: used to filter the collectino
+ *
+ * @param string context jQuery selector.
+ * @return jQuery (chainable)
+ */
+ on: function( context ) {
+ var target = Jetpack.getTarget.call( this, context );
+
+ if ( ! listening ) {
+ setupListener();
+ }
+
+ target.each( function() {
+ sourceOrigins.push( URLtoOrigin( $( this ).attr( 'src' ) ) );
+ } ).addClass( 'jetpack-resizeable' );
+
+ $sources = $( '.jetpack-resizeable' );
+
+ return target;
+ },
+
+ /**
+ * Stop listening for resize postMessage events on the given iframes
+ *
+ * Call statically as: Jetpack.resizeable( 'off', context )
+ * Call as: $( selector ).Jetpack( 'resizeable', 'off', context ) // context optional: used to filter the collectino
+ *
+ * @param string context jQuery selector
+ * @return jQuery (chainable)
+ */
+ off: function( context ) {
+ var target = Jetpack.getTarget.call( this, context );
+
+ if ( 'undefined' === typeof target ) {
+ destroyListener();
+
+ return target;
+ }
+
+ target.each( function() {
+ var origin = URLtoOrigin( $( this ).attr( 'src' ) ),
+ pos = $.inArray( origin, sourceOrigins );
+
+ if ( -1 !== pos ) {
+ sourceOrigins.splice( pos, 1 );
+ }
+ } ).removeClass( 'jetpack-resizeable' );
+
+ $sources = $( '.jetpack-resizeable' );
+
+ return target;
+ },
+
+ /**
+ * Resize the given iframes
+ *
+ * Call statically as: Jetpack.resizeable( 'resize', dimensions, context )
+ * Call as: $( selector ).Jetpack( 'resizeable', 'resize', dimensions, context ) // context optional: used to filter the collectino
+ *
+ * @param object dimensions in pixels: { width: (int), height: (int) }
+ * @param string context jQuery selector
+ * @return jQuery (chainable)
+ */
+ resize: function( dimensions, context ) {
+ var target = Jetpack.getTarget.call( this, context );
+
+ $.each( [ 'width', 'height' ], function( i, variable ) {
+ var value = 0;
+ if ( 'undefined' !== typeof dimensions[variable] ) {
+ value = parseInt( dimensions[variable], 10 );
+ }
+
+ if ( 0 !== value ) {
+ target[variable]( value );
+ }
+ } );
+
+ return target;
+ }
+ };
+
+ // Define Jetpack.resizeable() namespace
+ $.extend( window.Jetpack, {
+ /**
+ * Defines the Jetpack.resizeable() namespace.
+ * See above for trivial definition for browsers with no postMessage.
+ *
+ * @param string method
+ * @param ...
+ * @return mixed|jQuery (chainable)
+ */
+ resizeable: function( method ) {
+ if ( methods[method] ) {
+ // Send the call to the correct Jetpack.resizeable() method
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ) );
+ } else if ( ! method ) {
+ // By default, send to Jetpack.resizeable( 'on' ), which isn't useful in that form but is when called as
+ // jQuery( selector ).Jetpack( 'resizeable' )
+ return methods.on.apply( this );
+ } else {
+ $.error( 'Method ' + method + ' does not exist on Jetpack.resizeable' );
+ }
+ }
+ } );
+})(jQuery);
diff --git a/plugins/jetpack/_inc/jquery.spin.js b/plugins/jetpack/_inc/jquery.spin.js
new file mode 100644
index 00000000..4642af13
--- /dev/null
+++ b/plugins/jetpack/_inc/jquery.spin.js
@@ -0,0 +1,86 @@
+/*
+ * Matt Husby https://github.com/matthusby/spin.js
+ * Based on the jquery plugin by Bradley Smith
+ * https://gist.github.com/1290439
+ */
+
+/*
+Add spin to the jQuery object
+If color is not passed the spinner will be black
+You can now create a spinner using any of the variants below:
+$("#el").spin(); // Produces default Spinner
+$("#el").spin("small"); // Produces a 'small' Spinner
+$("#el").spin("large", "white"); // Produces a 'large' Spinner in white (or any valid CSS color).
+$("#el").spin({ ... }); // Produces a Spinner using your custom settings.
+$("#el").spin("small-right"); // Pin the small spinner to the right edge
+$("#el").spin("{small, medium, large}-{left, right, top, bottom}"); // All options for where to pin
+$("#el").spin(false); // Kills the spinner.
+*/
+
+( function( $ ) {
+ $.fn.spin = function( opts, color ) {
+ var presets = {
+ "small": { lines: 8, length: 2, width: 2, radius: 3, trail: 60, speed: 1.3 },
+ "medium": { lines: 8, length: 4, width: 3, radius: 5, trail: 60, speed: 1.3 },
+ "large": { lines: 10, length: 6, width: 4, radius: 7, trail: 60, speed: 1.3 }
+ };
+ if ( Spinner ) {
+ return this.each( function() {
+ var $this = $( this ),
+ data = $this.data();
+
+ if ( data.spinner ) {
+ data.spinner.stop();
+ delete data.spinner;
+ }
+ if ( opts !== false ) {
+ var spinner_options;
+ if ( typeof opts === "string" ) {
+ var spinner_base = opts.indexOf( '-' );
+ if( spinner_base == -1 ) {
+ spinner_base = opts;
+ } else {
+ spinner_base = opts.substring( 0, spinner_base );
+ }
+ if ( spinner_base in presets ) {
+ spinner_options = presets[spinner_base];
+ } else {
+ spinner_options = {};
+ }
+ var padding;
+ if ( opts.indexOf( "-right" ) != -1 ) {
+ padding = jQuery( this ).css( 'padding-left' );
+ if( typeof padding === "undefined" ) {
+ padding = 0;
+ } else {
+ padding = padding.replace( 'px', '' );
+ }
+ spinner_options.left = jQuery( this ).outerWidth() - ( 2 * ( spinner_options.length + spinner_options.width + spinner_options.radius ) ) - padding - 5;
+ }
+ if ( opts.indexOf( '-left' ) != -1 ) {
+ spinner_options.left = 5;
+ }
+ if ( opts.indexOf( '-top' ) != -1 ) {
+ spinner_options.top = 5;
+ }
+ if ( opts.indexOf( '-bottom' ) != -1 ) {
+ padding = jQuery( this ).css( 'padding-top' );
+ if( typeof padding === "undefined" ) {
+ padding = 0;
+ } else {
+ padding = padding.replace( 'px', '' );
+ }
+ spinner_options.top = jQuery( this ).outerHeight() - ( 2 * ( spinner_options.length + spinner_options.width + spinner_options.radius ) ) - padding - 5;
+ }
+ }
+ if( color ){
+ spinner_options.color = color;
+ }
+ data.spinner = new Spinner( spinner_options ).spin( this );
+ }
+ });
+ } else {
+ throw "Spinner class not available.";
+ }
+ };
+})( jQuery ); \ No newline at end of file
diff --git a/plugins/jetpack/_inc/postmessage.js b/plugins/jetpack/_inc/postmessage.js
new file mode 100644
index 00000000..e8933bca
--- /dev/null
+++ b/plugins/jetpack/_inc/postmessage.js
@@ -0,0 +1,438 @@
+/**
+ The MIT License
+
+ Copyright (c) 2010 Daniel Park (http://metaweb.com, http://postmessage.freebaseapps.com)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ **/
+var NO_JQUERY = {};
+(function(window, $, undefined) {
+
+ if (!("console" in window)) {
+ var c = window.console = {};
+ c.log = c.warn = c.error = c.debug = function(){};
+ }
+
+ if ($ === NO_JQUERY) {
+ // jQuery is optional
+ $ = {
+ fn: {},
+ extend: function() {
+ var a = arguments[0];
+ for (var i=1,len=arguments.length; i<len; i++) {
+ var b = arguments[i];
+ for (var prop in b) {
+ a[prop] = b[prop];
+ }
+ }
+ return a;
+ }
+ };
+ }
+
+ $.fn.pm = function() {
+ console.log("usage: \nto send: $.pm(options)\nto receive: $.pm.bind(type, fn, [origin])");
+ return this;
+ };
+
+ // send postmessage
+ $.pm = window.pm = function(options) {
+ pm.send(options);
+ };
+
+ // bind postmessage handler
+ $.pm.bind = window.pm.bind = function(type, fn, origin, hash, async_reply) {
+ pm.bind(type, fn, origin, hash, async_reply === true);
+ };
+
+ // unbind postmessage handler
+ $.pm.unbind = window.pm.unbind = function(type, fn) {
+ pm.unbind(type, fn);
+ };
+
+ // default postmessage origin on bind
+ $.pm.origin = window.pm.origin = null;
+
+ // default postmessage polling if using location hash to pass postmessages
+ $.pm.poll = window.pm.poll = 200;
+
+ var pm = {
+
+ send: function(options) {
+ var o = $.extend({}, pm.defaults, options),
+ target = o.target;
+ if (!o.target) {
+ console.warn("postmessage target window required");
+ return;
+ }
+ if (!o.type) {
+ console.warn("postmessage type required");
+ return;
+ }
+ var msg = {data:o.data, type:o.type};
+ if (o.success) {
+ msg.callback = pm._callback(o.success);
+ }
+ if (o.error) {
+ msg.errback = pm._callback(o.error);
+ }
+ if (("postMessage" in target) && !o.hash) {
+ pm._bind();
+ target.postMessage(JSON.stringify(msg), o.origin || '*');
+ }
+ else {
+ pm.hash._bind();
+ pm.hash.send(o, msg);
+ }
+ },
+
+ bind: function(type, fn, origin, hash, async_reply) {
+ pm._replyBind ( type, fn, origin, hash, async_reply );
+ },
+
+ _replyBind: function(type, fn, origin, hash, isCallback) {
+ if (("postMessage" in window) && !hash) {
+ pm._bind();
+ }
+ else {
+ pm.hash._bind();
+ }
+ var l = pm.data("listeners.postmessage");
+ if (!l) {
+ l = {};
+ pm.data("listeners.postmessage", l);
+ }
+ var fns = l[type];
+ if (!fns) {
+ fns = [];
+ l[type] = fns;
+ }
+ fns.push({fn:fn, callback: isCallback, origin:origin || $.pm.origin});
+ },
+
+ unbind: function(type, fn) {
+ var l = pm.data("listeners.postmessage");
+ if (l) {
+ if (type) {
+ if (fn) {
+ // remove specific listener
+ var fns = l[type];
+ if (fns) {
+ var m = [];
+ for (var i=0,len=fns.length; i<len; i++) {
+ var o = fns[i];
+ if (o.fn !== fn) {
+ m.push(o);
+ }
+ }
+ l[type] = m;
+ }
+ }
+ else {
+ // remove all listeners by type
+ delete l[type];
+ }
+ }
+ else {
+ // unbind all listeners of all type
+ for (var i in l) {
+ delete l[i];
+ }
+ }
+ }
+ },
+
+ data: function(k, v) {
+ if (v === undefined) {
+ return pm._data[k];
+ }
+ pm._data[k] = v;
+ return v;
+ },
+
+ _data: {},
+
+ _CHARS: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''),
+
+ _random: function() {
+ var r = [];
+ for (var i=0; i<32; i++) {
+ r[i] = pm._CHARS[0 | Math.random() * 32];
+ };
+ return r.join("");
+ },
+
+ _callback: function(fn) {
+ var cbs = pm.data("callbacks.postmessage");
+ if (!cbs) {
+ cbs = {};
+ pm.data("callbacks.postmessage", cbs);
+ }
+ var r = pm._random();
+ cbs[r] = fn;
+ return r;
+ },
+
+ _bind: function() {
+ // are we already listening to message events on this w?
+ if (!pm.data("listening.postmessage")) {
+ if (window.addEventListener) {
+ window.addEventListener("message", pm._dispatch, false);
+ }
+ else if (window.attachEvent) {
+ window.attachEvent("onmessage", pm._dispatch);
+ }
+ pm.data("listening.postmessage", 1);
+ }
+ },
+
+ _dispatch: function(e) {
+ //console.log("$.pm.dispatch", e, this);
+ try {
+ var msg = JSON.parse(e.data);
+ }
+ catch (ex) {
+ //console.warn("postmessage data invalid json: ", ex); //message wasn't meant for pm
+ return;
+ }
+ if (!msg.type) {
+ //console.warn("postmessage message type required"); //message wasn't meant for pm
+ return;
+ }
+ var cbs = pm.data("callbacks.postmessage") || {},
+ cb = cbs[msg.type];
+ if (cb) {
+ cb(msg.data);
+ }
+ else {
+ var l = pm.data("listeners.postmessage") || {};
+ var fns = l[msg.type] || [];
+ for (var i=0,len=fns.length; i<len; i++) {
+ var o = fns[i];
+ if (o.origin && o.origin !== '*' && e.origin !== o.origin) {
+ console.warn("postmessage message origin mismatch", e.origin, o.origin);
+ if (msg.errback) {
+ // notify post message errback
+ var error = {
+ message: "postmessage origin mismatch",
+ origin: [e.origin, o.origin]
+ };
+ pm.send({target:e.source, data:error, type:msg.errback});
+ }
+ continue;
+ }
+
+ function sendReply ( data ) {
+ if (msg.callback) {
+ pm.send({target:e.source, data:data, type:msg.callback});
+ }
+ }
+
+ try {
+ if ( o.callback ) {
+ o.fn(msg.data, sendReply, e);
+ } else {
+ sendReply ( o.fn(msg.data, e) );
+ }
+ }
+ catch (ex) {
+ if (msg.errback) {
+ // notify post message errback
+ pm.send({target:e.source, data:ex, type:msg.errback});
+ } else {
+ throw ex;
+ }
+ }
+ };
+ }
+ }
+ };
+
+ // location hash polling
+ pm.hash = {
+
+ send: function(options, msg) {
+ //console.log("hash.send", target_window, options, msg);
+ var target_window = options.target,
+ target_url = options.url;
+ if (!target_url) {
+ console.warn("postmessage target window url is required");
+ return;
+ }
+ target_url = pm.hash._url(target_url);
+ var source_window,
+ source_url = pm.hash._url(window.location.href);
+ if (window == target_window.parent) {
+ source_window = "parent";
+ }
+ else {
+ try {
+ for (var i=0,len=parent.frames.length; i<len; i++) {
+ var f = parent.frames[i];
+ if (f == window) {
+ source_window = i;
+ break;
+ }
+ };
+ }
+ catch(ex) {
+ // Opera: security error trying to access parent.frames x-origin
+ // juse use window.name
+ source_window = window.name;
+ }
+ }
+ if (source_window == null) {
+ console.warn("postmessage windows must be direct parent/child windows and the child must be available through the parent window.frames list");
+ return;
+ }
+ var hashmessage = {
+ "x-requested-with": "postmessage",
+ source: {
+ name: source_window,
+ url: source_url
+ },
+ postmessage: msg
+ };
+ var hash_id = "#x-postmessage-id=" + pm._random();
+ target_window.location = target_url + hash_id + encodeURIComponent(JSON.stringify(hashmessage));
+ },
+
+ _regex: /^\#x\-postmessage\-id\=(\w{32})/,
+
+ _regex_len: "#x-postmessage-id=".length + 32,
+
+ _bind: function() {
+ // are we already listening to message events on this w?
+ if (!pm.data("polling.postmessage")) {
+ setInterval(function() {
+ var hash = "" + window.location.hash,
+ m = pm.hash._regex.exec(hash);
+ if (m) {
+ var id = m[1];
+ if (pm.hash._last !== id) {
+ pm.hash._last = id;
+ pm.hash._dispatch(hash.substring(pm.hash._regex_len));
+ }
+ }
+ }, $.pm.poll || 200);
+ pm.data("polling.postmessage", 1);
+ }
+ },
+
+ _dispatch: function(hash) {
+ if (!hash) {
+ return;
+ }
+ try {
+ hash = JSON.parse(decodeURIComponent(hash));
+ if (!(hash['x-requested-with'] === 'postmessage' &&
+ hash.source && hash.source.name != null && hash.source.url && hash.postmessage)) {
+ // ignore since hash could've come from somewhere else
+ return;
+ }
+ }
+ catch (ex) {
+ // ignore since hash could've come from somewhere else
+ return;
+ }
+ var msg = hash.postmessage,
+ cbs = pm.data("callbacks.postmessage") || {},
+ cb = cbs[msg.type];
+ if (cb) {
+ cb(msg.data);
+ }
+ else {
+ var source_window;
+ if (hash.source.name === "parent") {
+ source_window = window.parent;
+ }
+ else {
+ source_window = window.frames[hash.source.name];
+ }
+ var l = pm.data("listeners.postmessage") || {};
+ var fns = l[msg.type] || [];
+ for (var i=0,len=fns.length; i<len; i++) {
+ var o = fns[i];
+ if (o.origin) {
+ var origin = /https?\:\/\/[^\/]*/.exec(hash.source.url)[0];
+ if (o.origin !== '*' && origin !== o.origin) {
+ console.warn("postmessage message origin mismatch", origin, o.origin);
+ if (msg.errback) {
+ // notify post message errback
+ var error = {
+ message: "postmessage origin mismatch",
+ origin: [origin, o.origin]
+ };
+ pm.send({target:source_window, data:error, type:msg.errback, hash:true, url:hash.source.url});
+ }
+ continue;
+ }
+ }
+
+ function sendReply ( data ) {
+ if (msg.callback) {
+ pm.send({target:source_window, data:data, type:msg.callback, hash:true, url:hash.source.url});
+ }
+ }
+
+ try {
+ if ( o.callback ) {
+ o.fn(msg.data, sendReply);
+ } else {
+ sendReply ( o.fn(msg.data) );
+ }
+ }
+ catch (ex) {
+ if (msg.errback) {
+ // notify post message errback
+ pm.send({target:source_window, data:ex, type:msg.errback, hash:true, url:hash.source.url});
+ } else {
+ throw ex;
+ }
+ }
+ };
+ }
+ },
+
+ _url: function(url) {
+ // url minus hash part
+ return (""+url).replace(/#.*$/, "");
+ }
+
+ };
+
+ $.extend(pm, {
+ defaults: {
+ target: null, /* target window (required) */
+ url: null, /* target window url (required if no window.postMessage or hash == true) */
+ type: null, /* message type (required) */
+ data: null, /* message data (required) */
+ success: null, /* success callback (optional) */
+ error: null, /* error callback (optional) */
+ origin: "*", /* postmessage origin (optional) */
+ hash: false /* use location hash for message passing (optional) */
+ }
+ });
+
+ })(this, typeof jQuery === "undefined" ? NO_JQUERY : jQuery);
+
+/**
+ * http://www.JSON.org/json2.js
+ **/
+if (! ("JSON" in window && window.JSON)){JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z"};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
diff --git a/plugins/jetpack/_inc/spin.js b/plugins/jetpack/_inc/spin.js
new file mode 100644
index 00000000..f506cd2b
--- /dev/null
+++ b/plugins/jetpack/_inc/spin.js
@@ -0,0 +1,301 @@
+//fgnass.github.com/spin.js#v1.2.4
+(function(window, document, undefined) {
+
+/**
+ * Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de]
+ * Licensed under the MIT license
+ */
+
+ var prefixes = ['webkit', 'Moz', 'ms', 'O']; /* Vendor prefixes */
+ var animations = {}; /* Animation rules keyed by their name */
+ var useCssAnimations;
+
+ /**
+ * Utility function to create elements. If no tag name is given,
+ * a DIV is created. Optionally properties can be passed.
+ */
+ function createEl(tag, prop) {
+ var el = document.createElement(tag || 'div');
+ var n;
+
+ for(n in prop) {
+ el[n] = prop[n];
+ }
+ return el;
+ }
+
+ /**
+ * Appends children and returns the parent.
+ */
+ function ins(parent /* child1, child2, ...*/) {
+ for (var i=1, n=arguments.length; i<n; i++) {
+ parent.appendChild(arguments[i]);
+ }
+ return parent;
+ }
+
+ /**
+ * Insert a new stylesheet to hold the @keyframe or VML rules.
+ */
+ var sheet = function() {
+ var el = createEl('style');
+ ins(document.getElementsByTagName('head')[0], el);
+ return el.sheet || el.styleSheet;
+ }();
+
+ /**
+ * Creates an opacity keyframe animation rule and returns its name.
+ * Since most mobile Webkits have timing issues with animation-delay,
+ * we create separate rules for each line/segment.
+ */
+ function addAnimation(alpha, trail, i, lines) {
+ var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-');
+ var start = 0.01 + i/lines*100;
+ var z = Math.max(1-(1-alpha)/trail*(100-start) , alpha);
+ var prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase();
+ var pre = prefix && '-'+prefix+'-' || '';
+
+ if (!animations[name]) {
+ sheet.insertRule(
+ '@' + pre + 'keyframes ' + name + '{' +
+ '0%{opacity:'+z+'}' +
+ start + '%{opacity:'+ alpha + '}' +
+ (start+0.01) + '%{opacity:1}' +
+ (start+trail)%100 + '%{opacity:'+ alpha + '}' +
+ '100%{opacity:'+ z + '}' +
+ '}', 0);
+ animations[name] = 1;
+ }
+ return name;
+ }
+
+ /**
+ * Tries various vendor prefixes and returns the first supported property.
+ **/
+ function vendor(el, prop) {
+ var s = el.style;
+ var pp;
+ var i;
+
+ if(s[prop] !== undefined) return prop;
+ prop = prop.charAt(0).toUpperCase() + prop.slice(1);
+ for(i=0; i<prefixes.length; i++) {
+ pp = prefixes[i]+prop;
+ if(s[pp] !== undefined) return pp;
+ }
+ }
+
+ /**
+ * Sets multiple style properties at once.
+ */
+ function css(el, prop) {
+ for (var n in prop) {
+ el.style[vendor(el, n)||n] = prop[n];
+ }
+ return el;
+ }
+
+ /**
+ * Fills in default values.
+ */
+ function merge(obj) {
+ for (var i=1; i < arguments.length; i++) {
+ var def = arguments[i];
+ for (var n in def) {
+ if (obj[n] === undefined) obj[n] = def[n];
+ }
+ }
+ return obj;
+ }
+
+ /**
+ * Returns the absolute page-offset of the given element.
+ */
+ function pos(el) {
+ var o = {x:el.offsetLeft, y:el.offsetTop};
+ while((el = el.offsetParent)) {
+ o.x+=el.offsetLeft;
+ o.y+=el.offsetTop;
+ }
+ return o;
+ }
+
+ var defaults = {
+ lines: 12, // The number of lines to draw
+ length: 7, // The length of each line
+ width: 5, // The line thickness
+ radius: 10, // The radius of the inner circle
+ color: '#000', // #rgb or #rrggbb
+ speed: 1, // Rounds per second
+ trail: 100, // Afterglow percentage
+ opacity: 1/4, // Opacity of the lines
+ fps: 20, // Frames per second when using setTimeout()
+ zIndex: 2e9, // Use a high z-index by default
+ className: 'spinner', // CSS class to assign to the element
+ top: 'auto', // center vertically
+ left: 'auto' // center horizontally
+ };
+
+ /** The constructor */
+ var Spinner = function Spinner(o) {
+ if (!this.spin) return new Spinner(o);
+ this.opts = merge(o || {}, Spinner.defaults, defaults);
+ };
+
+ Spinner.defaults = {};
+ Spinner.prototype = {
+ spin: function(target) {
+ this.stop();
+ var self = this;
+ var o = self.opts;
+ var el = self.el = css(createEl(0, {className: o.className}), {position: 'relative', zIndex: o.zIndex});
+ var mid = o.radius+o.length+o.width;
+ var ep; // element position
+ var tp; // target position
+
+ if (target) {
+ target.insertBefore(el, target.firstChild||null);
+ tp = pos(target);
+ ep = pos(el);
+ css(el, {
+ left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : o.left+mid) + 'px',
+ top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : o.top+mid) + 'px'
+ });
+ }
+
+ el.setAttribute('aria-role', 'progressbar');
+ self.lines(el, self.opts);
+
+ if (!useCssAnimations) {
+ // No CSS animation support, use setTimeout() instead
+ var i = 0;
+ var fps = o.fps;
+ var f = fps/o.speed;
+ var ostep = (1-o.opacity)/(f*o.trail / 100);
+ var astep = f/o.lines;
+
+ !function anim() {
+ i++;
+ for (var s=o.lines; s; s--) {
+ var alpha = Math.max(1-(i+s*astep)%f * ostep, o.opacity);
+ self.opacity(el, o.lines-s, alpha, o);
+ }
+ self.timeout = self.el && setTimeout(anim, ~~(1000/fps));
+ }();
+ }
+ return self;
+ },
+ stop: function() {
+ var el = this.el;
+ if (el) {
+ clearTimeout(this.timeout);
+ if (el.parentNode) el.parentNode.removeChild(el);
+ this.el = undefined;
+ }
+ return this;
+ },
+ lines: function(el, o) {
+ var i = 0;
+ var seg;
+
+ function fill(color, shadow) {
+ return css(createEl(), {
+ position: 'absolute',
+ width: (o.length+o.width) + 'px',
+ height: o.width + 'px',
+ background: color,
+ boxShadow: shadow,
+ transformOrigin: 'left',
+ transform: 'rotate(' + ~~(360/o.lines*i) + 'deg) translate(' + o.radius+'px' +',0)',
+ borderRadius: (o.width>>1) + 'px'
+ });
+ }
+ for (; i < o.lines; i++) {
+ seg = css(createEl(), {
+ position: 'absolute',
+ top: 1+~(o.width/2) + 'px',
+ transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
+ opacity: o.opacity,
+ animation: useCssAnimations && addAnimation(o.opacity, o.trail, i, o.lines) + ' ' + 1/o.speed + 's linear infinite'
+ });
+ if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}));
+ ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)')));
+ }
+ return el;
+ },
+ opacity: function(el, i, val) {
+ if (i < el.childNodes.length) el.childNodes[i].style.opacity = val;
+ }
+ };
+
+ /////////////////////////////////////////////////////////////////////////
+ // VML rendering for IE
+ /////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Check and init VML support
+ */
+ !function() {
+ var s = css(createEl('group'), {behavior: 'url(#default#VML)'});
+ var i;
+
+ if (!vendor(s, 'transform') && s.adj) {
+
+ // VML support detected. Insert CSS rules ...
+ for (i=4; i--;) sheet.addRule(['group', 'roundrect', 'fill', 'stroke'][i], 'behavior:url(#default#VML)');
+
+ Spinner.prototype.lines = function(el, o) {
+ var r = o.length+o.width;
+ var s = 2*r;
+
+ function grp() {
+ return css(createEl('group', {coordsize: s +' '+s, coordorigin: -r +' '+-r}), {width: s, height: s});
+ }
+
+ var margin = -(o.width+o.length)*2+'px';
+ var g = css(grp(), {position: 'absolute', top: margin, left: margin});
+
+ var i;
+
+ function seg(i, dx, filter) {
+ ins(g,
+ ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
+ ins(css(createEl('roundrect', {arcsize: 1}), {
+ width: r,
+ height: o.width,
+ left: o.radius,
+ top: -o.width>>1,
+ filter: filter
+ }),
+ createEl('fill', {color: o.color, opacity: o.opacity}),
+ createEl('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
+ )
+ )
+ );
+ }
+
+ if (o.shadow) {
+ for (i = 1; i <= o.lines; i++) {
+ seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)');
+ }
+ }
+ for (i = 1; i <= o.lines; i++) seg(i);
+ return ins(el, g);
+ };
+ Spinner.prototype.opacity = function(el, i, val, o) {
+ var c = el.firstChild;
+ o = o.shadow && o.lines || 0;
+ if (c && i+o < c.childNodes.length) {
+ c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild;
+ if (c) c.opacity = val;
+ }
+ };
+ }
+ else {
+ useCssAnimations = vendor(s, 'animation');
+ }
+ }();
+
+ window.Spinner = Spinner;
+
+})(window, document); \ No newline at end of file
diff --git a/plugins/jetpack/class.jetpack-ixr-client.php b/plugins/jetpack/class.jetpack-ixr-client.php
index 19f119c5..8d6e52fe 100644
--- a/plugins/jetpack/class.jetpack-ixr-client.php
+++ b/plugins/jetpack/class.jetpack-ixr-client.php
@@ -18,8 +18,6 @@ class Jetpack_IXR_Client extends IXR_Client {
$args = wp_parse_args( $args, $defaults );
- $args['user_id'] = (int) $args['user_id'];
-
$this->jetpack_args = $args;
$this->IXR_Client( $args['url'], $path, $port, $timeout );
diff --git a/plugins/jetpack/class.jetpack-post-images.php b/plugins/jetpack/class.jetpack-post-images.php
new file mode 100644
index 00000000..afdcacfa
--- /dev/null
+++ b/plugins/jetpack/class.jetpack-post-images.php
@@ -0,0 +1,440 @@
+<?php
+
+/**
+ * Useful for finding an image to display alongside/in representation of a specific post.
+ *
+ * Includes a few different methods, all of which return a similar-format array containing
+ * details of any images found. Everything can (should) be called statically, it's just a
+ * function-bucket. You can also call Jetpack_PostImages::get_image() to cycle through all of the methods until
+ * one of them finds something useful.
+ *
+ * This file is included verbatim in Jetpack
+ */
+class Jetpack_PostImages {
+ /**
+ * If a slideshow is embedded within a post, then parse out the images involved and return them
+ */
+ static function from_slideshow( $post_id, $width = 200, $height = 200 ) {
+ $post = get_post( $post_id );
+
+ if ( false === strpos( $post->post_content, '[slideshow' ) )
+ return false; // no slideshow - bail
+
+ $permalink = get_permalink( $post->ID );
+
+ $images = array();
+
+ // Mechanic: Somebody set us up the bomb
+ $old_post = $GLOBALS['post'];
+ $GLOBALS['post'] = $post;
+ $old_shortcodes = $GLOBALS['shortcode_tags'];
+ $GLOBALS['shortcode_tags'] = array( 'slideshow' => $old_shortcodes['slideshow'] );
+
+ // Find all the slideshows
+ preg_match_all( '/' . get_shortcode_regex() . '/sx', $post->post_content, $slideshow_matches, PREG_SET_ORDER );
+
+ ob_start(); // The slideshow shortcode handler calls wp_print_scripts and wp_print_styles... not too happy about that
+
+ foreach ( $slideshow_matches as $slideshow_match ) {
+ $slideshow = do_shortcode_tag( $slideshow_match );
+ if ( false === $pos = stripos( $slideshow, 'slideShow.images' ) ) // must be something wrong - or we changed the output format in which case none of the following will work
+ continue;
+ $start = strpos( $slideshow, '[', $pos );
+ $end = strpos( $slideshow, ']', $start );
+ $post_images = json_decode( str_replace( "'", '"', substr( $slideshow, $start, $end - $start + 1 ) ) ); // parse via JSON
+ foreach ( $post_images as $post_image ) {
+ if ( !$post_image_id = absint( $post_image->id ) )
+ continue;
+
+ $meta = wp_get_attachment_metadata( $post_image_id );
+
+ // Must be larger than 200x200 (or user-specified)
+ if ( !isset( $meta['width'] ) || $meta['width'] < $width )
+ continue;
+ if ( !isset( $meta['height'] ) || $meta['height'] < $height )
+ continue;
+
+ $url = wp_get_attachment_url( $post_image_id );
+
+ $images[] = array(
+ 'type' => 'image',
+ 'from' => 'slideshow',
+ 'src' => $url,
+ 'src_width' => $meta['width'],
+ 'src_height' => $meta['height'],
+ 'href' => $permalink,
+ );
+ }
+ }
+ ob_end_clean();
+
+ // Operator: Main screen turn on
+ $GLOBALS['shortcode_tags'] = $old_shortcodes;
+ $GLOBALS['post'] = $old_post;
+
+ return $images;
+ }
+
+ /**
+ * If a gallery is detected, then get all the images from it.
+ */
+ static function from_gallery( $post_id ) {
+ $post = get_post( $post_id );
+
+ if ( false === strpos( $post->post_content, '[gallery' ) )
+ return false; // no gallery - bail
+
+ $permalink = get_permalink( $post->ID );
+
+ $images = array();
+
+ // CATS: All your base are belong to us
+ $old_post = $GLOBALS['post'];
+ $GLOBALS['post'] = $post;
+ $old_shortcodes = $GLOBALS['shortcode_tags'];
+ $GLOBALS['shortcode_tags'] = array( 'gallery' => $old_shortcodes['gallery'] );
+
+ // Find all the galleries
+ preg_match_all( '/' . get_shortcode_regex() . '/s', $post->post_content, $gallery_matches, PREG_SET_ORDER );
+
+ foreach ( $gallery_matches as $gallery_match ) {
+ $gallery = do_shortcode_tag( $gallery_match );
+
+ // Um... no images in the gallery - bail
+ if ( false === $pos = stripos( $gallery, '<img' ) )
+ continue;
+
+ preg_match_all( '/<img\s+[^>]*src=([\'"])([^\'"]*)\\1/', $gallery, $image_match, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE );
+
+ $a_pos = 0;
+ foreach ( $image_match[2] as $src ) {
+ list( $raw_src ) = explode( '?', $src[0] ); // pull off any Query string (?w=250)
+ $raw_src = wp_specialchars_decode( $raw_src ); // rawify it
+ $raw_src = esc_url_raw( $raw_src ); // clean it
+
+ $a_pos = strrpos( substr( $gallery, 0, $src[1] ), '<a', $a_pos ); // is there surrounding <a>?
+
+ if ( false !== $a_pos && preg_match( '/<a\s+[^>]*href=([\'"])([^\'"]*)\\1/', $gallery, $href_match, 0, $a_pos ) ) {
+ $href = wp_specialchars_decode( $href_match[2] );
+ $href = esc_url_raw( $href );
+ } else {
+ // CATS: You have no chance to survive make your time
+ $href = $raw_src;
+ }
+
+ $a_pos = $src[1];
+
+ $images[] = array(
+ 'type' => 'image',
+ 'from' => 'gallery',
+ 'src' => $raw_src,
+ 'href' => $permalink, // $href,
+ );
+ }
+ }
+
+ // Captain: For great justice
+ $GLOBALS['shortcode_tags'] = $old_shortcodes;
+ $GLOBALS['post'] = $old_post;
+
+ return $images;
+ }
+
+ /**
+ * Get attachment images for a specified post and return them. Also make sure
+ * their dimensions are at or above a required minimum.
+ */
+ static function from_attachment( $post_id, $width = 200, $height = 200 ) {
+
+ $post_images = get_posts( array(
+ 'post_parent' => $post_id, // Must be children of post
+ 'numberposts' => 5, // No more than 5
+ 'post_type' => 'attachment', // Must be attachments
+ 'post_mime_type' => 'image', // Must be images
+ ) );
+
+ if ( !$post_images )
+ return false;
+
+ $permalink = get_permalink( $post_id );
+
+ $images = array();
+
+ foreach ( $post_images as $post_image ) {
+ $meta = wp_get_attachment_metadata( $post_image->ID );
+ // Must be larger than 200x200
+ if ( !isset( $meta['width'] ) || $meta['width'] < $width )
+ continue;
+ if ( !isset( $meta['height'] ) || $meta['height'] < $height )
+ continue;
+
+ $url = wp_get_attachment_url( $post_image->ID );
+
+ $images[] = array(
+ 'type' => 'image',
+ 'from' => 'attachment',
+ 'src' => $url,
+ 'src_width' => $meta['width'],
+ 'src_height' => $meta['height'],
+ 'href' => $permalink,
+ );
+ }
+
+ /*
+ * We only want to pass back attached images that were actually inserted.
+ * We can load up all the images found in the HTML source and then
+ * compare URLs to see if an image is attached AND inserted.
+ */
+ $html_images = array();
+ $html_images = self::from_html( $post_id );
+ $inserted_images = array();
+
+ foreach( $html_images as $html_image ) {
+ $src = parse_url( $html_image['src'] );
+ $inserted_images[] = $src['scheme'] . '://' . $src['host'] . $src['path']; // strip off any query strings
+ }
+ foreach( $images as $i => $image ) {
+ if ( !in_array( $image['src'], $inserted_images ) )
+ unset( $images[$i] );
+ }
+
+ return $images;
+ }
+
+ /**
+ * Check if a Featured Image is set for this post, and return it in a similar
+ * format to the other images?_from_*() methods.
+ * @param int $post_id The post ID to check
+ * @return Array containing details of the Featured Image, or empty array if none.
+ */
+ static function from_thumbnail( $post_id, $width = 200, $height = 200 ) {
+ $images = array();
+
+ if ( !function_exists( 'get_post_thumbnail_id' ) ) {
+ return $images;
+ }
+
+ $thumb = get_post_thumbnail_id( $post_id );
+
+ if ( $thumb ) {
+ $meta = wp_get_attachment_metadata( $thumb );
+
+ // Must be larger than requested minimums
+ if ( !isset( $meta['width'] ) || $meta['width'] < $width )
+ return $images;
+ if ( !isset( $meta['height'] ) || $meta['height'] < $height )
+ return $images;
+
+ $url = wp_get_attachment_url( $thumb );
+ if ( stristr( $url, '?' ) )
+ $url = substr( $url, 0, strpos( $url, '?' ) );
+
+ $images = array( array( // Other methods below all return an array of arrays
+ 'type' => 'image',
+ 'from' => 'thumbnail',
+ 'src' => $url,
+ 'src_width' => $meta['width'],
+ 'src_height' => $meta['height'],
+ 'href' => get_permalink( $thumb ),
+ ) );
+ }
+ return $images;
+ }
+
+ /**
+ * Very raw -- just parse the HTML and pull out any/all img tags and return their src
+ * @param mixed $html_or_id The HTML string to parse for images, or a post id
+ * @return Array containing images
+ */
+ static function from_html( $html_or_id ) {
+ $images = array();
+
+ if ( is_numeric( $html_or_id ) ) {
+ $post = get_post( $html_or_id );
+
+ if ( !$post )
+ return $images;
+ $html = $post->post_content; // DO NOT apply the_content filters here, it will cause loops
+ }
+
+ if ( !$html )
+ return $images;
+
+ preg_match_all( '!<img.*src="([^"]+)".*/?>!iUs', $html, $matches );
+ if ( !empty( $matches[1] ) ) {
+ foreach ( $matches[1] as $match ) {
+ if ( stristr( $match, '/smilies/' ) )
+ continue;
+
+ $images[] = array(
+ 'type' => 'image',
+ 'from' => 'html',
+ 'src' => html_entity_decode( $match ),
+ 'href' => '', // No link to apply to these. Might potentially parse for that as well, but not for now
+ );
+ }
+ }
+
+ return $images;
+ }
+
+ /**
+ * @param int $post_id The post ID to check
+ * @param int $size
+ * @return Array containing details of the image, or empty array if none.
+ */
+ static function from_blavatar( $post_id, $size = 96 ) {
+ if ( !function_exists( 'blavatar_domain' ) || !function_exists( 'blavatar_exists' ) || !function_exists( 'blavatar_url' ) ) {
+ return array();
+ }
+
+ $permalink = get_permalink( $post_id );
+ $domain = blavatar_domain( $permalink );
+
+ if ( !blavatar_exists( $domain ) ) {
+ return array();
+ }
+
+ $url = blavatar_url( $domain, 'img', $size );
+
+ return array( array(
+ 'type' => 'image',
+ 'from' => 'blavatar',
+ 'src' => $url,
+ 'src_width' => $size,
+ 'src_height' => $size,
+ 'href' => $permalink,
+ ) );
+ }
+
+ /**
+ * @param int $post_id The post ID to check
+ * @param int $size
+ * @param string $default The default image to use.
+ * @return Array containing details of the image, or empty array if none.
+ */
+ static function from_gravatar( $post_id, $size = 96, $default = false ) {
+ $post = get_post( $post_id );
+ $permalink = get_permalink( $post_id );
+
+ if ( function_exists( 'get_avatar_url' ) ) {
+ $url = get_avatar_url( $post->post_author, $size, $default, true );
+ if ( $url && is_array( $url ) ) {
+ $url = $url[0];
+ }
+ } else {
+ $has_filter = has_filter( 'pre_option_show_avatars', '__return_true' );
+ if ( !$has_filter ) {
+ add_filter( 'pre_option_show_avatars', '__return_true' );
+ }
+ $avatar = get_avatar( $post->post_author, $size, $default );
+ if ( !$has_filter ) {
+ remove_filter( 'pre_option_show_avatars', '__return_true' );
+ }
+
+ if ( !$avatar ) {
+ return array();
+ }
+
+ if ( !preg_match( '/src=["\']([^"\']+)["\']/', $avatar, $matches ) ) {
+ return array();
+ }
+
+ $url = wp_specialchars_decode( $matches[1], ENT_QUOTES );
+ }
+
+ return array( array(
+ 'type' => 'image',
+ 'from' => 'gravatar',
+ 'src' => $url,
+ 'src_width' => $size,
+ 'src_height' => $size,
+ 'href' => $permalink,
+ ) );
+ }
+
+ /**
+ * Run through the different methods that we have available to try to find a single good
+ * display image for this post.
+ * @param int $post_id
+ * @param array $args Other arguments (currently width and height required for images where possible to determine)
+ * @return Array containing details of the best image to be used
+ */
+ static function get_image( $post_id, $args = array() ) {
+ $image = '';
+ do_action( 'jetpack_postimages_pre_get_image', $post_id );
+ $media = self::get_images( $post_id, $args );
+
+
+ if ( is_array( $media ) ) {
+ foreach ( $media as $item ) {
+ if ( 'image' == $item['type'] ) {
+ $image = $item;
+ break;
+ }
+ }
+ }
+
+ do_action( 'jetpack_postimages_post_get_image', $post_id );
+
+ return $image;
+ }
+
+ /**
+ * Get an array containing a collection of possible images for this post, stopping once we hit a method
+ * that returns something useful.
+ * @param int $post_id
+ * @param array $args Optional args, see defaults list for details
+ * @return Array containing images that would be good for representing this post
+ */
+ static function get_images( $post_id, $args = array() ) {
+ // Figure out which image to attach to this post.
+ $media = false;
+
+ $media = apply_filters( 'jetpack_images_pre_get_images', $media, $post_id, $args );
+ if ( $media )
+ return $media;
+
+ $defaults = array(
+ 'width' => 200, // Required minimum width (if possible to determine)
+ 'height' => 200, // Required minimum height (if possible to determine)
+
+ 'fallback_to_avatars' => false, // Optionally include Blavatar and Gravatar (in that order) in the image stack
+ 'avatar_size' => 96, // Used for both Grav and Blav
+ 'gravatar_default' => false, // Default image to use if we end up with no Gravatar
+
+ 'from_thumbnail' => true, // Use these flags to specifcy which methods to use to find an image
+ 'from_slideshow' => true,
+ 'from_gallery' => true,
+ 'from_attachment' => true,
+ 'from_html' => true,
+
+ 'html_content' => '' // HTML string to pass to from_html()
+ );
+ $args = wp_parse_args( $args, $defaults );
+
+ $media = false;
+ if ( $args['from_thumbnail'] )
+ $media = self::from_thumbnail( $post_id, $args['width'], $args['height'] );
+ if ( !$media && $args['from_slideshow'] )
+ $media = self::from_slideshow( $post_id, $args['width'], $args['height'] );
+ if ( !$media && $args['from_gallery'] )
+ $media = self::from_gallery( $post_id );
+ if ( !$media && $args['from_attachment'] )
+ $media = self::from_attachment( $post_id, $args['width'], $args['height'] );
+ if ( !$media && $args['from_html'] ) {
+ if ( empty( $args['html_content'] ) )
+ $media = self::from_html( $post_id ); // Use the post_id, which will load the content
+ else
+ $media = self::from_html( $args['html_content'] ); // If html_content is provided, use that
+ }
+
+ if ( !$media && $args['fallback_to_avatars'] ) {
+ $media = self::from_blavatar( $post_id, $args['avatar_size'] );
+ if ( !$media )
+ $media = self::from_gravatar( $post_id, $args['avatar_size'], $args['gravatar_default'] );
+ }
+
+ return apply_filters( 'jetpack_images_get_images', $media, $post_id, $args );
+ }
+}
diff --git a/plugins/jetpack/class.jetpack-signature.php b/plugins/jetpack/class.jetpack-signature.php
index b5718846..975375ab 100644
--- a/plugins/jetpack/class.jetpack-signature.php
+++ b/plugins/jetpack/class.jetpack-signature.php
@@ -17,21 +17,32 @@ class Jetpack_Signature {
$this->time_diff = $time_diff;
}
- function sign_current_request( $override = null ) {
+ function sign_current_request( $override = array() ) {
+ if ( isset( $override['scheme'] ) ) {
+ $scheme = $override['scheme'];
+ if ( !in_array( $scheme, array( 'http', 'https' ) ) ) {
+ return new Jetpack_Error( 'invalid_sheme', 'Invalid URL scheme' );
+ }
+ } else {
+ if ( is_ssl() ) {
+ $scheme = 'https';
+ } else {
+ $scheme = 'http';
+ }
+ }
+
if ( is_ssl() ) {
- $scheme = 'https';
$port = JETPACK_SIGNATURE__HTTPS_PORT == $_SERVER['SERVER_PORT'] ? '' : $_SERVER['SERVER_PORT'];
} else {
- $scheme = 'http';
$port = JETPACK_SIGNATURE__HTTP_PORT == $_SERVER['SERVER_PORT'] ? '' : $_SERVER['SERVER_PORT'];
}
$url = "{$scheme}://{$_SERVER['HTTP_HOST']}:{$port}" . stripslashes( $_SERVER['REQUEST_URI'] );
- if ( isset( $override['body'] ) && !is_null( $override['body'] ) ) {
+ if ( array_key_exists( 'body', $override ) && !is_null( $override['body'] ) ) {
$body = $override['body'];
} else if ( 'POST' == strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
- $body = $GLOBALS['HTTP_RAW_POST_DATA'];
+ $body = isset( $GLOBALS['HTTP_RAW_POST_DATA'] ) ? $GLOBALS['HTTP_RAW_POST_DATA'] : null;
} else {
$body = null;
}
@@ -45,7 +56,8 @@ class Jetpack_Signature {
}
}
- return $this->sign_request( $a['token'], $a['timestamp'], $a['nonce'], $a['body-hash'], $_SERVER['REQUEST_METHOD'], $url, $body, true );
+ $method = isset( $override['method'] ) ? $override['method'] : $_SERVER['REQUEST_METHOD'];
+ return $this->sign_request( $a['token'], $a['timestamp'], $a['nonce'], $a['body-hash'], $method, $url, $body, true );
}
// body_hash v. body-hash is annoying. Refactor to accept an array?
diff --git a/plugins/jetpack/class.jetpack-user-agent.php b/plugins/jetpack/class.jetpack-user-agent.php
new file mode 100644
index 00000000..3ae1bb85
--- /dev/null
+++ b/plugins/jetpack/class.jetpack-user-agent.php
@@ -0,0 +1,1331 @@
+<?php
+
+function jetpack_is_mobile( $kind = 'any', $return_matched_agent = false ) {
+ static $kinds = array( 'smart' => false, 'dumb' => false, 'any' => false );
+ static $first_run = true;
+ static $matched_agent = '';
+
+ $ua_info = new Jetpack_User_Agent_Info();
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) || strpos( strtolower( $_SERVER['HTTP_USER_AGENT'] ), 'ipad' ) )
+ return false;
+
+ if( $ua_info->is_android_tablet() && $ua_info->is_kindle_touch() === false )
+ return false;
+
+ if( $ua_info->is_blackberry_tablet() )
+ return false;
+
+ if ( $first_run ) {
+ $first_run = false;
+
+ //checks for iPhoneTier devices & RichCSS devices
+ if ( $ua_info->isTierIphone() || $ua_info->isTierRichCSS() ) {
+ $kinds['smart'] = true;
+ $matched_agent = $ua_info->matched_agent;
+ }
+
+ if ( !$kinds['smart'] ) {
+ // if smart, we are not dumb so no need to check
+ $dumb_agents = $ua_info->dumb_agents;
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ foreach ( $dumb_agents as $dumb_agent ) {
+ if ( false !== strpos( $agent, $dumb_agent ) ) {
+ $kinds['dumb'] = true;
+ $matched_agent = $dumb_agent;
+ break;
+ }
+ }
+
+ if ( !$kinds['dumb'] ) {
+ if ( isset( $_SERVER['HTTP_X_WAP_PROFILE'] ) ) {
+ $kinds['dumb'] = true;
+ $matched_agent = 'http_x_wap_profile';
+ } elseif ( isset( $_SERVER['HTTP_ACCEPT']) && ( preg_match( '/wap\.|\.wap/i', $_SERVER['HTTP_ACCEPT'] ) || false !== strpos( strtolower( $_SERVER['HTTP_ACCEPT'] ), 'application/vnd.wap.xhtml+xml' ) ) ) {
+ $kinds['dumb'] = true;
+ $matched_agent = 'vnd.wap.xhtml+xml';
+ }
+ }
+ }
+
+ if ( $kinds['dumb'] || $kinds['smart'] )
+ $kinds['any'] = true;
+ }
+
+ if ( $return_matched_agent )
+ return $matched_agent;
+
+ return $kinds[$kind];
+}
+
+class Jetpack_User_Agent_Info {
+
+ var $useragent;
+ var $matched_agent;
+ var $isTierIphone; //Stores whether is the iPhone tier of devices.
+ var $isTierRichCss; //Stores whether the device can probably support Rich CSS, but JavaScript (jQuery) support is not assumed.
+ var $isTierGenericMobile; //Stores whether it is another mobile device, which cannot be assumed to support CSS or JS (eg, older BlackBerry, RAZR)
+
+ private $_platform = null; //Stores the device platform name
+ const PLATFORM_WINDOWS = 'windows';
+ const PLATFORM_IPHONE = 'iphone';
+ const PLATFORM_IPOD = 'ipod';
+ const PLATFORM_IPAD = 'ipad';
+ const PLATFORM_BLACKBERRY = 'blackberry';
+ const PLATFORM_BLACKBERRY_10 = 'blackberry_10';
+ const PLATFORM_SYMBIAN = 'symbian_series60';
+ const PLATFORM_SYMBIAN_S40 = 'symbian_series40';
+ const PLATFORM_J2ME_MIDP = 'j2me_midp';
+ const PLATFORM_ANDROID = 'android';
+ const PLATFORM_ANDROID_TABLET = 'android_tablet';
+
+ var $dumb_agents = array(
+ 'nokia', 'blackberry', 'philips', 'samsung', 'sanyo', 'sony', 'panasonic', 'webos',
+ 'ericsson', 'alcatel', 'palm',
+ 'windows ce', 'opera mini', 'series60', 'series40',
+ 'au-mic,', 'audiovox', 'avantgo', 'blazer',
+ 'danger', 'docomo', 'epoc',
+ 'ericy', 'i-mode', 'ipaq', 'midp-',
+ 'mot-', 'netfront', 'nitro',
+ 'palmsource', 'pocketpc', 'portalmmm',
+ 'rover', 'sie-',
+ 'symbian', 'cldc-', 'j2me',
+ 'smartphone', 'up.browser', 'up.link',
+ 'up.link', 'vodafone/', 'wap1.', 'wap2.', 'mobile', 'googlebot-mobile',
+ );
+
+ //The constructor. Initializes default variables.
+ function Jetpack_User_Agent_Info()
+ {
+ if ( !empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ $this->useragent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ }
+
+ /**
+ * This method detects the mobile User Agent name.
+ *
+ * @return string The matched User Agent name, false otherwise.
+ */
+ function get_mobile_user_agent_name() {
+ if( $this->is_chrome_for_iOS( ) ) //keep this check before the safari rule
+ return 'chrome-for-ios';
+ elseif ( $this->is_iphone_or_ipod( 'iphone-safari' ) )
+ return 'iphone';
+ elseif ( $this->is_ipad( 'ipad-safari' ) )
+ return 'ipad';
+ elseif ( $this->is_android_tablet() ) //keep this check before the android rule
+ return 'android_tablet';
+ elseif ( $this->is_android() )
+ return 'android';
+ elseif ( $this->is_blackberry_10() )
+ return 'blackberry_10';
+ elseif ( $this->is_blackbeberry() )
+ return 'blackberry';
+ elseif ( $this->is_WindowsPhone7() )
+ return 'win7';
+ elseif ( $this->is_windows_phone_8() )
+ return 'winphone8';
+ elseif ( $this->is_opera_mini() )
+ return 'opera-mini';
+ elseif ( $this->is_opera_mini_dumb() )
+ return 'opera-mini-dumb';
+ elseif ( $this->is_opera_mobile() )
+ return 'opera-mobi';
+ elseif ( $this->is_blackberry_tablet() )
+ return 'blackberry_tablet';
+ elseif ( $this->is_kindle_fire() )
+ return 'kindle-fire';
+ elseif ( $this->is_PalmWebOS() )
+ return 'webos';
+ elseif ( $this->is_S60_OSSBrowser() )
+ return 'series60';
+ elseif ( $this->is_firefox_mobile() )
+ return 'firefox_mobile';
+ elseif ( $this->is_MaemoTablet() )
+ return 'maemo';
+ elseif ( $this->is_MeeGo() )
+ return 'meego';
+ elseif( $this->is_TouchPad() )
+ return 'hp_tablet';
+ elseif ( $this->is_facebook_for_iphone() )
+ return 'facebook-for-iphone';
+ elseif ( $this->is_facebook_for_ipad() )
+ return 'facebook-for-ipad';
+ elseif ( $this->is_twitter_for_iphone() )
+ return 'twitter-for-iphone';
+ elseif ( $this->is_twitter_for_ipad() )
+ return 'twitter-for-ipad';
+ elseif ( $this->is_wordpress_for_ios() )
+ return 'ios-app';
+ elseif ( $this->is_iphone_or_ipod( 'iphone-not-safari' ) )
+ return 'iphone-unknown';
+ elseif ( $this->is_ipad( 'ipad-not-safari' ) )
+ return 'ipad-unknown';
+ else {
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ $dumb_agents = $this->dumb_agents;
+ foreach ( $dumb_agents as $dumb_agent ) {
+ if ( false !== strpos( $agent, $dumb_agent ) ) {
+ return $dumb_agent;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * This method detects the mobile device's platform. All return strings are from the class constants.
+ * Note that this function returns the platform name, not the UA name/type. You should use a different function
+ * if you need to test the UA capabilites.
+ *
+ * @return string Name of the platform, false otherwise.
+ */
+ public function get_platform() {
+ if ( isset( $this->_platform ) ) {
+ return $this->_platform;
+ }
+
+ if ( strpos( $this->useragent, 'windows phone' ) !== false ) {
+ $this->_platform = self::PLATFORM_WINDOWS;
+ }
+ elseif ( strpos( $this->useragent, 'windows ce' ) !== false ) {
+ $this->_platform = self::PLATFORM_WINDOWS;
+ }
+ elseif ( strpos( $this->useragent, 'ipad' ) !== false ) {
+ $this->_platform = self::PLATFORM_IPAD;
+ }
+ else if ( strpos( $this->useragent, 'ipod' ) !== false ) {
+ $this->_platform = self::PLATFORM_IPOD;
+ }
+ else if ( strpos( $this->useragent, 'iphone' ) !== false ) {
+ $this->_platform = self::PLATFORM_IPHONE;
+ }
+ elseif ( strpos( $this->useragent, 'android' ) !== false ) {
+ if ( $this->is_android_tablet() )
+ $this->_platform = self::PLATFORM_ANDROID_TABLET;
+ else
+ $this->_platform = self::PLATFORM_ANDROID;
+ }
+ elseif ( $this->is_kindle_fire() ) {
+ $this->_platform = self::PLATFORM_ANDROID_TABLET;
+ }
+ elseif ( $this->is_blackberry_10() ) {
+ $this->_platform = self::PLATFORM_BLACKBERRY_10;
+ }
+ elseif ( strpos( $this->useragent, 'blackberry' ) !== false ) {
+ $this->_platform = self::PLATFORM_BLACKBERRY;
+ }
+ elseif ( $this->is_blackberry_tablet() ) {
+ $this->_platform = self::PLATFORM_BLACKBERRY;
+ }
+ elseif ( $this->is_symbian_platform() ) {
+ $this->_platform = self::PLATFORM_SYMBIAN;
+ }
+ elseif ( $this->is_symbian_s40_platform() ) {
+ $this->_platform = self::PLATFORM_SYMBIAN_S40;
+ }
+ elseif ( $this->is_J2ME_platform() ) {
+ $this->_platform = self::PLATFORM_J2ME_MIDP;
+ }
+ else
+ $this->_platform = false;
+
+ return $this->_platform;
+ }
+
+ /*
+ * This method detects for UA which can display iPhone-optimized web content.
+ * Includes iPhone, iPod Touch, Android, WebOS, Fennec (Firefox mobile), etc.
+ *
+ */
+ function isTierIphone() {
+ if ( isset( $this->isTierIphone ) ) {
+ return $this->isTierIphone;
+ }
+ if ( $this->is_iphoneOrIpod() ) {
+ $this->matched_agent = 'iphone';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_android() ) {
+ $this->matched_agent = 'android';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_windows_phone_8() ) {
+ $this->matched_agent = 'winphone8';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_WindowsPhone7() ) {
+ $this->matched_agent = 'win7';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_blackberry_10() ) {
+ $this->matched_agent = 'blackberry-10';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_blackbeberry() && $this->detect_blackberry_browser_version() == 'blackberry-webkit' ) {
+ $this->matched_agent = 'blackberry-webkit';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_blackberry_tablet() ) {
+ $this->matched_agent = 'blackberry_tablet';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_PalmWebOS() ) {
+ $this->matched_agent = 'webos';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_TouchPad() ) {
+ $this->matched_agent = 'hp_tablet';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_firefox_mobile() ) {
+ $this->matched_agent = 'fennec';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_opera_mobile() ) {
+ $this->matched_agent = 'opera-mobi';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_MaemoTablet() ) {
+ $this->matched_agent = 'maemo';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_MeeGo() ) {
+ $this->matched_agent = 'meego';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_kindle_touch() ) {
+ $this->matched_agent = 'kindle-touch';
+ $this->isTierIphone = true;
+ $this->isTierRichCss = false;
+ $this->isTierGenericMobile = false;
+ }
+ else {
+ $this->isTierIphone = false;
+ }
+ return $this->isTierIphone;
+ }
+
+ /*
+ * This method detects for UA which are likely to be capable
+ * but may not necessarily support JavaScript.
+ * Excludes all iPhone Tier UA.
+ *
+ */
+ function isTierRichCss(){
+ if ( isset( $this->isTierRichCss ) ) {
+ return $this->isTierRichCss;
+ }
+ if ($this->isTierIphone())
+ return false;
+
+ //The following devices are explicitly ok.
+ if ( $this->is_S60_OSSBrowser() ) {
+ $this->matched_agent = 'series60';
+ $this->isTierIphone = false;
+ $this->isTierRichCss = true;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_opera_mini() ) {
+ $this->matched_agent = 'opera-mini';
+ $this->isTierIphone = false;
+ $this->isTierRichCss = true;
+ $this->isTierGenericMobile = false;
+ }
+ elseif ( $this->is_blackbeberry() ) {
+ $detectedDevice = $this->detect_blackberry_browser_version();
+ if ( $detectedDevice === 'blackberry-5' || $detectedDevice == 'blackberry-4.7' || $detectedDevice === 'blackberry-4.6' ) {
+ $this->matched_agent = $detectedDevice;
+ $this->isTierIphone = false;
+ $this->isTierRichCss = true;
+ $this->isTierGenericMobile = false;
+ }
+ }
+ else {
+ $this->isTierRichCss = false;
+ }
+
+ return $this->isTierRichCss;
+ }
+
+ // Detects if the user is using a tablet.
+ // props Corey Gilmore, BGR.com
+ function is_tablet() {
+ return ( 0 // never true, but makes it easier to manage our list of tablet conditions
+ || self::is_ipad()
+ || self::is_android_tablet()
+ || self::is_blackberry_tablet()
+ || self::is_kindle_fire()
+ || self::is_MaemoTablet()
+ || self::is_TouchPad()
+ );
+ }
+
+ /*
+ * Detects if the current UA is the default iPhone or iPod Touch Browser.
+ *
+ * DEPRECATED: use is_iphone_or_ipod
+ *
+ */
+ function is_iphoneOrIpod(){
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ if ( ( strpos( $ua, 'iphone' ) !== false ) || ( strpos( $ua,'ipod' ) !== false ) ) {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ }
+ else
+ return false;
+ }
+
+
+ /*
+ * Detects if the current UA is iPhone Mobile Safari or another iPhone or iPod Touch Browser.
+ *
+ * They type can check for any iPhone, an iPhone using Safari, or an iPhone using something other than Safari.
+ *
+ * Note: If you want to check for Opera mini, Opera mobile or Firefox mobile (or any 3rd party iPhone browser),
+ * you should put the check condition before the check for 'iphone-any' or 'iphone-not-safari'.
+ * Otherwise those browsers will be 'catched' by the iphone string.
+ *
+ */
+ function is_iphone_or_ipod( $type = 'iphone-any' ) {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ $is_iphone = ( strpos( $ua, 'iphone' ) !== false ) || ( strpos( $ua,'ipod' ) !== false );
+ $is_safari = ( false !== strpos( $ua, 'safari' ) );
+
+ if ( 'iphone-safari' == $type )
+ return $is_iphone && $is_safari;
+ elseif ( 'iphone-not-safari' == $type )
+ return $is_iphone && !$is_safari;
+ else
+ return $is_iphone;
+ }
+
+
+ /*
+ * Detects if the current UA is Chrome for iOS
+ *
+ * The User-Agent string in Chrome for iOS is the same as the Mobile Safari User-Agent, with CriOS/<ChromeRevision> instead of Version/<VersionNum>.
+ * - 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
+ */
+ function is_chrome_for_iOS( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ if ( self::is_iphone_or_ipod( 'iphone-safari' ) === false ) return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'crios/' ) !== false )
+ return true;
+ else
+ return false;
+ }
+
+
+ /*
+ * Detects if the current UA is Twitter for iPhone
+ *
+ * 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
+ * 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
+ *
+ */
+ function is_twitter_for_iphone( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'ipad' ) !== false )
+ return false;
+
+ if ( strpos( $ua, 'twitter for iphone' ) !== false )
+ return true;
+ else
+ return false;
+ }
+
+ /*
+ * Detects if the current UA is Twitter for iPad
+ *
+ * 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
+ * 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
+ *
+ */
+ function is_twitter_for_ipad( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'twitter for ipad' ) !== false )
+ return true;
+ elseif( strpos( $ua, 'ipad' ) !== false && strpos( $ua, 'twitter for iphone' ) !== false )
+ return true;
+ else
+ return false;
+ }
+
+
+ /*
+ * Detects if the current UA is Facebook for iPhone
+ * - Facebook 4020.0 (iPhone; iPhone OS 5.0.1; fr_FR)
+ * - 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]
+ * - 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]
+ */
+ function is_facebook_for_iphone( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if( strpos( $ua, 'iphone' ) === false )
+ return false;
+
+ if ( strpos( $ua, 'facebook' ) !== false && strpos( $ua, 'ipad' ) === false )
+ return true;
+ else if ( strpos( $ua, 'fbforiphone' ) !== false && strpos( $ua, 'tablet' ) === false )
+ return true;
+ else if ( strpos( $ua, 'fban/fbios;' ) !== false && strpos( $ua, 'tablet' ) === false ) //FB app v5.0 or higher
+ return true;
+ else
+ return false;
+ }
+
+ /*
+ * Detects if the current UA is Facebook for iPad
+ * - Facebook 4020.0 (iPad; iPhone OS 5.0.1; en_US)
+ * - 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]
+ * - 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]
+ */
+ function is_facebook_for_ipad( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'ipad' ) === false )
+ return false;
+
+ if ( strpos( $ua, 'facebook' ) !== false || strpos( $ua, 'fbforiphone' ) !== false || strpos( $ua, 'fban/fbios;' ) !== false )
+ return true;
+ else
+ return false;
+ }
+
+ /*
+ * Detects if the current UA is WordPress for iOS
+ */
+ function is_wordpress_for_ios( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ if ( strpos( $ua, 'wp-iphone' ) !== false )
+ return true;
+ else
+ return false;
+ }
+
+ /*
+ * Detects if the current device is an iPad.
+ * They type can check for any iPad, an iPad using Safari, or an iPad using something other than Safari.
+ *
+ * Note: If you want to check for Opera mini, Opera mobile or Firefox mobile (or any 3rd party iPad browser),
+ * you should put the check condition before the check for 'iphone-any' or 'iphone-not-safari'.
+ * Otherwise those browsers will be 'catched' by the ipad string.
+ *
+ */
+ function is_ipad( $type = 'ipad-any' ) {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ $is_ipad = ( false !== strpos( $ua, 'ipad' ) );
+ $is_safari = ( false !== strpos( $ua, 'safari' ) );
+
+ if ( 'ipad-safari' == $type )
+ return $is_ipad && $is_safari;
+ elseif ( 'ipad-not-safari' == $type )
+ return $is_ipad && !$is_safari;
+ else
+ return $is_ipad;
+ }
+
+ /*
+ * Detects if the current browser is Firefox Mobile (Fennec)
+ *
+ * http://www.useragentstring.com/pages/Fennec/
+ * Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.1.1) Gecko/20110415 Firefox/4.0.2pre Fennec/4.0.1
+ * Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1
+ */
+ function is_firefox_mobile( ) {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'fennec' ) !== false )
+ return true;
+ else
+ return false;
+ }
+
+
+ /*
+ * Detects if the current browser is Opera Mobile
+ *
+ * What is the difference between Opera Mobile and Opera Mini?
+ * - Opera Mobile is a full Internet browser for mobile devices.
+ * - Opera Mini always uses a transcoder to convert the page for a small display.
+ * (it uses Opera advanced server compression technology to compress web content before it gets to a device.
+ * The rendering engine is on Opera's server.)
+ *
+ * Opera/9.80 (Windows NT 6.1; Opera Mobi/14316; U; en) Presto/2.7.81 Version/11.00"
+ */
+ function is_opera_mobile( ) {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'opera' ) !== false && strpos( $ua, 'mobi' ) !== false )
+ return true;
+ else
+ return false;
+ }
+
+
+ /*
+ * Detects if the current browser is Opera Mini
+ *
+ * Opera/8.01 (J2ME/MIDP; Opera Mini/3.0.6306/1528; en; U; ssr)
+ * Opera/9.80 (Android;Opera Mini/6.0.24212/24.746 U;en) Presto/2.5.25 Version/10.5454
+ * Opera/9.80 (iPhone; Opera Mini/5.0.019802/18.738; U; en) Presto/2.4.15
+ * Opera/9.80 (J2ME/iPhone;Opera Mini/5.0.019802/886; U; ja) Presto/2.4.15
+ * Opera/9.80 (J2ME/iPhone;Opera Mini/5.0.019802/886; U; ja) Presto/2.4.15
+ * Opera/9.80 (Series 60; Opera Mini/5.1.22783/23.334; U; en) Presto/2.5.25 Version/10.54
+ * Opera/9.80 (BlackBerry; Opera Mini/5.1.22303/22.387; U; en) Presto/2.5.25 Version/10.54
+ *
+ */
+ function is_opera_mini( ) {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'opera' ) !== false && strpos( $ua, 'mini' ) !== false )
+ return true;
+ else
+ return false;
+ }
+
+ /*
+ * Detects if the current browser is Opera Mini, but not on a smart device OS(Android, iOS, etc)
+ * Used to send users on dumb devices to m.wor
+ */
+ function is_opera_mini_dumb( ) {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( self::is_opera_mini() ) {
+ if ( strpos( $ua, 'android' ) !== false || strpos( $ua, 'iphone' ) !== false || strpos( $ua, 'ipod' ) !== false
+ || strpos( $ua, 'ipad' ) !== false || strpos( $ua, 'blackberry' ) !== false)
+ return false;
+ else
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /*
+ * Detects if the current browser is Opera Mobile or Mini.
+ * DEPRECATED: use is_opera_mobile or is_opera_mini
+ *
+ * Opera Mini 5 Beta: Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.15650/756; U; en) Presto/2.2.0
+ * Opera Mini 8: Opera/8.01 (J2ME/MIDP; Opera Mini/3.0.6306/1528; en; U; ssr)
+ */
+ function is_OperaMobile() {
+ _deprecated_function( __FUNCTION__, 'always', 'is_opera_mini() or is_opera_mobile()' );
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'opera' ) !== false ) {
+ if ( ( strpos( $ua, 'mini' ) !== false ) || ( strpos( $ua,'mobi' ) !== false ) )
+ return true;
+ else
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ /*
+ * Detects if the current browser is a Windows Phone 7 device.
+ * ex: Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; LG; GW910)
+ */
+ function is_WindowsPhone7() {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'windows phone os 7' ) === false ) {
+ return false;
+ } else {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ }
+ }
+
+ /*
+ * Detects if the current browser is a Windows Phone 8 device.
+ * ex: Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; ARM; Touch; IEMobile/10.0; <Manufacturer>; <Device> [;<Operator>])
+ */
+ function is_windows_phone_8() {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ if ( strpos( $ua, 'windows phone 8' ) === false ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+ /*
+ * Detects if the current browser is on a Palm device running the new WebOS. This EXCLUDES TouchPad.
+ *
+ * ex1: Mozilla/5.0 (webOS/1.4.0; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pre/1.1
+ * 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
+ *
+ */
+ function is_PalmWebOS() {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'webos' ) === false ) {
+ return false;
+ } else {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ }
+ }
+
+ /*
+ * Detects if the current browser is the HP TouchPad default browser. This excludes phones wt WebOS.
+ *
+ * TouchPad Emulator: Mozilla/5.0 (hp-desktop; Linux; hpwOS/2.0; U; it-IT) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 Desktop/1.0
+ * 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
+ *
+ */
+ function is_TouchPad() {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $http_user_agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ if ( false !== strpos( $http_user_agent, 'hp-tablet' ) || false !== strpos( $http_user_agent, 'hpwos' ) || false !== strpos( $http_user_agent, 'touchpad' ) ) {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ }
+ else
+ return false;
+ }
+
+
+ /*
+ * Detects if the current browser is the Series 60 Open Source Browser.
+ *
+ * OSS Browser 3.2 on E75: Mozilla/5.0 (SymbianOS/9.3; U; Series60/3.2 NokiaE75-1/110.48.125 Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413
+ *
+ * 7.0 Browser (Nokia 5800 XpressMusic (v21.0.025)) : Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 Nokia5800d-1/21.0.025; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413
+ *
+ * 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
+ *
+ */
+ function is_S60_OSSBrowser() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+
+ $pos_webkit = strpos( $agent, 'webkit' );
+ if ( $pos_webkit !== false ) {
+ //First, test for WebKit, then make sure it's either Symbian or S60.
+ if ( strpos( $agent, 'symbian' ) !== false || strpos( $agent, 'series60' ) !== false ) {
+ return true;
+ } else
+ return false;
+ } elseif ( strpos( $agent, 'symbianos' ) !== false && strpos( $agent,'series60' ) !== false ) {
+ return true;
+ } elseif ( strpos( $agent, 'nokia' ) !== false && strpos( $agent,'series60' ) !== false ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /*
+ *
+ * Detects if the device platform is the Symbian Series 60.
+ *
+ */
+ function is_symbian_platform() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ $pos_webkit = strpos( $agent, 'webkit' );
+ if ( $pos_webkit !== false ) {
+ //First, test for WebKit, then make sure it's either Symbian or S60.
+ if ( strpos( $agent, 'symbian' ) !== false || strpos( $agent, 'series60' ) !== false ) {
+ return true;
+ } else
+ return false;
+ } elseif ( strpos( $agent, 'symbianos' ) !== false && strpos( $agent,'series60' ) !== false ) {
+ return true;
+ } elseif ( strpos( $agent, 'nokia' ) !== false && strpos( $agent,'series60' ) !== false ) {
+ return true;
+ } elseif ( strpos( $agent, 'opera mini' ) !== false ) {
+ if( strpos( $agent,'symbianos' ) !== false || strpos( $agent,'symbos' ) !== false || strpos( $agent,'series 60' ) !== false )
+ return true;
+ }
+
+ return false;
+ }
+
+ /*
+ *
+ * Detects if the device platform is the Symbian Series 40.
+ * Nokia Browser for Series 40 is a proxy based browser, previously known as Ovi Browser.
+ * This browser will report 'NokiaBrowser' in the header, however some older version will also report 'OviBrowser'.
+ *
+ */
+ function is_symbian_s40_platform() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $agent, 'series40' ) !== false ) {
+ if( strpos( $agent,'nokia' ) !== false || strpos( $agent,'ovibrowser' ) !== false || strpos( $agent,'nokiabrowser' ) !== false )
+ return true;
+ }
+
+ return false;
+ }
+
+ function is_J2ME_platform() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $agent, 'j2me/midp' ) !== false ) {
+ return true;
+ } elseif ( strpos( $agent, 'midp' ) !== false && strpos( $agent, 'cldc' ) ) {
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /*
+ * Detects if the current UA is on one of the Maemo-based Nokia Internet Tablets.
+ */
+ function is_MaemoTablet() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ $pos_maemo = strpos( $agent, 'maemo' );
+ if ( $pos_maemo === false ) return false;
+
+ //Must be Linux + Tablet, or else it could be something else.
+ if ( strpos( $agent, 'tablet' ) !== false && strpos( $agent, 'linux' ) !== false ) {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ } else
+ return false;
+ }
+
+ /*
+ * Detects if the current UA is a MeeGo device (Nokia Smartphone).
+ */
+ function is_MeeGo() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( strpos( $ua, 'meego' ) === false ) {
+ return false;
+ } else {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ }
+ }
+
+
+ /*
+ is_webkit() can be used to check the User Agent for an webkit generic browser
+ */
+ function is_webkit() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ $pos_webkit = strpos( $agent, 'webkit' );
+
+ if ( $pos_webkit !== false )
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Detects if the current browser is the Native Android browser.
+ * @return boolean true if the browser is Android otherwise false
+ */
+ function is_android() {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ $pos_android = strpos( $agent, 'android' );
+ if ( $pos_android !== false ) {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ }
+ else
+ return false;
+ }
+
+
+ /**
+ * Detects if the current browser is the Native Android Tablet browser.
+ * Assumes 'Android' should be in the user agent, but not 'mobile'
+ *
+ * @return boolean true if the browser is Android and not 'mobile' otherwise false
+ */
+ function is_android_tablet( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ $pos_android = strpos( $agent, 'android' );
+ $pos_mobile = strpos( $agent, 'mobile' );
+ $post_android_app = strpos( $agent, 'wp-android' );
+
+ if ( $pos_android !== false && $pos_mobile === false && $post_android_app === false ) {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ } else
+ return false;
+ }
+
+ /**
+ * Detects if the current browser is the Kindle Fire Native browser.
+ *
+ * Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-84) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true
+ * Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-84) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=false
+ *
+ * @return boolean true if the browser is Kindle Fire Native browser otherwise false
+ */
+ function is_kindle_fire( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ $pos_silk = strpos( $agent, 'silk/' );
+ $pos_silk_acc = strpos( $agent, 'silk-accelerated=' );
+ if ( $pos_silk !== false && $pos_silk_acc !== false )
+ return true;
+ else
+ return false;
+ }
+
+
+/**
+ * Detects if the current browser is the Kindle Touch Native browser
+ *
+ * Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+
+ *
+ * @return boolean true if the browser is Kindle monochrome Native browser otherwise false
+ */
+ function is_kindle_touch( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ $pos_kindle_touch = strpos( $agent, 'kindle/3.0+' );
+ if ( $pos_kindle_touch !== false && self::is_kindle_fire() === false )
+ return true;
+ else
+ return false;
+ }
+
+
+ // Detect if user agent is the WordPress.com Windows 8 app (used ONLY on the custom oauth stylesheet)
+ function is_windows8_auth( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ $pos = strpos( $agent, 'msauthhost' );
+ if ( $pos !== false )
+ return true;
+ else
+ return false;
+ }
+
+ // Detect if user agent is the WordPress.com Windows 8 app.
+ function is_wordpress_for_win8( ) {
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ $pos = strpos( $agent, 'wp-windows8' );
+ if ( $pos !== false )
+ return true;
+ else
+ return false;
+ }
+
+
+ /*
+ * is_blackberry_tablet() can be used to check the User Agent for a RIM blackberry tablet
+ * The user agent of the BlackBerry® Tablet OS follows a format similar to the following:
+ * 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+
+ *
+ */
+ function is_blackberry_tablet() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ $pos_playbook = stripos( $agent, 'PlayBook' );
+ $pos_rim_tablet = stripos( $agent, 'RIM Tablet' );
+
+ if ( ($pos_playbook === false) || ($pos_rim_tablet === false) )
+ {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /*
+ is_blackbeberry() can be used to check the User Agent for a blackberry device
+ Note that opera mini on BB matches this rule.
+ */
+ function is_blackbeberry() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ $pos_blackberry = strpos( $agent, 'blackberry' );
+ if ( $pos_blackberry !== false ) {
+ if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
+ return false;
+ else
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /*
+ is_blackberry_10() can be used to check the User Agent for a BlackBerry 10 device.
+ */
+ function is_blackberry_10() {
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+ return ( strpos( $agent, 'bb10' ) !== false ) && ( strpos( $agent, 'mobile' ) !== false );
+ }
+
+ /**
+ * Retrieve the blackberry OS version.
+ *
+ * Return strings are from the following list:
+ * - blackberry-10
+ * - blackberry-7
+ * - blackberry-6
+ * - blackberry-torch //only the first edition. The 2nd edition has the OS7 onboard and doesn't need any special rule.
+ * - blackberry-5
+ * - blackberry-4.7
+ * - blackberry-4.6
+ * - blackberry-4.5
+ *
+ * @return string Version of the BB OS.
+ * If version is not found, get_blackbeberry_OS_version will return boolean false.
+ */
+ function get_blackbeberry_OS_version() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ if ( self::is_blackberry_10() )
+ return 'blackberry-10';
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ $pos_blackberry = stripos( $agent, 'blackberry' );
+ if ( $pos_blackberry === false ) {
+ //not a blackberry device
+ return false;
+ }
+
+ //blackberry devices OS 6.0 or higher
+ //Mozilla/5.0 (BlackBerry; U; BlackBerry 9670; en) AppleWebKit/534.3+ (KHTML, like Gecko) Version/6.0.0.286 Mobile Safari/534.3+
+ //Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1+
+ //Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0 Mobile Safari/534.11+
+ $pos_webkit = stripos( $agent, 'webkit' );
+ if ( $pos_webkit !== false ) {
+ //detected blackberry webkit browser
+ $pos_torch = stripos( $agent, 'BlackBerry 9800' );
+ if ( $pos_torch !== false ) {
+ return 'blackberry-torch'; //match the torch first edition. the 2nd edition should use the OS7 and doesn't need any special rule
+ } else {
+ //detecting the BB OS version for devices running OS 6.0 or higher
+ if ( preg_match( '#Version\/([\d\.]+)#i', $agent, $matches ) ) {
+ $version = $matches[1];
+ $version_num = explode( '.', $version );
+ if( is_array( $version_num ) === false || count( $version_num ) <= 1 )
+ return 'blackberry-6'; //not a BB device that match our rule.
+ else
+ return 'blackberry-'.$version_num[0];
+ } else {
+ //if doesn't match returns the minimun version with a webkit browser. we should never fall here.
+ return 'blackberry-6'; //not a BB device that match our rule.
+ }
+ }
+ }
+
+ //blackberry devices <= 5.XX
+ //BlackBerry9000/5.0.0.93 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/179
+ if ( preg_match( '#BlackBerry\w+\/([\d\.]+)#i', $agent, $matches ) ) {
+ $version = $matches[1];
+ } else {
+ return false; //not a BB device that match our rule.
+ }
+
+ $version_num = explode( '.', $version );
+
+ if( is_array( $version_num ) === false || count( $version_num ) <= 1 )
+ return false;
+ if ( $version_num[0] == 5 ) {
+ return 'blackberry-5';
+ } elseif ( $version_num[0] == 4 && $version_num[1] == 7 ) {
+ return 'blackberry-4.7';
+ } elseif ( $version_num[0] == 4 && $version_num[1] == 6 ) {
+ return 'blackberry-4.6';
+ } elseif ( $version_num[0] == 4 && $version_num[1] == 5 ) {
+ return 'blackberry-4.5';
+ } else {
+ return false;
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve the blackberry browser version.
+ *
+ * Return string are from the following list:
+ * - blackberry-10
+ * - blackberry-webkit
+ * - blackberry-5
+ * - blackberry-4.7
+ * - blackberry-4.6
+ *
+ * @return string Type of the BB browser.
+ * If browser's version is not found, detect_blackbeberry_browser_version will return boolean false.
+ */
+ function detect_blackberry_browser_version() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( self::is_blackberry_10() )
+ return 'blackberry-10';
+
+ $pos_blackberry = strpos( $agent, 'blackberry' );
+ if ( $pos_blackberry === false ) {
+ //not a blackberry device
+ return false;
+ }
+
+ $pos_webkit = strpos( $agent, 'webkit' );
+
+ if ( ! ( $pos_webkit === false ) ) {
+ return 'blackberry-webkit';
+ } else {
+ if ( preg_match( '#BlackBerry\w+\/([\d\.]+)#i', $agent, $matches ) ) {
+ $version = $matches[1];
+ } else {
+ return false; //not a BB device that match our rule.
+ }
+
+ $version_num = explode( '.', $version );
+
+ if( is_array( $version_num ) === false || count( $version_num ) <= 1 )
+ return false;
+
+ if ( $version_num[0] == 5 ) {
+ return 'blackberry-5';
+ } elseif ( $version_num[0] == 4 && $version_num[1] == 7 ) {
+ return 'blackberry-4.7';
+ } elseif ( $version_num[0] == 4 && $version_num[1] == 6 ) {
+ return 'blackberry-4.6';
+ } else {
+ //A very old BB device is found or this is a BB device that doesn't match our rules.
+ return false;
+ }
+ }
+ return false;
+ }
+
+ //Checks if a visitor is coming from one of the WordPress mobile apps
+ function is_mobile_app() {
+
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+ return false;
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ if ( isset( $_SERVER['X_USER_AGENT'] ) && preg_match( '|wp-webos|', $_SERVER['X_USER_AGENT'] ) )
+ return true; //wp4webos 1.1 or higher
+
+ $app_agents = array( 'wp-android', 'wp-blackberry', 'wp-iphone', 'wp-nokia', 'wp-webos', 'wp-windowsphone' );
+ // the mobile reader on iOS has an incorrect UA when loading the reader
+ // currently it is the default one provided by the iOS framework which
+ // causes problems with 2-step-auth
+ // User-Agent WordPress/3.1.4 CFNetwork/609 Darwin/13.0.0
+ $app_agents[] = 'wordpress/3.1';
+
+ foreach ( $app_agents as $app_agent ) {
+ if ( false !== strpos( $agent, $app_agent ) )
+ return true;
+ }
+ return false;
+ }
+
+ static function is_bot() {
+ static $is_bot = false;
+ static $first_run = true;
+
+ if ( $first_run ) {
+ $first_run = false;
+
+ /*
+ $bot_ips = array( );
+
+ foreach ( $bot_ips as $bot_ip ) {
+ if ( $_SERVER['REMOTE_ADDR'] == $bot_ip )
+ $is_bot = true;
+ }
+ */
+
+ $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+ $bot_agents = array(
+ 'alexa', 'altavista', 'ask jeeves', 'attentio', 'baiduspider', 'bingbot', 'chtml generic', 'crawler', 'fastmobilecrawl',
+ 'feedfetcher-google', 'firefly', 'froogle', 'gigabot', 'googlebot', 'googlebot-mobile', 'heritrix', 'ia_archiver', 'irlbot',
+ 'infoseek', 'jumpbot', 'lycos', 'mediapartners', 'mediobot', 'motionbot', 'msnbot', 'mshots', 'openbot',
+ 'pythumbnail', 'scooter', 'slurp', 'snapbot', 'spider', 'surphace scout', 'taptubot', 'technoratisnoop',
+ 'teoma', 'twiceler', 'yahooseeker', 'yahooysmcm', 'yammybot',
+ );
+
+ foreach ( $bot_agents as $bot_agent ) {
+ if ( false !== strpos( $agent, $bot_agent ) )
+ $is_bot = true;
+ }
+ }
+
+ return $is_bot;
+ }
+}
diff --git a/plugins/jetpack/class.jetpack-xmlrpc-server.php b/plugins/jetpack/class.jetpack-xmlrpc-server.php
index cf01db52..3aa5adb1 100644
--- a/plugins/jetpack/class.jetpack-xmlrpc-server.php
+++ b/plugins/jetpack/class.jetpack-xmlrpc-server.php
@@ -10,22 +10,37 @@ class Jetpack_XMLRPC_Server {
var $error = null;
/**
- * Whitelist of the XML-RPC methods available to the Jetpack Server. If the
+ * Whitelist of the XML-RPC methods available to the Jetpack Server. If the
* user is not authenticated (->login()) then the methods are never added,
* so they will get a "does not exist" error.
*/
- function xmlrpc_methods() {
- if ( !$user = $this->login() ) {
- return array();
+ function xmlrpc_methods( $core_methods ) {
+ $jetpack_methods = array(
+ 'jetpack.jsonAPI' => array( $this, 'json_api' ),
+ 'jetpack.verifyAction' => array( $this, 'verify_action' ),
+ );
+
+ $user = $this->login();
+
+ if ( $user ) {
+ $jetpack_methods = array_merge( $jetpack_methods, array(
+ 'jetpack.testConnection' => array( $this, 'test_connection' ),
+ 'jetpack.testAPIUserCode' => array( $this, 'test_api_user_code' ),
+ 'jetpack.featuresAvailable' => array( $this, 'features_available' ),
+ 'jetpack.featuresEnabled' => array( $this, 'features_enabled' ),
+ 'jetpack.getPost' => array( $this, 'get_post' ),
+ 'jetpack.getPosts' => array( $this, 'get_posts' ),
+ 'jetpack.getComment' => array( $this, 'get_comment' ),
+ 'jetpack.getComments' => array( $this, 'get_comments' ),
+ ) );
+
+ if ( isset( $core_methods['metaWeblog.editPost'] ) ) {
+ $jetpack_methods['metaWeblog.newMediaObject'] = $core_methods['metaWeblog.newMediaObject'];
+ $jetpack_methods['jetpack.updateAttachmentParent'] = array( $this, 'update_attachment_parent' );
+ }
}
- return apply_filters( 'jetpack_xmlrpc_methods', array(
- 'jetpack.testConnection' => array( $this, 'test_connection' ),
- 'jetpack.featuresAvailable' => array( $this, 'features_available' ),
- 'jetpack.featuresEnabled' => array( $this, 'features_enabled' ),
- 'jetpack.getPost' => array( $this, 'get_post' ),
- 'jetpack.getComment' => array( $this, 'get_comment' ),
- ) );
+ return apply_filters( 'jetpack_xmlrpc_methods', $jetpack_methods, $core_methods, $user );
}
/**
@@ -34,12 +49,18 @@ class Jetpack_XMLRPC_Server {
function bootstrap_xmlrpc_methods() {
return array(
'jetpack.verifyRegistration' => array( $this, 'verify_registration' ),
+ 'jetpack.verifyAction' => array( $this, 'verify_action' ),
);
}
/**
- * Verifies that Jetpack.WordPress.com received a registration request from this site
- *
+ * Verifies that Jetpack.WordPress.com received a registration request from this site
+ */
+ function verify_registration( $verify_secret ) {
+ return $this->verify_action( array( 'register', $verify_secret ) );
+ }
+
+ /**
* @return WP_Error|string secret_2 on success, WP_Error( error_code => error_code, error_message => error description, error_data => status code ) on failure
*
* Possible error_codes:
@@ -49,31 +70,34 @@ class Jetpack_XMLRPC_Server {
* verify_secrets_missing: No longer have verification secrets stored
* verify_secrets_mismatch: stored secret_1 does not match secret_1 sent by Jetpack.WordPress.com
*/
- function verify_registration( $verify_secret ) {
+ function verify_action( $params ) {
+ $action = $params[0];
+ $verify_secret = $params[1];
+
if ( empty( $verify_secret ) ) {
return $this->error( new Jetpack_Error( 'verify_secret_1_missing', sprintf( 'The required "%s" parameter is missing.', 'secret_1' ), 400 ) );
} else if ( !is_string( $verify_secret ) ) {
return $this->error( new Jetpack_Error( 'verify_secret_1_malformed', sprintf( 'The required "%s" parameter is malformed.', 'secret_1' ), 400 ) );
}
- $secrets = Jetpack::get_option( 'register' );
+ $secrets = Jetpack::get_option( $action );
if ( !$secrets || is_wp_error( $secrets ) ) {
- Jetpack::delete_option( 'register' );
+ Jetpack::delete_option( $action );
return $this->error( new Jetpack_Error( 'verify_secrets_missing', 'Verification took too long', 400 ) );
}
@list( $secret_1, $secret_2, $secret_eol ) = explode( ':', $secrets );
if ( empty( $secret_1 ) || empty( $secret_2 ) || empty( $secret_eol ) || $secret_eol < time() ) {
- Jetpack::delete_option( 'register' );
+ Jetpack::delete_option( $action );
return $this->error( new Jetpack_Error( 'verify_secrets_missing', 'Verification took too long', 400 ) );
}
if ( $verify_secret !== $secret_1 ) {
- Jetpack::delete_option( 'register' );
+ Jetpack::delete_option( $action );
return $this->error( new Jetpack_Error( 'verify_secrets_mismatch', 'Secret mismatch', 400 ) );
}
- Jetpack::delete_option( 'register' );
+ Jetpack::delete_option( $action );
return $secret_2;
}
@@ -132,7 +156,50 @@ class Jetpack_XMLRPC_Server {
* @return bool|IXR_Error
*/
function test_connection() {
- return true;
+ return JETPACK__VERSION;
+ }
+
+ function test_api_user_code( $args ) {
+ $client_id = (int) $args[0];
+ $user_id = (int) $args[1];
+ $nonce = (string) $args[2];
+ $verify = (string) $args[3];
+
+ if ( !$client_id || !$user_id || !strlen( $nonce ) || 32 !== strlen( $verify ) ) {
+ return false;
+ }
+
+ $user = get_user_by( 'id', $user_id );
+ if ( !$user || is_wp_error( $user ) ) {
+ return false;
+ }
+
+ /* debugging
+ error_log( "CLIENT: $client_id" );
+ error_log( "USER: $user_id" );
+ error_log( "NONCE: $nonce" );
+ error_log( "VERIFY: $verify" );
+ */
+
+ $jetpack_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
+
+ $api_user_code = get_user_meta( $user_id, "jetpack_json_api_$client_id", true );
+ if ( !$api_user_code ) {
+ return false;
+ }
+
+ $hmac = hash_hmac( 'md5', json_encode( (object) array(
+ 'client_id' => (int) $client_id,
+ 'user_id' => (int) $user_id,
+ 'nonce' => (string) $nonce,
+ 'code' => (string) $api_user_code,
+ ) ), $jetpack_token->secret );
+
+ if ( $hmac !== $verify ) {
+ return false;
+ }
+
+ return $user_id;
}
/**
@@ -164,35 +231,137 @@ class Jetpack_XMLRPC_Server {
return $modules;
}
-
+
function get_post( $id ) {
if ( !$id = (int) $id ) {
return false;
}
$jetpack = Jetpack::init();
- $post = $jetpack->get_post( $id );
- if ( $jetpack->is_post_public( $post ) )
- return $post;
+ $post = $jetpack->sync->get_post( $id );
+ return $post;
+ }
- return false;
+ function get_posts( $args ) {
+ list( $post_ids ) = $args;
+ $post_ids = array_map( 'intval', (array) $post_ids );
+ $jp = Jetpack::init();
+ $sync_data = $jp->sync->get_content( array( 'posts' => $post_ids ) );
+
+ return $sync_data;
}
-
+
function get_comment( $id ) {
if ( !$id = (int) $id ) {
return false;
}
$jetpack = Jetpack::init();
- $comment = $jetpack->get_comment( $id );
+ $comment = $jetpack->sync->get_comment( $id );
if ( !is_array( $comment ) )
return false;
- if ( !$this->get_post( $comment['comment_post_ID'] ) )
+ $post = $jetpack->sync->get_post( $comment['comment_post_ID'] );
+ if ( !$post ) {
return false;
+ }
return $comment;
}
+
+ function get_comments( $args ) {
+ list( $comment_ids ) = $args;
+ $comment_ids = array_map( 'intval', (array) $comment_ids );
+ $jp = Jetpack::init();
+ $sync_data = $jp->sync->get_content( array( 'comments' => $comment_ids ) );
+
+ return $sync_data;
+ }
+
+ function update_attachment_parent( $args ) {
+ $attachment_id = (int) $args[0];
+ $parent_id = (int) $args[1];
+
+ return wp_update_post( array(
+ 'ID' => $attachment_id,
+ 'post_parent' => $parent_id,
+ ) );
+ }
+
+ function json_api( $args = array() ) {
+ $json_api_args = $args[0];
+ $verify_api_user_args = $args[1];
+
+ $method = (string) $json_api_args[0];
+ $url = (string) $json_api_args[1];
+ $post_body = is_null( $json_api_args[2] ) ? null : (string) $json_api_args[2];
+ $my_id = (int) $json_api_args[3];
+ $user_details = (array) $json_api_args[4];
+
+ if ( !$verify_api_user_args ) {
+ $user_id = 0;
+ } elseif ( 'internal' === $verify_api_user_args[0] ) {
+ $user_id = (int) $verify_api_user_args[1];
+ if ( $user_id ) {
+ $user = get_user_by( 'id', $user_id );
+ if ( !$user || is_wp_error( $user ) ) {
+ return false;
+ }
+ }
+ } else {
+ $user_id = call_user_func( array( $this, 'test_api_user_code' ), $verify_api_user_args );
+ if ( !$user_id ) {
+ return false;
+ }
+ }
+
+ /* debugging
+ error_log( "-- begin json api via jetpack debugging -- " );
+ error_log( "METHOD: $method" );
+ error_log( "URL: $url" );
+ error_log( "POST BODY: $post_body" );
+ error_log( "MY JETPACK ID: $my_id" );
+ error_log( "VERIFY_ARGS: " . print_r( $verify_api_user_args, 1 ) );
+ error_log( "VERIFIED USER_ID: " . (int) $user_id );
+ error_log( "-- end json api via jetpack debugging -- " );
+ */
+
+ $old_user = wp_get_current_user();
+ wp_set_current_user( $user_id );
+
+ $token = Jetpack_Data::get_access_token( get_current_user_id() );
+ if ( !$token || is_wp_error( $token ) ) {
+ return false;
+ }
+
+ define( 'REST_API_REQUEST', true );
+ define( 'WPCOM_JSON_API__BASE', 'public-api.wordpress.com/rest/v1' );
+
+ // needed?
+ require_once ABSPATH . 'wp-admin/includes/admin.php';
+
+ require_once dirname( __FILE__ ) . '/class.json-api.php';
+ $api = WPCOM_JSON_API::init( $method, $url, $post_body );
+ $api->token_details['user'] = $user_details;
+ require_once dirname( __FILE__ ) . '/class.json-api-endpoints.php';
+
+ $display_errors = ini_set( 'display_errors', 0 );
+ ob_start();
+ $content_type = $api->serve( false );
+ $output = ob_get_clean();
+ ini_set( 'display_errors', $display_errors );
+
+ $nonce = wp_generate_password( 10, false );
+ $hmac = hash_hmac( 'md5', $nonce . $output, $token->secret );
+
+ wp_set_current_user( isset( $old_user->ID ) ? $old_user->ID : 0 );
+
+ return array(
+ (string) $output,
+ (string) $nonce,
+ (string) $hmac,
+ );
+ }
}
diff --git a/plugins/jetpack/class.json-api-endpoints.php b/plugins/jetpack/class.json-api-endpoints.php
new file mode 100644
index 00000000..6189d404
--- /dev/null
+++ b/plugins/jetpack/class.json-api-endpoints.php
@@ -0,0 +1,3912 @@
+<?php
+
+// Endpoint
+abstract class WPCOM_JSON_API_Endpoint {
+ // The API Object
+ var $api;
+
+ var $pass_wpcom_user_details = false;
+ var $can_use_user_details_instead_of_blog_membership = false;
+
+ // One liner.
+ var $description;
+
+ // Object Grouping For Documentation (Users, Posts, Comments)
+ var $group;
+
+ // Stats extra value to bump
+ var $stat;
+
+ // HTTP Method
+ var $method = 'GET';
+
+ // Path at which to serve this endpoint: sprintf() format.
+ var $path = '';
+
+ // Identifiers to fill sprintf() formatted $path
+ var $path_labels = array();
+
+ // Accepted query parameters
+ var $query = array(
+ // Parameter name
+ 'context' => array(
+ // Default value => description
+ 'display' => 'Formats the output as HTML for display. Shortcodes are parsed, paragraph tags are added, etc..',
+ // Other possible values => description
+ 'edit' => 'Formats the output for editing. Shortcodes are left unparsed, significant whitespace is kept, etc..',
+ ),
+ 'http_envelope' => array(
+ 'false' => '',
+ 'true' => 'Some enviroments (like in-browser Javascript or Flash) block or divert responses with a non-200 HTTP status code. Setting this parameter will force the HTTP status code to always be 200. The JSON response is wrapped in an "envelope" containing the "real" HTTP status code and headers.',
+ ),
+ 'pretty' => array(
+ 'false' => '',
+ 'true' => 'Output pretty JSON',
+ ),
+ // Parameter name => description (default value is empty)
+ 'callback' => '(string) An optional JSONP callback function.',
+ );
+
+ // Response format
+ var $response_format = array();
+
+ // Request format
+ var $request_format = array();
+
+ // Is this endpoint still in testing phase? If so, not available to the public.
+ var $in_testing = false;
+
+ /**
+ * @var string Version of the API
+ */
+ var $version = '';
+
+ /**
+ * @var string Example request to make
+ */
+ var $example_request = '';
+
+ /**
+ * @var string Example request data (for POST methods)
+ */
+ var $example_request_data = '';
+
+ /**
+ * @var string Example response from $example_request
+ */
+ var $example_response = '';
+
+ function __construct( $args ) {
+ $defaults = array(
+ 'in_testing' => false,
+ 'description' => '',
+ 'group' => '',
+ 'method' => 'GET',
+ 'path' => '/',
+ 'force' => '',
+ 'jp_disabled' => false,
+ 'path_labels' => array(),
+ 'request_format' => array(),
+ 'response_format' => array(),
+ 'query_parameters' => array(),
+ 'version' => 'v1',
+ 'example_request' => '',
+ 'example_request_data' => '',
+ 'example_response' => '',
+
+ 'pass_wpcom_user_details' => false,
+ 'can_use_user_details_instead_of_blog_membership' => false,
+ );
+
+ $args = wp_parse_args( $args, $defaults );
+
+ $this->in_testing = $args['in_testing'];
+
+ $this->description = $args['description'];
+ $this->group = $args['group'];
+ $this->stat = $args['stat'];
+ $this->force = $args['force'];
+ $this->jp_disabled = $args['jp_disabled'];
+
+ $this->method = $args['method'];
+ $this->path = $args['path'];
+ $this->path_labels = $args['path_labels'];
+
+ $this->pass_wpcom_user_details = $args['pass_wpcom_user_details'];
+ $this->can_use_user_details_instead_of_blog_membership = $args['can_use_user_details_instead_of_blog_membership'];
+
+ $this->version = $args['version'];
+
+ if ( $this->request_format ) {
+ $this->request_format = array_filter( array_merge( $this->request_format, $args['request_format'] ) );
+ } else {
+ $this->request_format = $args['request_format'];
+ }
+
+ if ( $this->response_format ) {
+ $this->response_format = array_filter( array_merge( $this->response_format, $args['response_format'] ) );
+ } else {
+ $this->response_format = $args['response_format'];
+ }
+
+ if ( false === $args['query_parameters'] ) {
+ $this->query = array();
+ } elseif ( is_array( $args['query_parameters'] ) ) {
+ $this->query = array_filter( array_merge( $this->query, $args['query_parameters'] ) );
+ }
+
+ $this->api = WPCOM_JSON_API::init(); // Auto-add to WPCOM_JSON_API
+
+ /** Example Request/Response ******************************************/
+
+ // Examples for endpoint documentation request
+ $this->example_request = $args['example_request'];
+ $this->example_request_data = $args['example_request_data'];
+ $this->example_response = $args['example_response'];
+
+ $this->api->add( $this );
+ }
+
+ // Get all query args. Prefill with defaults
+ function query_args( $return_default_values = true, $cast_and_filter = true ) {
+ $args = array_intersect_key( $this->api->query, $this->query );
+
+ if ( !$cast_and_filter ) {
+ return $args;
+ }
+
+ return $this->cast_and_filter( $args, $this->query, $return_default_values );
+ }
+
+ // Get POST body data
+ function input( $return_default_values = true, $cast_and_filter = true ) {
+ $input = trim( $this->api->post_body );
+
+ switch ( $this->api->content_type ) {
+ case 'application/json' :
+ case 'application/x-javascript' :
+ case 'text/javascript' :
+ case 'text/x-javascript' :
+ case 'text/x-json' :
+ case 'text/json' :
+ $return = json_decode( $input );
+ if ( function_exists( 'json_last_error' ) ) {
+ if ( JSON_ERROR_NONE !== json_last_error() ) {
+ return null;
+ }
+ } else {
+ if ( is_null( $return ) && json_encode( null ) !== $input ) {
+ return null;
+ }
+ }
+
+ if ( is_object( $return ) ) {
+ $return = (array) $return;
+ }
+ break;
+ case 'multipart/form-data' :
+ $return = array_merge( stripslashes_deep( $_POST ), $_FILES );
+ break;
+ default :
+ wp_parse_str( $input, $return );
+ break;
+ }
+
+ if ( !$cast_and_filter ) {
+ return $return;
+ }
+
+ return $this->cast_and_filter( $return, $this->request_format, $return_default_values );
+ }
+
+ function cast_and_filter( $data, $documentation, $return_default_values = false, $for_output = false ) {
+ $return_as_object = false;
+ if ( is_object( $data ) ) {
+ $data = (array) $data;
+ $return_as_object = true;
+ } elseif ( !is_array( $data ) ) {
+ return $data;
+ }
+
+ $boolean_arg = array( 'false', 'true' );
+ $naeloob_arg = array( 'true', 'false' );
+
+ $return = array();
+
+ foreach ( $documentation as $key => $description ) {
+ if ( is_array( $description ) ) {
+ // String or boolean array keys only
+ $whitelist = array_keys( $description );
+ if ( isset( $data[$key] ) && isset( $description[$data[$key]] ) ) {
+ $return[$key] = (string) $data[$key];
+ } elseif ( $return_default_values ) {
+ $return[$key] = (string) current( $whitelist );
+ } else {
+ continue;
+ }
+
+ // Truthiness
+ if ( $whitelist === $boolean_arg || $whitelist === $naeloob_arg ) {
+ $return[$key] = (bool) WPCOM_JSON_API::is_truthy( $return[$key] );
+ }
+
+ continue;
+ }
+
+ $types = $this->parse_types( $description );
+ $type = array_shift( $types );
+
+ // Explicit default - string and int only for now. Always set these reguardless of $return_default_values
+ if ( isset( $type['default'] ) ) {
+ if ( !isset( $data[$key] ) ) {
+ $data[$key] = $type['default'];
+ }
+ }
+
+ if ( !isset( $data[$key] ) ) {
+ continue;
+ }
+
+ $this->cast_and_filter_item( $return, $type, $key, $data[$key], $types, $for_output );
+ }
+
+ if ( $return_as_object ) {
+ return (object) $return;
+ }
+
+ return $return;
+ }
+
+ /**
+ * Casts $value according to $type.
+ * Handles fallbacks for certain values of $type when $value is not that $type
+ * Currently, only handles fallback between string <-> array (two way), from string -> false (one way), and from object -> false (one way)
+ *
+ * Handles "child types" - array:URL, object:category
+ * array:URL means an array of URLs
+ * object:category means a hash of categories
+ *
+ * Handles object typing - object>post means an object of type post
+ */
+ function cast_and_filter_item( &$return, $type, $key, $value, $types = array(), $for_output = false ) {
+ if ( is_string( $type ) ) {
+ $type = compact( 'type' );
+ }
+
+ switch ( $type['type'] ) {
+ case 'false' :
+ $return[$key] = false;
+ break;
+ case 'url' :
+ $return[$key] = (string) esc_url_raw( $value );
+ break;
+ case 'string' :
+ // Fallback string -> array
+ if ( is_array( $value ) ) {
+ if ( !empty( $types[0] ) ) {
+ $next_type = array_shift( $types );
+ return $this->cast_and_filter_item( $return, $next_type, $key, $value, $types, $for_output );
+ }
+ }
+
+ // Fallback string -> false
+ if ( !is_string( $value ) ) {
+ if ( !empty( $types[0] ) && 'false' === $types[0]['type'] ) {
+ $next_type = array_shift( $types );
+ return $this->cast_and_filter_item( $return, $next_type, $key, $value, $types, $for_output );
+ }
+ }
+ $return[$key] = (string) $value;
+ break;
+ case 'html' :
+ $return[$key] = (string) $value;
+ break;
+ case 'media' :
+ if ( is_array( $value ) ) {
+ if ( isset( $value['name'] ) ) {
+ // It's a $_FILES array
+ // Reformat into array of $_FILES items
+
+ $files = array();
+ foreach ( $value['name'] as $k => $v ) {
+ $files[$k] = array();
+ foreach ( array_keys( $value ) as $file_key ) {
+ $files[$k][$file_key] = $value[$file_key][$k];
+ }
+ }
+
+ $return[$key] = $files;
+ }
+ break;
+ } else {
+ // no break - treat as 'array'
+ }
+ // nobreak
+ case 'array' :
+ // Fallback array -> string
+ if ( is_string( $value ) ) {
+ if ( !empty( $types[0] ) ) {
+ $next_type = array_shift( $types );
+ return $this->cast_and_filter_item( $return, $next_type, $key, $value, $types, $for_output );
+ }
+ }
+
+ if ( isset( $type['children'] ) ) {
+ $children = array();
+ foreach ( (array) $value as $k => $child ) {
+ $this->cast_and_filter_item( $children, $type['children'], $k, $child, array(), $for_output );
+ }
+ $return[$key] = (array) $children;
+ break;
+ }
+
+ $return[$key] = (array) $value;
+ break;
+ case 'iso 8601 datetime' :
+ case 'datetime' :
+ // (string)s
+ $dates = $this->parse_date( (string) $value );
+ if ( $for_output ) {
+ $return[$key] = $this->format_date( $dates[1], $dates[0] );
+ } else {
+ list( $return[$key], $return["{$key}_gmt"] ) = $dates;
+ }
+ break;
+ case 'float' :
+ $return[$key] = (float) $value;
+ break;
+ case 'int' :
+ case 'integer' :
+ $return[$key] = (int) $value;
+ break;
+ case 'bool' :
+ case 'boolean' :
+ $return[$key] = (bool) WPCOM_JSON_API::is_truthy( $value );
+ break;
+ case 'object' :
+ // Fallback object -> false
+ if ( is_scalar( $value ) || is_null( $value ) ) {
+ if ( !empty( $types[0] ) && 'false' === $types[0]['type'] ) {
+ return $this->cast_and_filter_item( $return, 'false', $key, $value, $types, $for_output );
+ }
+ }
+
+ if ( isset( $type['children'] ) ) {
+ $children = array();
+ foreach ( (array) $value as $k => $child ) {
+ $this->cast_and_filter_item( $children, $type['children'], $k, $child, array(), $for_output );
+ }
+ $return[$key] = (object) $children;
+ break;
+ }
+
+ if ( isset( $type['subtype'] ) ) {
+ return $this->cast_and_filter_item( $return, $type['subtype'], $key, $value, $types, $for_output );
+ }
+
+ $return[$key] = (object) $value;
+ break;
+ case 'post' :
+ $return[$key] = (object) $this->cast_and_filter( $value, $this->post_object_format, false, $for_output );
+ break;
+ case 'comment' :
+ $return[$key] = (object) $this->cast_and_filter( $value, $this->comment_object_format, false, $for_output );
+ break;
+ case 'tag' :
+ case 'category' :
+ $docs = array(
+ 'name' => '(string)',
+ 'slug' => '(string)',
+ 'description' => '(HTML)',
+ 'post_count' => '(int)',
+ 'meta' => '(object)',
+ );
+ if ( 'category' === $type ) {
+ $docs['parent'] = '(int)';
+ }
+ $return[$key] = (object) $this->cast_and_filter( $value, $docs, false, $for_output );
+ break;
+ case 'post_reference' :
+ case 'comment_reference' :
+ $docs = array(
+ 'ID' => '(int)',
+ 'type' => '(string)',
+ 'link' => '(URL)',
+ );
+ $return[$key] = (object) $this->cast_and_filter( $value, $docs, false, $for_output );
+ break;
+ case 'geo' :
+ $docs = array(
+ 'latitude' => '(float)',
+ 'longitude' => '(float)',
+ 'address' => '(string)',
+ );
+ $return[$key] = (object) $this->cast_and_filter( $value, $docs, false, $for_output );
+ break;
+ case 'author' :
+ $docs = array(
+ 'ID' => '(int)',
+ 'email' => '(string|false)',
+ 'name' => '(string)',
+ 'URL' => '(URL)',
+ 'avatar_URL' => '(URL)',
+ 'profile_URL' => '(URL)',
+ );
+ $return[$key] = (object) $this->cast_and_filter( $value, $docs, false, $for_output );
+ break;
+ case 'attachment' :
+ $docs = array(
+ 'ID' => '(int)',
+ 'URL' => '(URL)',
+ 'guid' => '(string)',
+ 'mime_type' => '(string)',
+ 'width' => '(int)',
+ 'height' => '(int)',
+ 'duration' => '(int)',
+ );
+ $return[$key] = (object) $this->cast_and_filter( $value, apply_filters( 'wpcom_json_api_attachment_cast_and_filter', $docs ), false, $for_output );
+ break;
+ default :
+ trigger_error( "Unknown API casting type {$type['type']}", E_USER_WARNING );
+ }
+ }
+
+ function parse_types( $text ) {
+ if ( !preg_match( '#^\(([^)]+)\)#', ltrim( $text ), $matches ) ) {
+ return 'none';
+ }
+
+ $types = explode( '|', strtolower( $matches[1] ) );
+ $return = array();
+ foreach ( $types as $type ) {
+ foreach ( array( ':' => 'children', '>' => 'subtype', '=' => 'default' ) as $operator => $meaning ) {
+ if ( false !== strpos( $type, $operator ) ) {
+ $item = explode( $operator, $type, 2 );
+ $return[] = array( 'type' => $item[0], $meaning => $item[1] );
+ continue 2;
+ }
+ }
+ $return[] = compact( 'type' );
+ }
+
+ return $return;
+ }
+
+ /**
+ * Auto generates documentation based on description, method, path, path_labels, and query parameters.
+ * Echoes HTML.
+ */
+ function document( $show_description = true ) {
+ $original_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : 'unset';
+ unset( $GLOBALS['post'] );
+
+ $doc = $this->generate_documentation();
+
+ if ( $show_description ) :
+?>
+<caption>
+ <h1><?php echo wp_kses_post( $doc['method'] ); ?> <?php echo wp_kses_post( $doc['path_labeled'] ); ?></h1>
+ <p><?php echo wp_kses_post( $doc['description'] ); ?></p>
+</caption>
+
+<?php endif; ?>
+
+<section class="resource-url">
+ <h2 id="apidoc-resource-url">Resource URL</h2>
+ <table class="api-doc api-doc-resource-parameters api-doc-resource">
+ <thead>
+ <tr>
+ <th class="api-index-title" scope="column">Type</th>
+ <th class="api-index-title" scope="column">URL and Format</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="api-index-item">
+ <th scope="row" class="parameter api-index-item-title"><?php echo wp_kses_post( $doc['method'] ); ?></th>
+ <td class="type api-index-item-title" style="white-space: nowrap;">https://public-api.wordpress.com/rest/v1<?php echo wp_kses_post( $doc['path_labeled'] ); ?></td>
+ </tr>
+ </tbody>
+ </table>
+</section>
+
+<?php
+
+ foreach ( array(
+ 'path' => 'Method Parameters',
+ 'query' => 'Query Parameters',
+ 'body' => 'Request Parameters',
+ 'response' => 'Response Parameters',
+ ) as $doc_section_key => $label ) :
+ $doc_section = 'response' == $doc_section_key ? $doc['response']['body'] : $doc['request'][$doc_section_key];
+ if ( !$doc_section ) {
+ continue;
+ }
+
+ $param_label = strtolower( str_replace( ' ', '-', $label ) );
+?>
+
+<section class="<?php echo $param_label; ?>">
+
+<h2 id="apidoc-<?php echo esc_attr( $doc_section_key ); ?>"><?php echo wp_kses_post( $label ); ?></h2>
+
+<table class="api-doc api-doc-<?php echo $param_label; ?>-parameters api-doc-<?php echo strtolower( str_replace( ' ', '-', $doc['group'] ) ); ?>">
+
+<thead>
+ <tr>
+ <th class="api-index-title" scope="column">Parameter</th>
+ <th class="api-index-title" scope="column">Type</th>
+ <th class="api-index-title" scope="column">Description</th>
+ </tr>
+</thead>
+<tbody>
+
+<?php foreach ( $doc_section as $key => $item ) : ?>
+
+ <tr class="api-index-item">
+ <th scope="row" class="parameter api-index-item-title"><?php echo wp_kses_post( $key ); ?></th>
+ <td class="type api-index-item-title"><?php echo wp_kses_post( $item['type'] ); // @todo auto-link? ?></td>
+ <td class="description api-index-item-body"><?php
+
+ $this->generate_doc_description( $item['description'] );
+
+ ?></td>
+ </tr>
+
+<?php endforeach; ?>
+</tbody>
+</table>
+</section>
+<?php endforeach; ?>
+
+<?php
+ // If no example was hardcoded in the doc, try to get some
+ if ( empty( $this->example_response ) ) {
+
+ // Examples for endpoint documentation response
+ $response_key = 'dev_response_' . $this->version . '_' . $this->method . '_' . sanitize_title( $this->path );
+ $response = get_option( $response_key );
+
+ // Response doesn't exist, so run the request
+ if ( empty( $response ) ) {
+
+ // Only trust GET request
+ if ( 'GET' == $this->method ) {
+ $response = wp_remote_get( $this->example_request );
+ }
+
+ // Set as false if it's an error
+ if ( is_wp_error( $response ) ) {
+ $response = false;
+ }
+
+ // Only update the option if there's a result
+ if ( !empty( $response ) ) {
+ $response = $response['body'];
+ update_option( $response_key, $response );
+ }
+ }
+
+ // Example response was passed into the constructor via params
+ } else {
+ $response = $this->example_response;
+ }
+
+ // Wrap the response in a sourcecode shortcode
+ if ( !empty( $response ) ) {
+ $response = '[sourcecode language="php" wraplines="false" light="true" autolink="false" htmlscript="false"]' . $response . '[/sourcecode]';
+ $response = apply_filters( 'the_content', $response );
+ $this->example_response = $response;
+ }
+
+ $curl = 'curl';
+
+ $php_opts = array( 'ignore_errors' => true );
+
+ if ( 'GET' !== $this->method ) {
+ $php_opts['method'] = $this->method;
+ }
+
+ if ( $this->example_request_data ) {
+ if ( isset( $this->example_request_data['headers'] ) && is_array( $this->example_request_data['headers'] ) ) {
+ $php_opts['header'] = array();
+ foreach ( $this->example_request_data['headers'] as $header => $value ) {
+ $curl .= " \\\n -H " . escapeshellarg( "$header: $value" );
+ $php_opts['header'][] = "$header: $value";
+ }
+ }
+
+ if ( isset( $this->example_request_data['body'] ) && is_array( $this->example_request_data['body'] ) ) {
+ $php_opts['content'] = $this->example_request_data['body'];
+ $php_opts['header'][] = 'Content-Type: application/x-www-form-urlencoded';
+ foreach ( $this->example_request_data['body'] as $key => $value ) {
+ $curl .= " \\\n --data-urlencode " . escapeshellarg( "$key=$value" );
+ }
+ }
+ }
+
+ if ( $php_opts ) {
+ $php_opts_exported = var_export( array( 'http' => $php_opts ), true );
+ if ( !empty( $php_opts['content'] ) ) {
+ $content_exported = preg_quote( var_export( $php_opts['content'], true ), '/' );
+ $content_exported = '\\s*' . str_replace( "\n", "\n\\s*", $content_exported ) . '\\s*';
+ $php_opts_exported = preg_replace_callback( "/$content_exported/", array( $this, 'add_http_build_query_to_php_content_example' ), $php_opts_exported );
+ }
+ $php = <<<EOPHP
+<?php
+
+\$options = $php_opts_exported;
+
+\$context = stream_context_create( \$options );
+\$response = file_get_contents(
+ '$this->example_request',
+ false,
+ \$context
+);
+\$response = json_decode( \$response );
+
+?>
+EOPHP;
+ } else {
+ $php = <<<EOPHP
+<?php
+
+\$response = file_get_contents( '$this->example_request' );
+\$response = json_decode( \$response );
+
+?>
+EOPHP;
+ }
+
+ if ( false !== strpos( $curl, "\n" ) ) {
+ $curl .= " \\\n";
+ }
+
+ $curl .= ' ' . escapeshellarg( $this->example_request );
+
+ $curl = '[sourcecode language="bash" wraplines="false" light="true" autolink="false" htmlscript="false"]' . $curl . '[/sourcecode]';
+ $curl = apply_filters( 'the_content', $curl );
+
+ $php = '[sourcecode language="php" wraplines="false" light="true" autolink="false" htmlscript="false"]' . $php . '[/sourcecode]';
+ $php = apply_filters( 'the_content', $php );
+?>
+
+<?php if ( ! empty( $this->example_request ) || ! empty( $this->example_request_data ) || ! empty( $this->example_response ) ) : ?>
+
+ <section class="example-response">
+ <h2 id="apidoc-example">Example</h2>
+
+ <section>
+ <h3>cURL</h3>
+ <?php echo wp_kses_post( $curl ); ?>
+ </section>
+
+ <section>
+ <h3>PHP</h3>
+ <?php echo wp_kses_post( $php ); ?>
+ </section>
+
+ <?php if ( ! empty( $this->example_response ) ) : ?>
+
+ <section>
+ <h3>Response Body</h3>
+ <?php echo $this->example_response; ?>
+ </section>
+
+ <?php endif; ?>
+
+ </section>
+
+<?php endif; ?>
+
+<?php
+ if ( 'unset' !== $original_post ) {
+ $GLOBALS['post'] = $original_post;
+ }
+ }
+
+ function add_http_build_query_to_php_content_example( $matches ) {
+ $trimmed_match = ltrim( $matches[0] );
+ $pad = substr( $matches[0], 0, -1 * strlen( $trimmed_match ) );
+ $pad = ltrim( $pad, ' ' );
+ $return = ' ' . str_replace( "\n", "\n ", $matches[0] );
+ return " http_build_query({$return}{$pad})";
+ }
+
+ /**
+ * Recursively generates the <dl>'s to document item descriptions.
+ * Echoes HTML.
+ */
+ function generate_doc_description( $item ) {
+ if ( is_array( $item ) ) : ?>
+
+ <dl>
+<?php foreach ( $item as $description_key => $description_value ) : ?>
+
+ <dt><?php echo wp_kses_post( $description_key . ':' ); ?></dt>
+ <dd><?php $this->generate_doc_description( $description_value ); ?></dd>
+
+<?php endforeach; ?>
+
+ </dl>
+
+<?php
+ else :
+ echo wp_kses_post( $item );
+ endif;
+ }
+
+ /**
+ * Auto generates documentation based on description, method, path, path_labels, and query parameters.
+ * Echoes HTML.
+ */
+ function generate_documentation() {
+ $format = str_replace( '%d', '%s', $this->path );
+ $path_labeled = vsprintf( $format, array_keys( $this->path_labels ) );
+ $boolean_arg = array( 'false', 'true' );
+ $naeloob_arg = array( 'true', 'false' );
+
+ $doc = array(
+ 'description' => $this->description,
+ 'method' => $this->method,
+ 'path_format' => $this->path,
+ 'path_labeled' => $path_labeled,
+ 'group' => $this->group,
+ 'request' => array(
+ 'path' => array(),
+ 'query' => array(),
+ 'body' => array(),
+ ),
+ 'response' => array(
+ 'body' => array(),
+ )
+ );
+
+ foreach ( array( 'path_labels' => 'path', 'query' => 'query', 'request_format' => 'body', 'response_format' => 'body' ) as $_property => $doc_item ) {
+ foreach ( $this->$_property as $key => $description ) {
+ if ( is_array( $description ) ) {
+ $description_keys = array_keys( $description );
+ if ( $boolean_arg === $description_keys || $naeloob_arg === $description_keys ) {
+ $type = '(bool)';
+ } else {
+ $type = '(string)';
+ }
+
+ if ( 'response_format' != $_property ) {
+ // hack - don't show "(default)" in response format
+ reset( $description );
+ $description_key = key( $description );
+ $description[$description_key] = "(default) {$description[$description_key]}";
+ }
+ } else {
+ $types = $this->parse_types( $description );
+ $type = array();
+ $default = '';
+
+ foreach ( $types as $type_array ) {
+ $type[] = $type_array['type'];
+ if ( isset( $type_array['default'] ) ) {
+ $default = $type_array['default'];
+ if ( 'string' === $type_array['type'] ) {
+ $default = "'$default'";
+ }
+ }
+ }
+ $type = '(' . join( '|', $type ) . ')';
+ $noop = ''; // skip an index in list below
+ list( $noop, $description ) = explode( ')', $description, 2 );
+ $description = trim( $description );
+ if ( $default ) {
+ $description .= " Default: $default.";
+ }
+ }
+
+ $item = compact( 'type', 'description' );
+
+ if ( 'response_format' == $_property ) {
+ $doc['response'][$doc_item][$key] = $item;
+ } else {
+ $doc['request'][$doc_item][$key] = $item;
+ }
+ }
+ }
+
+ return $doc;
+ }
+
+ function user_can_view_post( $post_id ) {
+ $post = get_post( $post_id );
+ if ( !$post || is_wp_error( $post ) ) {
+ return false;
+ }
+
+ if ( 'inherit' == $post->post_status ) {
+ $parent_post = get_post( $post->post_parent );
+ $post_status_obj = get_post_status_object( $parent_post->post_status );
+ } else {
+ $post_status_obj = get_post_status_object( $post->post_status );
+ }
+
+ if ( !$post_status_obj->public ) {
+ if ( is_user_logged_in() ) {
+ if ( $post_status_obj->protected ) {
+ if ( !current_user_can( 'edit_post', $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
+ }
+ } elseif ( $post_status_obj->private ) {
+ if ( !current_user_can( 'read_post', $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
+ }
+ } elseif ( 'trash' === $post->post_status ) {
+ if ( !current_user_can( 'edit_post', $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
+ }
+ } else {
+ return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
+ }
+ } else {
+ return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
+ }
+ }
+
+ if ( -1 == get_option( 'blog_public' ) && !current_user_can( 'read_post', $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
+ }
+
+ if ( strlen( $post->post_password ) && !current_user_can( 'edit_post', $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot view password protected post', 403 );
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns author object.
+ *
+ * @param $author user ID, user row, WP_User object, comment row, post row
+ * @param $show_email output the author's email address?
+ *
+ * @return (object)
+ */
+ function get_author( $author, $show_email = false ) {
+ if ( isset( $author->comment_author_email ) && !$author->user_id ) {
+ $ID = 0;
+ $email = $author->comment_author_email;
+ $name = $author->comment_author;
+ $URL = $author->comment_author_url;
+ $profile_URL = 'http://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
+ } else {
+ if ( isset( $author->post_author ) ) {
+ $author = $author->post_author;
+ } elseif ( isset( $author->user_id ) && $author->user_id ) {
+ $author = $author->user_id;
+ } elseif ( isset( $author->user_email ) ) {
+ $author = $author->ID;
+ }
+
+ $user = get_user_by( 'id', $author );
+ if ( !$user || is_wp_error( $user ) ) {
+ trigger_error( 'Unknown user', E_USER_WARNING );
+ return null;
+ }
+
+ $ID = $user->ID;
+ $email = $user->user_email;
+ $name = $user->display_name;
+ $URL = $user->user_url;
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ $profile_URL = "http://en.gravatar.com/{$user->user_login}";
+ } else {
+ $profile_URL = 'http://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
+ }
+ }
+
+ $avatar_URL = $this->api->get_avatar_url( $email );
+
+ $email = $show_email ? (string) $email : false;
+
+ return (object) array(
+ 'ID' => (int) $ID,
+ 'email' => $email, // (string|bool)
+ 'name' => (string) $name,
+ 'URL' => (string) esc_url_raw( $URL ),
+ 'avatar_URL' => (string) esc_url_raw( $avatar_URL ),
+ 'profile_URL' => (string) esc_url_raw( $profile_URL ),
+ );
+ }
+
+ function get_taxonomy( $taxonomy_id, $taxonomy_type, $context ) {
+
+ $taxonomy = get_term_by( 'slug', $taxonomy_id, $taxonomy_type );
+ /// keep updating this function
+ if ( !$taxonomy || is_wp_error( $taxonomy ) ) {
+ return new WP_Error( 'unknown_taxonomy', 'Unknown taxonomy', 404 );
+ }
+
+ // Permissions
+ switch ( $context ) {
+ case 'edit' :
+ $tax = get_taxonomy( $taxonomy_type );
+ if ( !current_user_can( $tax->cap->edit_terms ) )
+ return new WP_Error( 'unauthorized', 'User cannot edit taxonomy', 403 );
+ break;
+ case 'display' :
+ if ( -1 == get_option( 'blog_public' ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot view taxonomy', 403 );
+ }
+ break;
+ default :
+ return new WP_Error( 'invalid_context', 'Invalid API CONTEXT', 400 );
+ }
+
+ $response = array();
+ $response['name'] = (string) $taxonomy->name;
+ $response['slug'] = (string) $taxonomy_id;
+ $response['description'] = (string) $taxonomy->description;
+ $response['post_count'] = (int) $taxonomy->count;
+
+ if ( 'category' == $taxonomy_type )
+ $response['parent'] = (int) $taxonomy->parent;
+
+ $response['meta'] = (object) array(
+ 'links' => (object) array(
+ 'self' => (string) $this->get_taxonomy_link( $this->api->get_blog_id_for_output(), $taxonomy_id, $taxonomy_type ),
+ 'help' => (string) $this->get_taxonomy_link( $this->api->get_blog_id_for_output(), $taxonomy_id, $taxonomy_type, 'help' ),
+ 'site' => (string) $this->get_site_link( $this->api->get_blog_id_for_output() ),
+ ),
+ );
+
+ return (object) $response;
+ }
+
+ /**
+ * Returns ISO 8601 formatted datetime: 2011-12-08T01:15:36-08:00
+ *
+ * @param $date_gmt (string) GMT datetime string.
+ * @param $date (string) Optional. Used to calculate the offset from GMT.
+ *
+ * @return string
+ */
+ function format_date( $date_gmt, $date = null ) {
+ $timestamp_gmt = strtotime( "$date_gmt+0000" );
+ if ( null === $date ) {
+ $timestamp = $timestamp_gmt;
+ $hours = $minutes = $west = 0;
+ } else {
+ $timestamp = strtotime( "$date+0000" );
+ $offset = $timestamp - $timestamp_gmt;
+ $west = $offset < 0;
+ $offset = abs( $offset );
+ $hours = (int) floor( $offset / 3600 );
+ $offset -= $hours * 3600;
+ $minutes = (int) floor( $offset / 60 );
+ }
+
+ return (string) gmdate( 'Y-m-d\\TH:i:s', $timestamp ) . sprintf( '%s%02d:%02d', $west ? '-' : '+', $hours, $minutes );
+ }
+
+ /**
+ * @param datetime string
+ *
+ * @return array( $local_time_string, $gmt_time_string )
+ */
+ function parse_date( $date_string ) {
+ $time = strtotime( $date_string );
+ if ( !$time ) {
+ $time = time();
+ }
+
+ $datetime = new DateTime( "@$time" );
+ $gmt = $datetime->format( 'Y-m-d H:i:s' );
+ $timezone_string = get_option( 'timezone_string' );
+ if ( $timezone_string ) {
+ $tz = timezone_open( $timezone_string );
+ if ( $tz ) {
+ $datetime->setTimezone( $tz );
+ $local = $datetime->format( 'Y-m-d H:i:s' );
+ return array( (string) $local, (string) $gmt );
+ }
+ }
+
+ $gmt_offset = get_option( 'gmt_offset' );
+ $local_time = $time + $gmt_offset * 3600;
+
+ $date = getdate( ( int ) $local_time );
+ $datetime->setDate( $date['year'], $date['mon'], $date['mday'] );
+ $datetime->setTime( $date['hours'], $date['minutes'], $date['seconds'] );
+
+ $local = $datetime->format( 'Y-m-d H:i:s' );
+ return array( (string) $local, (string) $gmt );
+ }
+
+ function get_link() {
+ $args = func_get_args();
+ $format = array_shift( $args );
+ array_unshift( $args, $this->api->public_api_scheme, WPCOM_JSON_API__BASE );
+ $path = array_pop( $args );
+ if ( $path ) {
+ $path = '/' . ltrim( $path, '/' );
+ }
+ $args[] = $path;
+
+ // http, WPCOM_JSON_API__BASE, ... , path
+ // %s , %s , $format, %s
+ return esc_url_raw( vsprintf( "%s://%s$format%s", $args ) );
+ }
+
+ function get_me_link( $path = '' ) {
+ return $this->get_link( '/me', $path );
+ }
+
+ function get_taxonomy_link( $blog_id, $taxonomy_id, $taxonomy_type, $path = '' ) {
+ if ( 'category' == $taxonomy_type )
+ return $this->get_link( '/sites/%d/categories/slug:%s', $blog_id, $taxonomy_id, $path );
+ else
+ return $this->get_link( '/sites/%d/tags/slug:%s', $blog_id, $taxonomy_id, $path );
+ }
+
+ function get_site_link( $blog_id, $path = '' ) {
+ return $this->get_link( '/sites/%d', $blog_id, $path );
+ }
+
+ function get_post_link( $blog_id, $post_id, $path = '' ) {
+ return $this->get_link( '/sites/%d/posts/%d', $blog_id, $post_id, $path );
+ }
+
+ function get_comment_link( $blog_id, $comment_id, $path = '' ) {
+ return $this->get_link( '/sites/%d/comments/%d', $blog_id, $comment_id, $path );
+ }
+
+ /**
+ * Return endpoint response
+ *
+ * @param ... determined by ->$path
+ *
+ * @return
+ * falsy: HTTP 500, no response body
+ * WP_Error( $error_code, $error_message, $http_status_code ): HTTP $status_code, json_encode( array( 'error' => $error_code, 'message' => $error_message ) ) response body
+ * $data: HTTP 200, json_encode( $data ) response body
+ */
+ abstract function callback( $path = '' );
+}
+
+abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
+ var $post_object_format = array(
+ // explicitly document and cast all output
+ 'ID' => '(int) The post ID.',
+ 'author' => '(object>author) The author of the post.',
+ 'date' => "(ISO 8601 datetime) The post's creation time.",
+ 'modified' => "(ISO 8601 datetime) The post's creation time.",
+ 'title' => '(HTML) <code>context</code> dependent.',
+ 'URL' => '(URL) The full permalink URL to the post.',
+ 'short_URL' => '(URL) The wp.me short URL.',
+ 'content' => '(HTML) <code>context</code> dependent.',
+ 'excerpt' => '(HTML) <code>context</code> dependent.',
+ 'slug' => '(string) The name (slug) for your post, used in URLs.',
+ 'status' => array(
+ 'publish' => 'The post is published.',
+ 'draft' => 'The post is saved as a draft.',
+ 'pending' => 'The post is pending editorial approval.',
+ 'future' => 'The post is scheduled for future publishing.',
+ 'trash' => 'The post is in the trash.',
+ ),
+ 'password' => '(string) The plaintext password protecting the post, or, more likely, the empty string if the post is not password protected.',
+ 'parent' => "(object>post_reference|false) A reference to the post's parent, if it has one.",
+ 'type' => array(
+ 'post' => 'A blog post.',
+ 'page' => 'A page.',
+ ),
+ 'comments_open' => '(bool) Is the post open for comments?',
+ 'pings_open' => '(bool) Is the post open for pingbacks, trackbacks?',
+ 'comment_count' => '(int) The number of comments for this post.',
+ 'like_count' => '(int) The number of likes for this post.',
+ 'featured_image' => '(URL) The URL to the featured image for this post if it has one.',
+ 'format' => array(), // see constructor
+ 'geo' => '(object>geo|false)',
+ 'publicize_URLs' => '(array:URL) Array of Twitter and Facebook URLs published by this post.',
+ 'tags' => '(object:tag) Hash of tags (keyed by tag name) applied to the post.',
+ 'categories' => '(object:category) Hash of categories (keyed by category name) applied to the post.',
+ 'attachments' => '(object:attachment) Hash of post attachments (keyed by attachment ID).',
+ 'meta' => '(object) Meta data',
+ );
+
+ // var $response_format =& $this->post_object_format;
+
+ function __construct( $args ) {
+ if ( is_array( $this->post_object_format ) && isset( $this->post_object_format['format'] ) ) {
+ $this->post_object_format['format'] = get_post_format_strings();
+ }
+ if ( !$this->response_format ) {
+ $this->response_format =& $this->post_object_format;
+ }
+ parent::__construct( $args );
+ }
+
+ function the_password_form() {
+ return __( 'This post is password protected.', 'jetpack' );
+ }
+
+ function get_post_by( $field, $post_id, $context = 'display' ) {
+ global $blog_id;
+
+ if ( defined( 'GEO_LOCATION__CLASS' ) && class_exists( GEO_LOCATION__CLASS ) ) {
+ $geo = call_user_func( array( GEO_LOCATION__CLASS, 'init' ) );
+ } else {
+ $geo = false;
+ }
+
+ if ( 'display' == $context ) {
+ $args = $this->query_args();
+ if ( isset( $args['content_width'] ) && $args['content_width'] ) {
+ $GLOBALS['content_width'] = (int) $args['content_width'];
+ }
+ }
+
+ if ( strpos( $_SERVER['HTTP_USER_AGENT'], 'wp-windows8' ) ) {
+ remove_shortcode( 'gallery', 'gallery_shortcode' );
+ add_shortcode( 'gallery', array( &$this, 'win8_gallery_shortcode' ) );
+ }
+
+ switch ( $field ) {
+ case 'name' :
+ $post_id = sanitize_title( $post_id );
+ if ( !$post_id ) {
+ return new WP_Error( 'invalid_post', 'Invalid post', 400 );
+ }
+
+ $posts = get_posts( array( 'name' => $post_id ) );
+ if ( !$posts || !isset( $posts[0]->ID ) || !$posts[0]->ID ) {
+ $page = get_page_by_path( $post_id );
+ if ( !$page )
+ return new WP_Error( 'unknown_post', 'Unknown post', 404 );
+ $post_id = $page->ID;
+ } else {
+ $post_id = (int) $posts[0]->ID;
+ }
+ break;
+ default :
+ $post_id = (int) $post_id;
+ break;
+ }
+
+ $post = get_post( $post_id );
+ if ( !$post || is_wp_error( $post ) ) {
+ return new WP_Error( 'unknown_post', 'Unknown post', 404 );
+ }
+
+ $types = array( 'post', 'page' );
+ if ( !in_array( $post->post_type, $types ) ) {
+ return new WP_Error( 'unknown_post', 'Unknown post', 404 );
+ }
+
+ // Permissions
+ switch ( $context ) {
+ case 'edit' :
+ if ( !current_user_can( 'edit_post', $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot edit post', 403 );
+ }
+ break;
+ case 'display' :
+ break;
+ default :
+ return new WP_Error( 'invalid_context', 'Invalid API CONTEXT', 400 );
+ }
+
+ $can_view = $this->user_can_view_post( $post->ID );
+ if ( !$can_view || is_wp_error( $can_view ) ) {
+ return $can_view;
+ }
+
+ // Re-get post according to the correct $context
+ $post = get_post( $post->ID, OBJECT, $context );
+ $GLOBALS['post'] = $post;
+
+ if ( 'display' == $context ) {
+ setup_postdata( $post );
+ }
+
+ $response = array();
+ foreach ( array_keys( $this->post_object_format ) as $key ) {
+ switch ( $key ) {
+ case 'ID' :
+ // explicitly cast all output
+ $response[$key] = (int) $post->ID;
+ break;
+ case 'author' :
+ $response[$key] = (object) $this->get_author( $post, 'edit' === $context && current_user_can( 'edit_post', $post->ID ) );
+ break;
+ case 'date' :
+ $response[$key] = (string) $this->format_date( $post->post_date_gmt, $post->post_date );
+ break;
+ case 'modified' :
+ $response[$key] = (string) $this->format_date( $post->post_modified_gmt, $post->post_modified );
+ break;
+ case 'title' :
+ if ( 'display' == $context ) {
+ $response[$key] = (string) get_the_title( $post->ID );
+ } else {
+ $response[$key] = (string) $post->post_title;
+ }
+ break;
+ case 'URL' :
+ $response[$key] = (string) esc_url_raw( get_permalink( $post->ID ) );
+ break;
+ case 'short_URL' :
+ $response[$key] = (string) esc_url_raw( wp_get_shortlink( $post->ID ) );
+ break;
+ case 'content' :
+ if ( 'display' == $context ) {
+ add_filter( 'the_password_form', array( $this, 'the_password_form' ) );
+ $response[$key] = (string) $this->get_the_post_content_for_display();
+ remove_filter( 'the_password_form', array( $this, 'the_password_form' ) );
+ } else {
+ $response[$key] = (string) $post->post_content;
+ }
+ break;
+ case 'excerpt' :
+ if ( 'display' == $context ) {
+ add_filter( 'the_password_form', array( $this, 'the_password_form' ) );
+ ob_start();
+ the_excerpt();
+ $response[$key] = (string) ob_get_clean();
+ remove_filter( 'the_password_form', array( $this, 'the_password_form' ) );
+ } else {
+ $response[$key] = (string) $post->post_excerpt;
+ }
+ break;
+ case 'status' :
+ $response[$key] = (string) get_post_status( $post->ID );
+ break;
+ case 'slug' :
+ $response[$key] = (string) $post->post_name;
+ break;
+ case 'password' :
+ $response[$key] = (string) $post->post_password;
+ break;
+ case 'parent' : // (object|false)
+ if ( $post->post_parent ) {
+ $parent = get_post( $post->post_parent );
+ $response[$key] = (object) array(
+ 'ID' => (int) $parent->ID,
+ 'type' => (string) $parent->post_type,
+ 'link' => (string) $this->get_post_link( $this->api->get_blog_id_for_output(), $parent->ID ),
+ );
+ } else {
+ $response[$key] = false;
+ }
+ break;
+ case 'type' :
+ $response[$key] = (string) $post->post_type;
+ break;
+ case 'comments_open' :
+ $response[$key] = (bool) comments_open( $post->ID );
+ break;
+ case 'pings_open' :
+ $response[$key] = (bool) pings_open( $post->ID );
+ break;
+ case 'comment_count' :
+ $response[$key] = (int) $post->comment_count;
+ break;
+ case 'like_count' :
+ $response[$key] = (int) $this->api->post_like_count( $blog_id, $post->ID );
+ break;
+ case 'featured_image' :
+ $image_attributes = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'full' );
+ if ( is_array( $image_attributes ) && isset( $image_attributes[0] ) )
+ $response[$key] = (string) $image_attributes[0];
+ else
+ $response[$key] = '';
+ break;
+ case 'format' :
+ $response[$key] = (string) get_post_format( $post->ID );
+ if ( !$response[$key] ) {
+ $response[$key] = 'standard';
+ }
+ break;
+ case 'geo' : // (object|false)
+ if ( !$geo ) {
+ $response[$key] = false;
+ } else {
+ $geo_data = $geo->get_geo( 'post', $post->ID );
+ $response[$key] = false;
+ if ( $geo_data ) {
+ $geo_data = array_intersect_key( $geo_data, array( 'latitude' => true, 'longitude' => true, 'address' => true, 'public' => true ) );
+ if ( $geo_data ) {
+ $response[$key] = (object) array(
+ 'latitude' => isset( $geo_data['latitude'] ) ? (float) $geo_data['latitude'] : 0,
+ 'longitude' => isset( $geo_data['longitude'] ) ? (float) $geo_data['longitude'] : 0,
+ 'address' => isset( $geo_data['address'] ) ? (string) $geo_data['address'] : '',
+ );
+ } else {
+ $response[$key] = false;
+ }
+ // Private
+ if ( !isset( $geo_data['public'] ) || !$geo_data['public'] ) {
+ if ( 'edit' !== $context || !current_user_can( 'edit_post', $post->ID ) ) {
+ // user can't access
+ $response[$key] = false;
+ }
+ }
+ }
+ }
+ break;
+ case 'publicize_URLs' :
+ $publicize_URLs = array();
+ $publicize = get_post_meta( $post->ID, 'publicize_results', true );
+ if ( $publicize ) {
+ foreach ( $publicize as $service => $data ) {
+ switch ( $service ) {
+ case 'twitter' :
+ foreach ( $data as $datum ) {
+ $publicize_URLs[] = esc_url_raw( "https://twitter.com/{$datum['user_id']}/status/{$datum['post_id']}" );
+ }
+ break;
+ case 'fb' :
+ foreach ( $data as $datum ) {
+ $publicize_URLs[] = esc_url_raw( "https://www.facebook.com/permalink.php?story_fbid={$datum['post_id']}&id={$datum['user_id']}" );
+ }
+ break;
+ }
+ }
+ }
+ $response[$key] = (array) $publicize_URLs;
+ break;
+ case 'tags' :
+ $response[$key] = array();
+ $terms = wp_get_post_tags( $post->ID );
+ foreach ( $terms as $term ) {
+ if ( !empty( $term->name ) ) {
+ $response[$key][$term->name] = $this->get_taxonomy( $term->slug, 'post_tag', $context );
+ }
+ }
+ $response[$key] = (object) $response[$key];
+ break;
+ case 'categories':
+ $response[$key] = array();
+ $terms = wp_get_post_categories( $post->ID );
+ foreach ( $terms as $term ) {
+ $category = $taxonomy = get_term_by( 'id', $term, 'category' );
+ if ( !empty( $category->name ) ) {
+ $response[$key][$category->name] = $this->get_taxonomy( $category->slug, 'category', $context );
+ }
+ }
+ $response[$key] = (object) $response[$key];
+ break;
+ case 'attachments':
+ $response[$key] = array();
+ $_attachments = get_posts( array( 'post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment' ) );
+ foreach ( $_attachments as $attachment ) {
+ $response[$key][$attachment->ID] = $this->get_attachment( $attachment );
+ }
+ $response[$key] = (object) $response[$key];
+ break;
+ case 'meta' :
+ $response[$key] = (object) array(
+ 'links' => (object) array(
+ 'self' => (string) $this->get_post_link( $this->api->get_blog_id_for_output(), $post->ID ),
+ 'help' => (string) $this->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'help' ),
+ 'site' => (string) $this->get_site_link( $this->api->get_blog_id_for_output() ),
+// 'author' => (string) $this->get_user_link( $post->post_author ),
+// 'via' => (string) $this->get_post_link( $reblog_origin_blog_id, $reblog_origin_post_id ),
+ 'replies' => (string) $this->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'replies/' ),
+ 'likes' => (string) $this->get_post_link( $this->api->get_blog_id_for_output(), $post->ID, 'likes/' ),
+ ),
+ );
+ break;
+ }
+ }
+
+ unset( $GLOBALS['post'] );
+ return $response;
+ }
+
+ // No Blog ID parameter. No Post ID parameter. Depends on globals.
+ // Expects setup_postdata() to already have been run
+ function get_the_post_content_for_display() {
+ global $pages, $page;
+
+ $old_pages = $pages;
+ $old_page = $page;
+
+ $content = join( "\n\n", $pages );
+ $content = preg_replace( '/<!--more(.*?)?-->/', '', $content );
+ $pages = array( $content );
+ $page = 1;
+
+ ob_start();
+ the_content();
+ $return = ob_get_clean();
+
+ $pages = $old_pages;
+ $page = $old_page;
+
+ return $return;
+ }
+
+ function get_blog_post( $blog_id, $post_id, $context = 'display' ) {
+ $blog_id = $this->api->get_blog_id( $blog_id );
+ if ( !$blog_id || is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+ switch_to_blog( $blog_id );
+ $post = $this->get_post_by( 'ID', $post_id, $context );
+ restore_current_blog();
+ return $post;
+ }
+
+ function win8_gallery_shortcode( $attr ) {
+ global $post;
+
+ static $instance = 0;
+ $instance++;
+
+ $output = '';
+
+ // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
+ if ( isset( $attr['orderby'] ) ) {
+ $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
+ if ( !$attr['orderby'] )
+ unset( $attr['orderby'] );
+ }
+
+ extract( shortcode_atts( array(
+ 'order' => 'ASC',
+ 'orderby' => 'menu_order ID',
+ 'id' => $post->ID,
+ 'include' => '',
+ 'exclude' => '',
+ 'slideshow' => false
+ ), $attr ) );
+
+ // Custom image size and always use it
+ add_image_size( 'win8app-column', 480 );
+ $size = 'win8app-column';
+
+ $id = intval( $id );
+ if ( 'RAND' == $order )
+ $orderby = 'none';
+
+ if ( !empty( $include ) ) {
+ $include = preg_replace( '/[^0-9,]+/', '', $include );
+ $_attachments = get_posts( array( 'include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
+ $attachments = array();
+ foreach ( $_attachments as $key => $val ) {
+ $attachments[$val->ID] = $_attachments[$key];
+ }
+ } elseif ( !empty( $exclude ) ) {
+ $exclude = preg_replace( '/[^0-9,]+/', '', $exclude );
+ $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
+ } else {
+ $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
+ }
+
+ if ( ! empty( $attachments ) ) {
+ foreach ( $attachments as $id => $attachment ) {
+ $link = isset( $attr['link'] ) && 'file' == $attr['link'] ? wp_get_attachment_link( $id, $size, false, false ) : wp_get_attachment_link( $id, $size, true, false );
+
+ if ( $captiontag && trim($attachment->post_excerpt) ) {
+ $output .= "<div class='wp-caption aligncenter'>$link
+ <p class='wp-caption-text'>" . wptexturize($attachment->post_excerpt) . "</p>
+ </div>";
+ } else {
+ $output .= $link . ' ';
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns attachment object.
+ *
+ * @param $attachment attachment row
+ *
+ * @return (object)
+ */
+ function get_attachment( $attachment ) {
+ $metadata = wp_get_attachment_metadata( $attachment->ID );
+
+ $result = array(
+ 'ID' => (int) $attachment->ID,
+ 'URL' => (string) wp_get_attachment_url( $attachment->ID ),
+ 'guid' => (string) $attachment->guid,
+ 'mime_type' => (string) $attachment->post_mime_type,
+ 'width' => (int) $metadata['width'],
+ 'height' => (int) $metadata['height'],
+ );
+
+ if ( isset( $metadata['duration'] ) ) {
+ $result['duration'] = (int) $metadata['duration'];
+ }
+
+ return (object) apply_filters( 'get_attachment', $result );
+ }
+}
+
+class WPCOM_JSON_API_Get_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
+ // /sites/%s/posts/%d -> $blog_id, $post_id
+ // /sites/%s/posts/name:%s -> $blog_id, $post_id // not documented
+ // /sites/%s/posts/slug:%s -> $blog_id, $post_id
+ function callback( $path = '', $blog_id = 0, $post_id = 0 ) {
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ $args = $this->query_args();
+
+ if ( false === strpos( $path, '/posts/slug:' ) && false === strpos( $path, '/posts/name:' ) ) {
+ $get_by = 'ID';
+ } else {
+ $get_by = 'name';
+ }
+
+ $return = $this->get_post_by( $get_by, $post_id, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'posts' );
+
+ return $return;
+ }
+}
+
+class WPCOM_JSON_API_List_Posts_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
+ var $date_range = array();
+
+ var $response_format = array(
+ 'found' => '(int) The total number of posts found that match the request (ignoring limits, offsets, and pagination).',
+ 'posts' => '(array:post) An array of post objects.',
+ );
+
+ // /sites/%s/posts/ -> $blog_id
+ function callback( $path = '', $blog_id = 0 ) {
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ $args = $this->query_args();
+
+ if ( $args['number'] < 1 ) {
+ $args['number'] = 20;
+ } elseif ( 100 < $args['number'] ) {
+ return new WP_Error( 'invalid_number', 'The NUMBER parameter must be less than or equal to 100.', 400 );
+ }
+
+ $query = array(
+ 'posts_per_page' => $args['number'],
+ 'order' => $args['order'],
+ 'orderby' => $args['order_by'],
+ 'post_type' => $args['type'],
+ 'post_status' => $args['status'],
+ 'author' => isset( $args['author'] ) && 0 < $args['author'] ? $args['author'] : null,
+ 's' => isset( $args['search'] ) ? $args['search'] : null,
+ );
+
+ if (
+ isset( $args['sticky'] )
+ &&
+ ( $sticky = get_option( 'sticky_posts' ) )
+ &&
+ is_array( $sticky )
+ ) {
+ if ( $args['sticky'] ) {
+ $query['post__in'] = $sticky;
+ } else {
+ $query['post__not_in'] = $sticky;
+ $query['ignore_sticky_posts'] = 1;
+ }
+ }
+
+ if ( isset( $args['category'] ) ) {
+ $category = get_term_by( 'slug', $args['category'], 'category' );
+ if ( $category === false) {
+ $query['category_name'] = $args['category'];
+ } else {
+ $query['cat'] = $category->term_id;
+ }
+ }
+
+ if ( isset( $args['tag'] ) ) {
+ $query['tag'] = $args['tag'];
+ }
+
+ if ( isset( $args['page'] ) ) {
+ if ( $args['page'] < 1 ) {
+ $args['page'] = 1;
+ }
+
+ $query['paged'] = $args['page'];
+ } else {
+ if ( $args['offset'] < 0 ) {
+ $args['offset'] = 0;
+ }
+
+ $query['offset'] = $args['offset'];
+ }
+
+ if ( isset( $args['before'] ) ) {
+ $this->date_range['before'] = $args['before'];
+ }
+ if ( isset( $args['after'] ) ) {
+ $this->date_range['after'] = $args['after'];
+ }
+
+ if ( $this->date_range ) {
+ add_filter( 'posts_where', array( $this, 'handle_date_range' ) );
+ }
+ $wp_query = new WP_Query( $query );
+ if ( $this->date_range ) {
+ remove_filter( 'posts_where', array( $this, 'handle_date_range' ) );
+ $this->date_range = array();
+ }
+
+ $return = array();
+ foreach ( array_keys( $this->response_format ) as $key ) {
+ switch ( $key ) {
+ case 'found' :
+ $return[$key] = (int) $wp_query->found_posts;
+ break;
+ case 'posts' :
+ $posts = array();
+ foreach ( $wp_query->posts as $post ) {
+ $the_post = $this->get_post_by( 'ID', $post->ID, $args['context'] );
+ if ( $the_post && !is_wp_error( $the_post ) ) {
+ $posts[] = $the_post;
+ }
+ }
+
+ if ( $posts ) {
+ do_action( 'wpcom_json_api_objects', 'posts', count( $posts ) );
+ }
+
+ $return[$key] = $posts;
+ break;
+ }
+ }
+
+ return $return;
+ }
+
+ function handle_date_range( $where ) {
+ global $wpdb;
+
+ switch ( count( $this->date_range ) ) {
+ case 2 :
+ $where .= $wpdb->prepare(
+ " AND `$wpdb->posts`.post_date BETWEEN CAST( %s AS DATETIME ) AND CAST( %s AS DATETIME ) ",
+ $this->date_range['after'],
+ $this->date_range['before']
+ );
+ break;
+ case 1 :
+ if ( isset( $this->date_range['before'] ) ) {
+ $where .= $wpdb->prepare(
+ " AND `$wpdb->posts`.post_date <= CAST( %s AS DATETIME ) ",
+ $this->date_range['before']
+ );
+ } else {
+ $where .= $wpdb->prepare(
+ " AND `$wpdb->posts`.post_date >= CAST( %s AS DATETIME ) ",
+ $this->date_range['after']
+ );
+ }
+ break;
+ }
+
+ return $where;
+ }
+}
+
+class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
+ function __construct( $args ) {
+ parent::__construct( $args );
+ if ( $this->api->ends_with( $this->path, '/delete' ) ) {
+ $this->post_object_format['status']['deleted'] = 'The post has been deleted permanently.';
+ }
+ }
+
+ // /sites/%s/posts/new -> $blog_id
+ // /sites/%s/posts/%d -> $blog_id, $post_id
+ // /sites/%s/posts/%d/delete -> $blog_id, $post_id
+ function callback( $path = '', $blog_id = 0, $post_id = 0 ) {
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ if ( $this->api->ends_with( $path, '/delete' ) ) {
+ return $this->delete_post( $path, $blog_id, $post_id );
+ } else {
+ return $this->write_post( $path, $blog_id, $post_id );
+ }
+ }
+
+ // /sites/%s/posts/new -> $blog_id
+ // /sites/%s/posts/%d -> $blog_id, $post_id
+ function write_post( $path, $blog_id, $post_id ) {
+ $new = $this->api->ends_with( $path, '/new' );
+ $args = $this->query_args();
+
+ if ( $new ) {
+ $input = $this->input( true );
+
+ if ( !isset( $input['title'] ) && !isset( $input['content'] ) && !isset( $input['excerpt'] ) ) {
+ return new WP_Error( 'invalid_input', 'Invalid request input', 400 );
+ }
+
+ $post_type = get_post_type_object( $input['type'] );
+
+ if ( 'publish' === $input['status'] ) {
+ if ( !current_user_can( $post_type->cap->publish_posts ) ) {
+ if ( current_user_can( $post_type->cap->edit_posts ) ) {
+ $input['status'] = 'pending';
+ } else {
+ return new WP_Error( 'unauthorized', 'User cannot publish posts', 403 );
+ }
+ }
+ } else {
+ if ( !current_user_can( $post_type->cap->edit_posts ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot edit posts', 403 );
+ }
+ }
+ } else {
+ $input = $this->input( false );
+
+ if ( !is_array( $input ) || !$input ) {
+ return new WP_Error( 'invalid_input', 'Invalid request input', 400 );
+ }
+
+ $post = get_post( $post_id );
+ if ( !$post || is_wp_error( $post ) ) {
+ return new WP_Error( 'unknown_post', 'Unknown post', 404 );
+ }
+
+ if ( !current_user_can( 'edit_post', $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot edit post', 403 );
+ }
+
+ if ( 'publish' === $input['status'] && 'publish' !== $post->post_status && !current_user_can( 'publish_post', $post->ID ) ) {
+ $input['status'] = 'pending';
+ }
+
+ $post_type = get_post_type_object( $post->post_type );
+ }
+
+ if ( !is_post_type_hierarchical( $post_type->name ) ) {
+ unset( $input['parent'] );
+ }
+
+ $categories = null;
+ $tags = null;
+
+ if ( !empty( $input['categories'] )) {
+ if ( is_array( $input['categories'] ) ) {
+ $categories = $input['categories'];
+ } else {
+ foreach ( explode( ',', $input['categories'] ) as $category ) {
+ $categories[] = $category;
+ }
+ }
+ }
+
+ if ( !empty( $input['tags'] ) ) {
+ if ( is_array( $input['tags'] ) ) {
+ $tags = $input['tags'];
+ } else {
+ foreach ( explode( ',', $input['tags'] ) as $tag ) {
+ $tags[] = $tag;
+ }
+ }
+ $tags_string = implode( ',', $tags );
+ }
+
+ unset( $input['tags'], $input['categories'] );
+
+ $insert = array();
+
+ if ( !empty( $input['slug'] ) ) {
+ $insert['post_name'] = $input['slug'];
+ unset( $input['slug'] );
+ }
+
+ if ( true === $input['comments_open'] )
+ $insert['comment_status'] = 'open';
+ else if ( false === $input['comments_open'] )
+ $insert['comment_status'] = 'closed';
+
+ if ( true === $input['pings_open'] )
+ $insert['ping_status'] = 'open';
+ else if ( false === $input['pings_open'] )
+ $insert['ping_status'] = 'closed';
+
+ unset( $input['comments_open'], $input['pings_open'] );
+
+ $publicize = $input['publicize'];
+ $publicize_custom_message = $input['publicize_message'];
+ unset( $input['publicize'], $input['publicize_message'] );
+
+ foreach ( $input as $key => $value ) {
+ $insert["post_$key"] = $value;
+ }
+
+ $has_media = isset( $input['media'] ) && $input['media'] ? count( $input['media'] ) : false;
+
+ if ( $new ) {
+ if ( false === strpos( $input['content'], '[gallery' ) && $has_media ) {
+ switch ( $has_media ) {
+ case 0 :
+ // No images - do nothing.
+ break;
+ case 1 :
+ // 1 image - make it big
+ $insert['post_content'] = $input['content'] = "[gallery size=full columns=1]\n\n" . $input['content'];
+ break;
+ default :
+ // Several images - 3 column gallery
+ $insert['post_content'] = $input['content'] = "[gallery]\n\n" . $input['content'];
+ break;
+ }
+ }
+
+ $post_id = wp_insert_post( add_magic_quotes( $insert ), true );
+
+ if ( $has_media ) {
+ $this->api->trap_wp_die( 'upload_error' );
+ foreach ( $input['media'] as $media_item ) {
+ $_FILES['.api.media.item.'] = $media_item;
+ // check for WP_Error if we ever actually need $media_id
+ $media_id = media_handle_upload( '.api.media.item.', $post_id );
+ }
+ $this->api->trap_wp_die( null );
+
+ unset( $_FILES['.api.media.item.'] );
+ }
+ } else {
+ $insert['ID'] = $post->ID;
+ $post_id = wp_update_post( (object) $insert );
+ }
+
+ if ( !$post_id || is_wp_error( $post_id ) ) {
+ return null;
+ }
+
+ if ( $publicize === false ) {
+ foreach ( $GLOBALS['publicize_ui']->publicize->get_services( 'all' ) as $name => $service ) {
+ update_post_meta( $post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $name, 1 );
+ }
+ } else if ( is_array( $publicize ) && ( count ( $publicize ) > 0 ) ) {
+ foreach ( $GLOBALS['publicize_ui']->publicize->get_services( 'all' ) as $name => $service ) {
+ if ( !in_array( $name, $publicize ) ) {
+ update_post_meta( $post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $name, 1 );
+ }
+ }
+ }
+
+ if ( !empty( $publicize_custom_message ) )
+ update_post_meta( $post_id, $GLOBALS['publicize_ui']->publicize->POST_MESS, trim( $publicize_custom_message ) );
+
+ if ( is_array( $categories ) )
+ wp_set_object_terms( $post_id, $categories, 'category' );
+ if ( is_array( $tags ) )
+ wp_set_object_terms( $post_id, $tags, 'post_tag' );
+
+ set_post_format( $post_id, $insert['post_format'] );
+
+ $return = $this->get_post_by( 'ID', $post_id, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'posts' );
+
+ return $return;
+ }
+
+ // /sites/%s/posts/%d/delete -> $blog_id, $post_id
+ function delete_post( $path, $blog_id, $post_id ) {
+ $post = get_post( $post_id );
+ if ( !$post || is_wp_error( $post ) ) {
+ return new WP_Error( 'unknown_post', 'Unknown post', 404 );
+ }
+
+ if ( !current_user_can( 'delete_post', $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot delete posts', 403 );
+ }
+
+ $args = $this->query_args();
+ $return = $this->get_post_by( 'ID', $post->ID, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'posts' );
+
+ wp_delete_post( $post->ID );
+
+ $status = get_post_status( $post->ID );
+ if ( false === $status ) {
+ $return['status'] = 'deleted';
+ return $return;
+ }
+
+ return $this->get_post_by( 'ID', $post->ID, $args['context'] );
+ }
+}
+
+abstract class WPCOM_JSON_API_Taxonomy_Endpoint extends WPCOM_JSON_API_Endpoint {
+ var $category_object_format = array(
+ 'ID' => '(int) The category ID.',
+ 'name' => "(string) The name of the category.",
+ 'slug' => "(string) The slug of the category.",
+ 'description' => '(string) The description of the category.',
+ 'post_count' => "(int) The number of posts using this category.",
+ 'parent' => "(int) The parent ID for the category.",
+ 'meta' => '(object) Meta data',
+ );
+
+ var $tag_object_format = array(
+ 'ID' => '(int) The tag ID.',
+ 'name' => "(string) The name of the tag.",
+ 'slug' => "(string) The slug of the tag.",
+ 'description' => '(string) The description of the tag.',
+ 'post_count' => "(int) The number of posts using this t.",
+ 'meta' => '(object) Meta data',
+ );
+
+ function __construct( $args ) {
+ parent::__construct( $args );
+ if ( preg_match( '#/tags/#i', $this->path ) )
+ $this->response_format =& $this->tag_object_format;
+ else
+ $this->response_format =& $this->category_object_format;
+ }
+}
+
+
+class WPCOM_JSON_API_Get_Taxonomy_Endpoint extends WPCOM_JSON_API_Taxonomy_Endpoint {
+ // /sites/%s/tags/slug:%s -> $blog_id, $tag_id
+ // /sites/%s/categories/slug:%s -> $blog_id, $tag_id
+ function callback( $path = '', $blog_id = 0, $taxonomy_id = 0 ) {
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ $args = $this->query_args();
+ if ( preg_match( '#/tags/#i', $path ) ) {
+ $taxonomy_type = "post_tag";
+ } else {
+ $taxonomy_type = "category";
+ }
+
+ $return = $this->get_taxonomy( $taxonomy_id, $taxonomy_type, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'taxonomies' );
+
+ return $return;
+ }
+}
+
+
+class WPCOM_JSON_API_Update_Taxonomy_Endpoint extends WPCOM_JSON_API_Taxonomy_Endpoint {
+ // /sites/%s/tags|categories/new -> $blog_id
+ // /sites/%s/tags|categories/slug:%s -> $blog_id, $taxonomy_id
+ // /sites/%s/tags|categories/slug:%s/delete -> $blog_id, $taxonomy_id
+ function callback( $path = '', $blog_id = 0, $object_id = 0 ) {
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ if ( preg_match( '#/tags/#i', $path ) ) {
+ $taxonomy_type = "post_tag";
+ } else {
+ $taxonomy_type = "category";
+ }
+
+ if ( $this->api->ends_with( $path, '/delete' ) ) {
+ return $this->delete_taxonomy( $path, $blog_id, $object_id, $taxonomy_type );
+ } elseif ( $this->api->ends_with( $path, '/new' ) ) {
+ return $this->new_taxonomy( $path, $blog_id, $taxonomy_type );
+ }
+
+ return $this->update_taxonomy( $path, $blog_id, $object_id, $taxonomy_type );
+ }
+
+ // /sites/%s/tags|categories/new -> $blog_id
+ function new_taxonomy( $path, $blog_id, $taxonomy_type ) {
+ $args = $this->query_args();
+ $input = $this->input();
+ if ( !is_array( $input ) || !$input || !strlen( $input['name'] ) ) {
+ return new WP_Error( 'unknown_taxonomy', 'Unknown data passed', 404 );
+ }
+
+ $user = wp_get_current_user();
+ if ( !$user || is_wp_error( $user ) || !$user->ID ) {
+ return new WP_Error( 'authorization_required', 'An active access token must be used to manage taxonomies.', 403 );
+ }
+
+ $tax = get_taxonomy( $taxonomy_type );
+ if ( !current_user_can( $tax->cap->edit_terms ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot edit taxonomy', 403 );
+ }
+
+ if ( term_exists( $input['name'], $taxonomy_type ) ) {
+ return new WP_Error( 'unknown_taxonomy', 'A taxonomy with that name already exists', 404 );
+ }
+
+ if ( 'category' != $taxonomy_type )
+ $input['parent'] = 0;
+
+ $data = wp_insert_term( addslashes( $input['name'] ), $taxonomy_type,
+ array(
+ 'description' => addslashes( $input['description'] ),
+ 'parent' => $input['parent']
+ )
+ );
+
+ $taxonomy = get_term_by( 'id', $data['term_id'], $taxonomy_type );
+ $return = $this->get_taxonomy( $taxonomy->slug, $taxonomy_type, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'taxonomies' );
+ return $return;
+ }
+
+ // /sites/%s/tags|categories/slug:%s -> $blog_id, $taxonomy_id
+ function update_taxonomy( $path, $blog_id, $object_id, $taxonomy_type ) {
+ $taxonomy = get_term_by( 'slug', $object_id, $taxonomy_type );
+ $tax = get_taxonomy( $taxonomy_type );
+ if ( !current_user_can( $tax->cap->edit_terms ) )
+ return new WP_Error( 'unauthorized', 'User cannot edit taxonomy', 403 );
+
+ if ( !$taxonomy || is_wp_error( $taxonomy ) ) {
+ return new WP_Error( 'unknown_taxonomy', 'Unknown taxonomy', 404 );
+ }
+
+ if ( false === term_exists( $object_id, $taxonomy_type ) ) {
+ return new WP_Error( 'unknown_taxonomy', 'That taxonomy does not exist', 404 );
+ }
+
+ $args = $this->query_args();
+ $input = $this->input( false );
+ if ( !is_array( $input ) || !$input ) {
+ return new WP_Error( 'invalid_input', 'Invalid request input', 400 );
+ }
+
+ $update = array();
+ if ( 'category' == $taxonomy_type && !empty( $input['parent'] ) )
+ $update['parent'] = $input['parent'];
+
+ if ( !empty( $input['description'] ) )
+ $update['description'] = addslashes( $input['description'] );
+
+ if ( !empty( $input['name'] ) )
+ $update['name'] = addslashes( $input['name'] );
+
+
+ $data = wp_update_term( $taxonomy->term_id, $taxonomy_type, $update );
+ $taxonomy = get_term_by( 'id', $data['term_id'], $taxonomy_type );
+
+ $return = $this->get_taxonomy( $taxonomy->slug, $taxonomy_type, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'taxonomies' );
+ return $return;
+ }
+
+ // /sites/%s/tags|categories/%s/delete -> $blog_id, $taxonomy_id
+ function delete_taxonomy( $path, $blog_id, $object_id, $taxonomy_type ) {
+ $taxonomy = get_term_by( 'slug', $object_id, $taxonomy_type );
+ $tax = get_taxonomy( $taxonomy_type );
+ if ( !current_user_can( $tax->cap->delete_terms ) )
+ return new WP_Error( 'unauthorized', 'User cannot edit taxonomy', 403 );
+
+ if ( !$taxonomy || is_wp_error( $taxonomy ) ) {
+ return new WP_Error( 'unknown_taxonomy', 'Unknown taxonomy', 404 );
+ }
+
+ if ( false === term_exists( $object_id, $taxonomy_type ) ) {
+ return new WP_Error( 'unknown_taxonomy', 'That taxonomy does not exist', 404 );
+ }
+
+ $args = $this->query_args();
+ $return = $this->get_taxonomy( $taxonomy->slug, $taxonomy_type, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'taxonomies' );
+
+ wp_delete_term( $taxonomy->term_id, $taxonomy_type );
+
+ return array(
+ 'slug' => (string) $taxonomy->slug,
+ 'success' => 'true',
+ );
+ }
+}
+
+abstract class WPCOM_JSON_API_Comment_Endpoint extends WPCOM_JSON_API_Endpoint {
+ var $comment_object_format = array(
+ // explicitly document and cast all output
+ 'ID' => '(int) The comment ID.',
+ 'post' => "(object>post_reference) A reference to the comment's post.",
+ 'author' => '(object>author) The author of the comment.',
+ 'date' => "(ISO 8601 datetime) The comment's creation time.",
+ 'URL' => '(URL) The full permalink URL to the comment.',
+ 'short_URL' => '(URL) The wp.me short URL.',
+ 'content' => '(HTML) <code>context</code> dependent.',
+ 'status' => array(
+ 'approved' => 'The comment has been approved.',
+ 'unapproved' => 'The comment has been held for review in the moderation queue.',
+ 'spam' => 'The comment has been marked as spam.',
+ 'trash' => 'The comment is in the trash.',
+ ),
+ 'parent' => "(object>comment_reference|false) A reference to the comment's parent, if it has one.",
+ 'type' => array(
+ 'comment' => 'The comment is a regular comment.',
+ 'trackback' => 'The comment is a trackback.',
+ 'pingback' => 'The comment is a pingback.',
+ ),
+ 'meta' => '(object) Meta data',
+ );
+
+ // var $response_format =& $this->comment_object_format;
+
+ function __construct( $args ) {
+ if ( !$this->response_format ) {
+ $this->response_format =& $this->comment_object_format;
+ }
+ parent::__construct( $args );
+ }
+
+ function get_comment( $comment_id, $context ) {
+ global $blog_id;
+
+ $comment = get_comment( $comment_id );
+ if ( !$comment || is_wp_error( $comment ) ) {
+ return new WP_Error( 'unknown_comment', 'Unknown comment', 404 );
+ }
+
+ $types = array( '', 'comment', 'pingback', 'trackback' );
+ if ( !in_array( $comment->comment_type, $types ) ) {
+ return new WP_Error( 'unknown_comment', 'Unknown comment', 404 );
+ }
+
+ $post = get_post( $comment->comment_post_ID );
+ if ( !$post || is_wp_error( $post ) ) {
+ return new WP_Error( 'unknown_post', 'Unknown post', 404 );
+ }
+
+ $status = wp_get_comment_status( $comment->comment_ID );
+
+ // Permissions
+ switch ( $context ) {
+ case 'edit' :
+ if ( !current_user_can( 'edit_comment', $comment->comment_ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot edit comment', 403 );
+ }
+
+ $GLOBALS['post'] = $post;
+ $comment = get_comment_to_edit( $comment->comment_ID );
+ break;
+ case 'display' :
+ if ( 'approved' !== $status ) {
+ $current_user_id = get_current_user_id();
+ $user_can_read_coment = false;
+ if ( $current_user_id && $comment->user_id && $current_user_id == $comment->user_id ) {
+ $user_can_read_coment = true;
+ } elseif (
+ $comment->comment_author_email && $comment->comment_author
+ &&
+ isset( $this->api->token_details['user'] )
+ &&
+ $this->api->token_details['user']['user_email'] === $comment->comment_author_email
+ &&
+ $this->api->token_details['user']['display_name'] === $comment->comment_author
+ ) {
+ $user_can_read_coment = true;
+ } else {
+ $user_can_read_coment = current_user_can( 'edit_comment', $comment->comment_ID );
+ }
+
+ if ( !$user_can_read_coment ) {
+ return new WP_Error( 'unauthorized', 'User cannot read unapproved comment', 403 );
+ }
+ }
+
+ $GLOBALS['post'] = $post;
+ setup_postdata( $post );
+ break;
+ default :
+ return new WP_Error( 'invalid_context', 'Invalid API CONTEXT', 400 );
+ }
+
+ $can_view = $this->user_can_view_post( $post->ID );
+ if ( !$can_view || is_wp_error( $can_view ) ) {
+ return $can_view;
+ }
+
+ $GLOBALS['comment'] = $comment;
+ $response = array();
+
+ foreach ( array_keys( $this->comment_object_format ) as $key ) {
+ switch ( $key ) {
+ case 'ID' :
+ // explicitly cast all output
+ $response[$key] = (int) $comment->comment_ID;
+ break;
+ case 'post' :
+ $response[$key] = (object) array(
+ 'ID' => (int) $post->ID,
+ 'type' => (string) $post->post_type,
+ 'link' => (string) $this->get_post_link( $this->api->get_blog_id_for_output(), $post->ID ),
+ );
+ break;
+ case 'author' :
+ $response[$key] = (object) $this->get_author( $comment, 'edit' === $context && current_user_can( 'edit_comment', $comment->comment_ID ) );
+ break;
+ case 'date' :
+ $response[$key] = (string) $this->format_date( $comment->comment_date_gmt, $comment->comment_date );
+ break;
+ case 'URL' :
+ $response[$key] = (string) esc_url_raw( get_comment_link( $comment->comment_ID ) );
+ break;
+ case 'short_URL' :
+ // @todo - pagination
+ $response[$key] = (string) esc_url_raw( wp_get_shortlink( $post->ID ) . "%23comment-{$comment->comment_ID}" );
+ break;
+ case 'content' :
+ if ( 'display' == $context ) {
+ ob_start();
+ comment_text();
+ $response[$key] = (string) ob_get_clean();
+ } else {
+ $response[$key] = (string) $comment->comment_content;
+ }
+ break;
+ case 'status' :
+ $response[$key] = (string) $status;
+ break;
+ case 'parent' : // (object|false)
+ if ( $comment->comment_parent ) {
+ $parent = get_comment( $comment->comment_parent );
+ $response[$key] = (object) array(
+ 'ID' => (int) $parent->comment_ID,
+ 'type' => (string) ( $parent->comment_type ? $parent->comment_type : 'comment' ),
+ 'link' => (string) $this->get_comment_link( $blog_id, $parent->comment_ID ),
+ );
+ } else {
+ $response[$key] = false;
+ }
+ break;
+ case 'type' :
+ $response[$key] = (string) ( $comment->comment_type ? $comment->comment_type : 'comment' );
+ break;
+ case 'meta' :
+ $response[$key] = (object) array(
+ 'links' => (object) array(
+ 'self' => (string) $this->get_comment_link( $this->api->get_blog_id_for_output(), $comment->comment_ID ),
+ 'help' => (string) $this->get_comment_link( $this->api->get_blog_id_for_output(), $comment->comment_ID, 'help' ),
+ 'site' => (string) $this->get_site_link( $this->api->get_blog_id_for_output() ),
+ 'post' => (string) $this->get_post_link( $this->api->get_blog_id_for_output(), $comment->comment_post_ID ),
+ 'replies' => (string) $this->get_comment_link( $this->api->get_blog_id_for_output(), $comment->comment_ID, 'replies/' ),
+// 'author' => (string) $this->get_user_link( $comment->user_id ),
+// 'via' => (string) $this->get_post_link( $ping_origin_blog_id, $ping_origin_post_id ), // Ping/trackbacks
+ ),
+ );
+ break;
+ }
+ }
+
+ unset( $GLOBALS['comment'], $GLOBALS['post'] );
+ return $response;
+ }
+}
+
+class WPCOM_JSON_API_Get_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endpoint {
+ // /sites/%s/comments/%d -> $blog_id, $comment_id
+ function callback( $path = '', $blog_id = 0, $comment_id = 0 ) {
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ $args = $this->query_args();
+
+ $return = $this->get_comment( $comment_id, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'comments' );
+
+ return $return;
+ }
+}
+
+// @todo permissions
+class WPCOM_JSON_API_List_Comments_Endpoint extends WPCOM_JSON_API_Comment_Endpoint {
+ var $date_range = array();
+
+ var $response_format = array(
+ 'found' => '(int) The total number of comments found that match the request (ignoring limits, offsets, and pagination).',
+ 'comments' => '(array:comment) An array of comment objects.',
+ );
+
+ function __construct( $args ) {
+ parent::__construct( $args );
+ $this->query = array_merge( $this->query, array(
+ 'number' => '(int=20) The number of comments to return. Limit: 100.',
+ 'offset' => '(int=0) 0-indexed offset.',
+ 'page' => '(int) Return the Nth 1-indexed page of comments. Takes precedence over the <code>offset</code> parameter.',
+ 'order' => array(
+ 'DESC' => 'Return comments in descending order from newest to oldest.',
+ 'ASC' => 'Return comments in ascending order from oldest to newest.',
+ ),
+ 'after' => '(ISO 8601 datetime) Return comments dated on or after the specified datetime.',
+ 'before' => '(ISO 8601 datetime) Return comments dated on or before the specified datetime.',
+ 'type' => array(
+ 'any' => 'Return all comments regardless of type.',
+ 'comment' => 'Return only regular comments.',
+ 'trackback' => 'Return only trackbacks.',
+ 'pingback' => 'Return only pingbacks.',
+ 'pings' => 'Return both trackbacks and pingbacks.',
+ ),
+ 'status' => array(
+ 'approved' => 'Return only approved comments.',
+ 'unapproved' => 'Return only comments in the moderation queue.',
+ 'spam' => 'Return only comments marked as spam.',
+ 'trash' => 'Return only comments in the trash.',
+ ),
+ ) );
+ }
+
+ // /sites/%s/comments/ -> $blog_id
+ // /sites/%s/posts/%d/replies/ -> $blog_id, $post_id
+ // /sites/%s/comments/%d/replies/ -> $blog_id, $comment_id
+ function callback( $path = '', $blog_id = 0, $object_id = 0 ) {
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ $args = $this->query_args();
+
+ if ( $args['number'] < 1 ) {
+ $args['number'] = 20;
+ } elseif ( 100 < $args['number'] ) {
+ return new WP_Error( 'invalid_number', 'The NUMBER parameter must be less than or equal to 100.', 400 );
+ }
+
+ if ( false !== strpos( $path, '/posts/' ) ) {
+ // We're looking for comments of a particular post
+ $post_id = $object_id;
+ $comment_id = 0;
+ } else {
+ // We're looking for comments for the whole blog, or replies to a single comment
+ $comment_id = $object_id;
+ $post_id = 0;
+ }
+
+ // We can't efficiently get the number of replies to a single comment
+ $count = false;
+ $found = -1;
+
+ if ( !$comment_id ) {
+ // We can get comment counts for the whole site or for a single post, but only for certain queries
+ if ( 'any' === $args['type'] && !isset( $args['after'] ) && !isset( $args['before'] ) ) {
+ $count = wp_count_comments( $post_id );
+ }
+ }
+
+ switch ( $args['status'] ) {
+ case 'approved' :
+ $status = 'approve';
+ if ( $count ) {
+ $found = $count->approved;
+ }
+ break;
+ default :
+ if ( !current_user_can( 'moderate_comments' ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot read non-approved comments', 403 );
+ }
+ if ( 'unapproved' === $args['status'] ) {
+ $status = 'hold';
+ $count_status = 'moderated';
+ } else {
+ $status = $count_status = $args['status'];
+ }
+ if ( $count ) {
+ $found = $count->$count_status;
+ }
+ }
+
+ $query = array(
+ 'number' => $args['number'],
+ 'order' => $args['order'],
+ 'type' => 'any' === $args['type'] ? false : $args['type'],
+ 'status' => $status,
+ );
+
+ if ( $post_id ) {
+ $post = get_post( $post_id );
+ if ( !$post || is_wp_error( $post ) ) {
+ return new WP_Error( 'unknown_post', 'Unknown post', 404 );
+ }
+ $query['post_id'] = $post->ID;
+ if ( $this->api->ends_with( $this->path, '/replies' ) ) {
+ $query['parent'] = 0;
+ }
+ } elseif ( $comment_id ) {
+ $comment = get_comment( $comment_id );
+ if ( !$comment || is_wp_error( $comment ) ) {
+ return new WP_Error( 'unknown_comment', 'Unknown comment', 404 );
+ }
+ $query['parent'] = $comment_id;
+ }
+
+ if ( isset( $args['page'] ) ) {
+ if ( $args['page'] < 1 ) {
+ $args['page'] = 1;
+ }
+
+ $query['offset'] = ( $args['page'] - 1 ) * $args['number'];
+ } else {
+ if ( $args['offset'] < 0 ) {
+ $args['offset'] = 0;
+ }
+
+ $query['offset'] = $args['offset'];
+ }
+
+ if ( isset( $args['before_gmt'] ) ) {
+ $this->date_range['before_gmt'] = $args['before_gmt'];
+ }
+ if ( isset( $args['after_gmt'] ) ) {
+ $this->date_range['after_gmt'] = $args['after_gmt'];
+ }
+
+ if ( $this->date_range ) {
+ add_filter( 'comments_clauses', array( $this, 'handle_date_range' ) );
+ }
+ $comments = get_comments( $query );
+ if ( $this->date_range ) {
+ remove_filter( 'comments_clauses', array( $this, 'handle_date_range' ) );
+ $this->date_range = array();
+ }
+
+ $return = array();
+
+ foreach ( array_keys( $this->response_format ) as $key ) {
+ switch ( $key ) {
+ case 'found' :
+ $return[$key] = (int) $found;
+ break;
+ case 'comments' :
+ $return_comments = array();
+ foreach ( $comments as $comment ) {
+ $the_comment = $this->get_comment( $comment->comment_ID, $args['context'] );
+ if ( $the_comment && !is_wp_error( $the_comment ) ) {
+ $return_comments[] = $the_comment;
+ }
+ }
+
+ if ( $return_comments ) {
+ do_action( 'wpcom_json_api_objects', 'comments', count( $return_comments ) );
+ }
+
+ $return[$key] = $return_comments;
+ break;
+ }
+ }
+
+ return $return;
+ }
+
+ function handle_date_range( $clauses ) {
+ global $wpdb;
+
+ switch ( count( $this->date_range ) ) {
+ case 2 :
+ $clauses['where'] .= $wpdb->prepare(
+ " AND `$wpdb->comments`.comment_date_gmt BETWEEN CAST( %s AS DATETIME ) AND CAST( %s AS DATETIME ) ",
+ $this->date_range['after_gmt'],
+ $this->date_range['before_gmt']
+ );
+ break;
+ case 1 :
+ if ( isset( $this->date_range['before_gmt'] ) ) {
+ $clauses['where'] .= $wpdb->prepare(
+ " AND `$wpdb->comments`.comment_date_gmt <= CAST( %s AS DATETIME ) ",
+ $this->date_range['before_gmt']
+ );
+ } else {
+ $clauses['where'] .= $wpdb->prepare(
+ " AND `$wpdb->comments`.comment_date_gmt >= CAST( %s AS DATETIME ) ",
+ $this->date_range['after_gmt']
+ );
+ }
+ break;
+ }
+
+ return $clauses;
+ }
+}
+
+class WPCOM_JSON_API_Update_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endpoint {
+ function __construct( $args ) {
+ parent::__construct( $args );
+ if ( $this->api->ends_with( $this->path, '/delete' ) ) {
+ $this->comment_object_format['status']['deleted'] = 'The comment has been deleted permanently.';
+ }
+ }
+
+ // /sites/%s/posts/%d/replies/new -> $blog_id, $post_id
+ // /sites/%s/comments/%d/replies/new -> $blog_id, $comment_id
+ // /sites/%s/comments/%d -> $blog_id, $comment_id
+ // /sites/%s/comments/%d/delete -> $blog_id, $comment_id
+ function callback( $path = '', $blog_id = 0, $object_id = 0 ) {
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ if ( $this->api->ends_with( $path, '/delete' ) ) {
+ return $this->delete_comment( $path, $blog_id, $object_id );
+ } elseif ( $this->api->ends_with( $path, '/new' ) ) {
+ if ( false !== strpos( $path, '/posts/' ) ) {
+ return $this->new_comment( $path, $blog_id, $object_id, 0 );
+ } else {
+ return $this->new_comment( $path, $blog_id, 0, $object_id );
+ }
+ }
+
+ return $this->update_comment( $path, $blog_id, $object_id );
+ }
+
+ // /sites/%s/posts/%d/replies/new -> $blog_id, $post_id
+ // /sites/%s/comments/%d/replies/new -> $blog_id, $comment_id
+ function new_comment( $path, $blog_id, $post_id, $comment_parent_id ) {
+ if ( !$post_id ) {
+ $comment_parent = get_comment( $comment_parent_id );
+ if ( !$comment_parent_id || !$comment_parent || is_wp_error( $comment_parent ) ) {
+ return new WP_Error( 'unknown_comment', 'Unknown comment', 404 );
+ }
+
+ $post_id = $comment_parent->comment_post_ID;
+ }
+
+ $post = get_post( $post_id );
+ if ( !$post || is_wp_error( $post ) ) {
+ return new WP_Error( 'unknown_post', 'Unknown post', 404 );
+ }
+
+ if ( -1 == get_option( 'blog_public' ) && ! is_user_member_of_blog() && ! is_super_admin() ) {
+ return new WP_Error( 'unauthorized', 'User cannot create comments', 403 );
+ }
+
+ if ( !comments_open( $post->ID ) ) {
+ return new WP_Error( 'unauthorized', 'Comments on this post are closed', 403 );
+ }
+
+ $can_view = $this->user_can_view_post( $post->ID );
+ if ( !$can_view || is_wp_error( $can_view ) ) {
+ return $can_view;
+ }
+
+ $post_status = get_post_status_object( $post->post_status );
+ if ( !$post_status->public && !$post_status->private ) {
+ return new WP_Error( 'unauthorized', 'Comments on drafts are not allowed', 403 );
+ }
+
+ $args = $this->query_args();
+ $input = $this->input();
+ if ( !is_array( $input ) || !$input || !strlen( $input['content'] ) ) {
+ return new WP_Error( 'invalid_input', 'Invalid request input', 400 );
+ }
+
+ $user = wp_get_current_user();
+ if ( !$user || is_wp_error( $user ) || !$user->ID ) {
+ $auth_required = false;
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ $auth_required = true;
+ } elseif ( isset( $this->api->token_details['user'] ) ) {
+ $user = (object) $this->api->token_details['user'];
+ foreach ( array( 'display_name', 'user_email', 'user_url' ) as $user_datum ) {
+ if ( !isset( $user->$user_datum ) ) {
+ $auth_required = true;
+ }
+ }
+ if ( !isset( $user->ID ) ) {
+ $user->ID = 0;
+ }
+ } else {
+ $auth_required = true;
+ }
+
+ if ( $auth_required ) {
+ return new WP_Error( 'authorization_required', 'An active access token must be used to comment.', 403 );
+ }
+ }
+
+ $insert = array(
+ 'comment_post_ID' => $post->ID,
+ 'user_ID' => $user->ID,
+ 'comment_author' => $user->display_name,
+ 'comment_author_email' => $user->user_email,
+ 'comment_author_url' => $user->user_url,
+ 'comment_content' => $input['content'],
+ 'comment_parent' => $comment_parent_id,
+ 'comment_type' => '',
+ );
+
+ $this->api->trap_wp_die( 'comment_failure' );
+ $comment_id = wp_new_comment( add_magic_quotes( $insert ) );
+ $this->api->trap_wp_die( null );
+
+ $return = $this->get_comment( $comment_id, $args['context'] );
+ if ( !$return ) {
+ return new WP_Error( 400, __( 'Comment cache problem?', 'jetpack' ) );
+ }
+ if ( is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'comments' );
+ return $return;
+ }
+
+ // /sites/%s/comments/%d -> $blog_id, $comment_id
+ function update_comment( $path, $blog_id, $comment_id ) {
+ $comment = get_comment( $comment_id );
+ if ( !$comment || is_wp_error( $comment ) ) {
+ return new WP_Error( 'unknown_comment', 'Unknown comment', 404 );
+ }
+
+ if ( !current_user_can( 'edit_comment', $comment->comment_ID ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot edit comment', 403 );
+ }
+
+ $args = $this->query_args();
+ $input = $this->input( false );
+ if ( !is_array( $input ) || !$input ) {
+ return new WP_Error( 'invalid_input', 'Invalid request input', 400 );
+ }
+
+ $update = array();
+ foreach ( $input as $key => $value ) {
+ $update["comment_$key"] = $value;
+ }
+
+ $comment_status = wp_get_comment_status( $comment->comment_ID );
+ if ( $comment_status !== $update['status'] && !current_user_can( 'moderate_comments' ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot moderate comments', 403 );
+ }
+
+ if ( isset( $update['comment_status'] ) ) {
+ switch ( $update['comment_status'] ) {
+ case 'unapproved' :
+ $update['comment_approved'] = 0;
+ break;
+ case 'spam' :
+ if ( 'spam' != $comment_status ) {
+ wp_spam_comment( $comment->comment_ID );
+ }
+ break;
+ case 'unspam' :
+ if ( 'spam' == $comment_status ) {
+ wp_unspam_comment( $comment->comment_ID );
+ }
+ break;
+ case 'trash' :
+ if ( ! EMPTY_TRASH_DAYS ) {
+ return new WP_Error( 'trash_disabled', 'Cannot trash comment', 403 );
+ }
+
+ if ( 'trash' != $comment_status ) {
+ wp_trash_comment( $comment_id );
+ }
+ break;
+ case 'untrash' :
+ if ( 'trash' == $comment_status ) {
+ wp_untrash_comment( $comment->comment_ID );
+ }
+ break;
+ default:
+ $update['comment_approved'] = 1;
+ break;
+ }
+ unset( $update['comment_status'] );
+ }
+
+ $update['comment_ID'] = $comment->comment_ID;
+
+ wp_update_comment( add_magic_quotes( $update ) );
+
+ $return = $this->get_comment( $comment->comment_ID, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'comments' );
+ return $return;
+ }
+
+ // /sites/%s/comments/%d/delete -> $blog_id, $comment_id
+ function delete_comment( $path, $blog_id, $comment_id ) {
+ $comment = get_comment( $comment_id );
+ if ( !$comment || is_wp_error( $comment ) ) {
+ return new WP_Error( 'unknown_comment', 'Unknown comment', 404 );
+ }
+
+ if ( !current_user_can( 'edit_comment', $comment->comment_ID ) ) { // [sic] There is no delete_comment cap
+ return new WP_Error( 'unauthorized', 'User cannot delete comment', 403 );
+ }
+
+ $args = $this->query_args();
+ $return = $this->get_comment( $comment->comment_ID, $args['context'] );
+ if ( !$return || is_wp_error( $return ) ) {
+ return $return;
+ }
+
+ do_action( 'wpcom_json_api_objects', 'comments' );
+
+ wp_delete_comment( $comment->comment_ID );
+ $status = wp_get_comment_status( $comment->comment_ID );
+ if ( false === $status ) {
+ $return['status'] = 'deleted';
+ return $return;
+ }
+
+ return $this->get_comment( $comment->comment_ID, $args['context'] );
+ }
+}
+
+class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint {
+ // /sites/mine
+ // /sites/%s -> $blog_id
+ function callback( $path = '', $blog_id = 0 ) {
+ global $wpdb;
+ if ( 'mine' === $blog_id ) {
+ $api = WPCOM_JSON_API::init();
+ if ( !$api->token_details || empty( $api->token_details['blog_id'] ) ) {
+ return new WP_Error( 'authorization_required', 'An active access token must be used to query information about the current blog.', 403 );
+ }
+ $blog_id = $api->token_details['blog_id'];
+ }
+
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
+ if ( is_wp_error( $blog_id ) ) {
+ return $blog_id;
+ }
+
+ $is_user_logged_in = is_user_logged_in();
+
+ $response = array();
+ foreach ( array_keys( $this->response_format ) as $key ) {
+ switch ( $key ) {
+ case 'ID' :
+ $response[$key] = (int) $this->api->get_blog_id_for_output();
+ break;
+ case 'name' :
+ $response[$key] = (string) get_bloginfo( 'name' );
+ break;
+ case 'description' :
+ $response[$key] = (string) get_bloginfo( 'description' );
+ break;
+ case 'URL' :
+ $response[$key] = (string) home_url();
+ break;
+ case 'jetpack' :
+ if ( $is_user_logged_in )
+ $response[$key] = false; // magic
+ break;
+ case 'post_count' :
+ if ( $is_user_logged_in )
+ $response[$key] = (int) $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status = 'publish'");
+ break;
+ case 'lang' :
+ if ( $is_user_logged_in )
+ $response[$key] = (string) get_bloginfo( 'language' );
+ break;
+ case 'meta' :
+ $response[$key] = (object) array(
+ 'links' => (object) array(
+ 'self' => (string) $this->get_site_link( $this->api->get_blog_id_for_output() ),
+ 'help' => (string) $this->get_site_link( $this->api->get_blog_id_for_output(), 'help' ),
+ 'posts' => (string) $this->get_site_link( $this->api->get_blog_id_for_output(), 'posts/' ),
+ 'comments' => (string) $this->get_site_link( $this->api->get_blog_id_for_output(), 'comments/' ),
+ ),
+ );
+ break;
+ }
+ }
+
+ do_action( 'wpcom_json_api_objects', 'sites' );
+
+ return $response;
+ }
+}
+
+/*
+ * Set up endpoints
+ */
+
+/*
+ * Site endpoints
+ */
+new WPCOM_JSON_API_GET_Site_Endpoint( array(
+ 'description' => 'Information about a site ID/domain',
+ 'group' => 'Sites',
+ 'stat' => 'sites:X',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ ),
+
+ 'query_parameters' => array(
+ 'context' => false,
+ ),
+
+ 'response_format' => array(
+ 'ID' => '(int) Blog ID',
+ 'name' => '(string) Title of blog',
+ 'description' => '(string) Tagline or description of blog',
+ 'URL' => '(string) Full URL to the blog',
+ 'jetpack' => '(bool) Whether the blog is a Jetpack blog or not',
+ 'post_count' => '(int) The number of posts the blog has',
+ 'lang' => '(string) Primary language code of the blog',
+ 'meta' => '(object) Meta data',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/?pretty=1',
+) );
+
+
+/*
+ * Post endpoints
+ */
+new WPCOM_JSON_API_List_Posts_Endpoint( array(
+ 'description' => 'Return matching Posts',
+ 'group' => 'Posts',
+ 'stat' => 'posts',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/posts/',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ ),
+
+ 'query_parameters' => array(
+ 'number' => '(int=20) The number of posts to return. Limit: 100.',
+ 'offset' => '(int=0) 0-indexed offset.',
+ 'page' => '(int) Return the Nth 1-indexed page of posts. Takes precedence over the <code>offset</code> parameter.',
+ 'order' => array(
+ 'DESC' => 'Return posts in descending order. For dates, that means newest to oldest.',
+ 'ASC' => 'Return posts in ascending order. For dates, that means oldest to newest.',
+ ),
+ 'order_by' => array(
+ 'date' => 'Order by the created time of each post.',
+ 'modified' => 'Order by the modified time of each post.',
+ 'title' => "Order lexicographically by the posts' titles.",
+ 'comment_count' => 'Order by the number of comments for each post.',
+ ),
+ 'after' => '(ISO 8601 datetime) Return posts dated on or after the specified datetime.',
+ 'before' => '(ISO 8601 datetime) Return posts dated on or before the specified datetime.',
+ 'tag' => '(string) Specify the tag name or slug.',
+ 'category' => '(string) Specify the category name or slug.',
+ 'type' => array(
+ 'post' => 'Return only blog posts.',
+ 'page' => 'Return only pages.',
+ 'any' => 'Return both blog posts and pages.',
+ ),
+ 'status' => array(
+ 'publish' => 'Return only published posts.',
+ 'private' => 'Return only private posts.',
+ 'draft' => 'Return only draft posts.',
+ 'pending' => 'Return only posts pending editorial approval.',
+ 'future' => 'Return only posts scheduled for future publishing.',
+ 'trash' => 'Return only posts in the trash.',
+ 'any' => 'Return all posts regardless of status.',
+ ),
+ 'sticky' => '(bool) Specify the stickiness.',
+ 'author' => "(int) Author's user ID",
+ 'search' => '(string) Search query',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/posts/?number=5&pretty=1'
+) );
+
+new WPCOM_JSON_API_Get_Post_Endpoint( array(
+ 'description' => 'Return a single Post (by ID)',
+ 'group' => 'Posts',
+ 'stat' => 'posts:1',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/posts/%d',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$post_ID' => '(int) The post ID',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/posts/7/?pretty=1'
+) );
+
+new WPCOM_JSON_API_Get_Post_Endpoint( array(
+ 'description' => 'Return a single Post (by name)',
+ 'group' => '__do_not_document',
+ 'stat' => 'posts:name',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/posts/name:%s',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$post_name' => '(string) The post name (a.k.a. slug)',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/posts/name:blogging-and-stuff?pretty=1',
+) );
+
+new WPCOM_JSON_API_Get_Post_Endpoint( array(
+ 'description' => 'Return a single Post (by slug)',
+ 'group' => 'Posts',
+ 'stat' => 'posts:slug',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/posts/slug:%s',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$post_slug' => '(string) The post slug (a.k.a. sanitized name)',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/posts/slug:blogging-and-stuff?pretty=1',
+) );
+
+new WPCOM_JSON_API_Update_Post_Endpoint( array(
+ 'description' => 'Create a Post',
+ 'group' => 'Posts',
+ 'stat' => 'posts:new',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/posts/new',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ ),
+
+ 'request_format' => array(
+ // explicitly document all input
+ 'date' => "(ISO 8601 datetime) The post's creation time.",
+ 'title' => '(HTML) The post title.',
+ 'content' => '(HTML) The post content.',
+ 'excerpt' => '(HTML) An optional post excerpt.',
+ 'slug' => '(string) The name (slug) for your post, used in URLs.',
+ 'publicize' => '(array|bool) True or false if the post be publicized to external services. An array of services if we only want to publicize to a select few. Defaults to true.',
+ 'publicize_message' => '(string) Custom message to be publicized to external services.',
+ 'status' => array(
+ 'publish' => 'Publish the post.',
+ 'private' => 'Privately publish the post.',
+ 'draft' => 'Save the post as a draft.',
+ 'pending' => 'Mark the post as pending editorial approval.',
+ ),
+ 'password' => '(string) The plaintext password protecting the post, or, more likely, the empty string if the post is not password protected.',
+ 'parent' => "(int) The post ID of the new post's parent.",
+ 'type' => array(
+ 'post' => 'Create a blog post.',
+ 'page' => 'Create a page.',
+ ),
+ 'categories' => "(array|string) Comma separated list or array of categories (name or id)",
+ 'tags' => "(array|string) Comma separated list or array of tags (name or id)",
+ 'format' => get_post_format_strings(),
+ 'media' => "(media) An array of images to attach to the post. To upload media, the entire request should be multipart/form-data encoded. Multiple media items will be displayed in a gallery. Accepts images (image/gif, image/jpeg, image/png) only.<br /><br /><strong>Example</strong>:<br />" .
+ "<code>curl \<br />--form 'title=Image' \<br />--form 'media[]=@/path/to/file.jpg' \<br />-H 'Authorization: BEARER your-token' \<br />'https://public-api.wordpress.com/rest/v1/sites/123/posts/new'</code>",
+ 'comments_open' => "(bool) Should the post be open to comments? Defaults to the blog's preference.",
+ 'pings_open' => "(bool) Should the post be open to comments? Defaults to the blog's preference.",
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/posts/new/',
+
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+
+ 'body' => array(
+ 'title' => 'Hello World',
+ 'content' => 'Hello. I am a test post. I was created by the API',
+ 'tags' => 'tests',
+ 'categories' => 'API'
+ )
+ ),
+
+ 'example_response' => '
+{
+ "ID": 1270,
+ "author": {
+ "ID": 18342963,
+ "email": false,
+ "name": "binarysmash",
+ "URL": "http:\/\/binarysmash.wordpress.com",
+ "avatar_URL": "http:\/\/0.gravatar.com\/avatar\/a178ebb1731d432338e6bb0158720fcc?s=96&d=identicon&r=G",
+ "profile_URL": "http:\/\/en.gravatar.com\/binarysmash"
+ },
+ "date": "2012-04-11T19:42:44+00:00",
+ "modified": "2012-04-11T19:42:44+00:00",
+ "title": "Hello World",
+ "URL": "http:\/\/opossumapi.wordpress.com\/2012\/04\/11\/hello-world-3\/",
+ "short_URL": "http:\/\/wp.me\/p23HjV-ku",
+ "content": "<p>Hello. I am a test post. I was created by the API<\/p>\n",
+ "excerpt": "<p>Hello. I am a test post. I was created by the API<\/p>\n",
+ "status": "publish",
+ "password": "",
+ "parent": false,
+ "type": "post",
+ "comments_open": true,
+ "pings_open": true,
+ "comment_count": 0,
+ "like_count": 0,
+ "featured_image": "",
+ "format": "standard",
+ "geo": false,
+ "publicize_URLs": [
+
+ ],
+ "tags": {
+ "tests": {
+ "name": "tests",
+ "slug": "tests",
+ "description": "",
+ "post_count": 1,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/tests",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/tests\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+ }
+ },
+ "categories": {
+ "API": {
+ "name": "API",
+ "slug": "api",
+ "description": "",
+ "post_count": 1,
+ "parent": 0,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/categories\/api",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/categories\/api\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+ }
+ },
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1270",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1270\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183",
+ "replies": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1270\/replies\/",
+ "likes": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1270\/likes\/"
+ }
+ }
+}'
+) );
+
+new WPCOM_JSON_API_Update_Post_Endpoint( array(
+ 'description' => 'Edit a Post',
+ 'group' => 'Posts',
+ 'stat' => 'posts:1:POST',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/posts/%d',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$post_ID' => '(int) The post ID',
+ ),
+
+ 'request_format' => array(
+ 'date' => "(ISO 8601 datetime) The post's creation time.",
+ 'title' => '(HTML) The post title.',
+ 'content' => '(HTML) The post content.',
+ 'excerpt' => '(HTML) An optional post excerpt.',
+ 'slug' => '(string) The name (slug) for your post, used in URLs.',
+ 'publicize' => '(array|bool) True or false if the post be publicized to external services. An array of services if we only want to publicize to a select few. Defaults to true.',
+ 'publicize_message' => '(string) Custom message to be publicized to external services.',
+ 'status' => array(
+ 'publish' => 'Publish the post.',
+ 'private' => 'Privately publish the post.',
+ 'draft' => 'Save the post as a draft.',
+ 'pending' => 'Mark the post as pending editorial approval.',
+ ),
+ 'password' => '(string) The plaintext password protecting the post, or, more likely, the empty string if the post is not password protected.',
+ 'parent' => "(int) The post ID of the new post's parent.",
+ 'categories' => "(string) Comma separated list of categories (name or id)",
+ 'tags' => "(string) Comma separated list of tags (name or id)",
+ 'format' => get_post_format_strings(),
+ 'comments_open' => '(bool) Should the post be open to comments?',
+ 'pings_open' => '(bool) Should the post be open to comments?',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/posts/1222/',
+
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+
+ 'body' => array(
+ 'title' => 'Hello World (Again)',
+ 'content' => 'Hello. I am an edited post. I was edited by the API',
+ 'tags' => 'tests',
+ 'categories' => 'API'
+ )
+ ),
+
+ 'example_response' => '
+{
+ "ID": 1222,
+ "author": {
+ "ID": 422,
+ "email": false,
+ "name": "Justin Shreve",
+ "URL": "http:\/\/justin.wordpress.com",
+ "avatar_URL": "http:\/\/1.gravatar.com\/avatar\/9ea5b460afb2859968095ad3afe4804b?s=96&d=identicon&r=G",
+ "profile_URL": "http:\/\/en.gravatar.com\/justin"
+ },
+ "date": "2012-04-11T15:53:52+00:00",
+ "modified": "2012-04-11T19:44:35+00:00",
+ "title": "Hello World (Again)",
+ "URL": "http:\/\/opossumapi.wordpress.com\/2012\/04\/11\/hello-world-2\/",
+ "short_URL": "http:\/\/wp.me\/p23HjV-jI",
+ "content": "<p>Hello. I am an edited post. I was edited by the API<\/p>\n",
+ "excerpt": "<p>Hello. I am an edited post. I was edited by the API<\/p>\n",
+ "status": "publish",
+ "password": "",
+ "parent": false,
+ "type": "post",
+ "comments_open": true,
+ "pings_open": true,
+ "comment_count": 5,
+ "like_count": 0,
+ "featured_image": "",
+ "format": "standard",
+ "geo": false,
+ "publicize_URLs": [
+
+ ],
+ "tags": {
+ "tests": {
+ "name": "tests",
+ "slug": "tests",
+ "description": "",
+ "post_count": 2,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/tests",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/tests\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+ }
+ },
+ "categories": {
+ "API": {
+ "name": "API",
+ "slug": "api",
+ "description": "",
+ "post_count": 2,
+ "parent": 0,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/categories\/api",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/categories\/api\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+ }
+ },
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183",
+ "replies": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222\/replies\/",
+ "likes": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222\/likes\/"
+ }
+ }
+}'
+
+) );
+
+new WPCOM_JSON_API_Update_Post_Endpoint( array(
+ 'description' => 'Delete a Post',
+ 'group' => 'Posts',
+ 'stat' => 'posts:1:delete',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/posts/%d/delete',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$post_ID' => '(int) The post ID',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/posts/1222/delete/',
+
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ )
+ ),
+
+ 'example_response' => '
+{
+ "ID": 1222,
+ "author": {
+ "ID": 422,
+ "email": false,
+ "name": "Justin Shreve",
+ "URL": "http:\/\/justin.wordpress.com",
+ "avatar_URL": "http:\/\/1.gravatar.com\/avatar\/9ea5b460afb2859968095ad3afe4804b?s=96&d=identicon&r=G",
+ "profile_URL": "http:\/\/en.gravatar.com\/justin"
+ },
+ "date": "2012-04-11T15:53:52+00:00",
+ "modified": "2012-04-11T19:49:42+00:00",
+ "title": "Hello World (Again)",
+ "URL": "http:\/\/opossumapi.wordpress.com\/2012\/04\/11\/hello-world-2\/",
+ "short_URL": "http:\/\/wp.me\/p23HjV-jI",
+ "content": "<p>Hello. I am an edited post. I was edited by the API<\/p>\n",
+ "excerpt": "<p>Hello. I am an edited post. I was edited by the API<\/p>\n",
+ "status": "trash",
+ "password": "",
+ "parent": false,
+ "type": "post",
+ "comments_open": true,
+ "pings_open": true,
+ "comment_count": 5,
+ "like_count": 0,
+ "featured_image": "",
+ "format": "standard",
+ "geo": false,
+ "publicize_URLs": [
+
+ ],
+ "tags": {
+ "tests": {
+ "name": "tests",
+ "slug": "tests",
+ "description": "",
+ "post_count": 1,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/tests",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/tests\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+ }
+ },
+ "categories": {
+ "API": {
+ "name": "API",
+ "slug": "api",
+ "description": "",
+ "post_count": 1,
+ "parent": 0,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/categories\/api",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/categories\/api\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+ }
+ },
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183",
+ "replies": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222\/replies\/",
+ "likes": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222\/likes\/"
+ }
+ }
+}'
+
+) );
+
+/*
+ * Comment endpoints
+ */
+new WPCOM_JSON_API_List_Comments_Endpoint( array(
+ 'description' => 'Return recent Comments',
+ 'group' => 'Comments',
+ 'stat' => 'comments',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/comments/',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/comments/?number=5&pretty=1'
+) );
+
+new WPCOM_JSON_API_List_Comments_Endpoint( array(
+ 'description' => 'Return recent Comments for a Post',
+ 'group' => 'Comments',
+ 'stat' => 'posts:1:replies',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/posts/%d/replies/',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$post_ID' => '(int) The post ID',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/posts/7/replies/?number=5&pretty=1'
+) );
+
+new WPCOM_JSON_API_Get_Comment_Endpoint( array(
+ 'description' => 'Return a single Comment',
+ 'group' => 'Comments',
+ 'stat' => 'comments:1',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/comments/%d',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$comment_ID' => '(int) The comment ID'
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/comments/11/?pretty=1'
+) );
+
+new WPCOM_JSON_API_Update_Comment_Endpoint( array(
+ 'description' => 'Create a Comment on a Post',
+ 'group' => 'Comments',
+ 'stat' => 'posts:1:replies:new',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/posts/%d/replies/new',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$post_ID' => '(int) The post ID'
+ ),
+
+ 'request_format' => array(
+ // explicitly document all input
+ 'content' => '(HTML) The comment text.',
+// @todo Should we open this up to unauthenticated requests too?
+// 'author' => '(author object) The author of the comment.',
+ ),
+
+ 'pass_wpcom_user_details' => true,
+ 'can_use_user_details_instead_of_blog_membership' => true,
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/posts/1222/replies/new/',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'content' => 'Your reply is very interesting. This is a reply.'
+ )
+ ),
+
+ 'example_response' => '
+{
+ "ID": 9,
+ "post": {
+ "ID": 1222,
+ "type": "post",
+ "link": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222"
+ },
+ "author": {
+ "ID": 18342963,
+ "email": false,
+ "name": "binarysmash",
+ "URL": "http:\/\/binarysmash.wordpress.com",
+ "avatar_URL": "http:\/\/0.gravatar.com\/avatar\/a178ebb1731d432338e6bb0158720fcc?s=96&d=identicon&r=G",
+ "profile_URL": "http:\/\/en.gravatar.com\/binarysmash"
+ },
+ "date": "2012-04-11T18:09:41+00:00",
+ "URL": "http:\/\/opossumapi.wordpress.com\/2012\/04\/11\/hello-world-2\/#comment-9",
+ "short_URL": "http:\/\/wp.me\/p23HjV-jI%23comment-9",
+ "content": "<p>Your reply is very interesting. This is a reply.<\/p>\n",
+ "status": "approved",
+ "parent": {
+ "ID":8,
+ "type": "comment",
+ "link": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/8"
+ },
+ "type": "comment",
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/9",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/9\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183",
+ "post": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222",
+ "replies": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/9\/replies\/"
+ }
+ }
+}',
+) );
+
+new WPCOM_JSON_API_Update_Comment_Endpoint( array(
+ 'description' => 'Create a Comment as a reply to another Comment',
+ 'group' => 'Comments',
+ 'stat' => 'comments:1:replies:new',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/comments/%d/replies/new',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$comment_ID' => '(int) The comment ID'
+ ),
+
+ 'request_format' => array(
+ 'content' => '(HTML) The comment text.',
+// @todo Should we open this up to unauthenticated requests too?
+// 'author' => '(author object) The author of the comment.',
+ ),
+
+ 'pass_wpcom_user_details' => true,
+ 'can_use_user_details_instead_of_blog_membership' => true,
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/comments/8/replies/new/',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'content' => 'This reply is very interesting. This is editing a comment reply via the API.',
+ )
+ ),
+ 'example_response' => '
+{
+ "ID": 13,
+ "post": {
+ "ID": 1,
+ "type": "post",
+ "link": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1"
+ },
+ "author": {
+ "ID": 18342963,
+ "email": false,
+ "name": "binarysmash",
+ "URL": "http:\/\/binarysmash.wordpress.com",
+ "avatar_URL": "http:\/\/0.gravatar.com\/avatar\/a178ebb1731d432338e6bb0158720fcc?s=96&d=identicon&r=G",
+ "profile_URL": "http:\/\/en.gravatar.com\/binarysmash"
+ },
+ "date": "2012-04-11T20:16:28+00:00",
+ "URL": "http:\/\/opossumapi.wordpress.com\/2011\/12\/13\/hello-world\/#comment-13",
+ "short_URL": "http:\/\/wp.me\/p23HjV-1%23comment-13",
+ "content": "<p>This reply is very interesting. This is editing a comment reply via the API.<\/p>\n",
+ "status": "approved",
+ "parent": {
+ "ID": 1,
+ "type": "comment",
+ "link": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/1"
+ },
+ "type": "comment",
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183",
+ "post": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1",
+ "replies": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13\/replies\/"
+ }
+ }
+}'
+
+) );
+
+new WPCOM_JSON_API_Update_Comment_Endpoint( array(
+ 'description' => 'Edit a Comment',
+ 'group' => 'Comments',
+ 'stat' => 'comments:1:POST',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/comments/%d',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$comment_ID' => '(int) The comment ID'
+ ),
+
+ 'request_format' => array(
+ 'date' => "(ISO 8601 datetime) The comment's creation time.",
+ 'content' => '(HTML) The comment text.',
+ 'status' => array(
+ 'approved' => 'Approve the comment.',
+ 'unapproved' => 'Remove the comment from public view and send it to the moderation queue.',
+ 'spam' => 'Mark the comment as spam.',
+ 'unspam' => 'Unmark the comment as spam. Will attempt to set it to the previous status.',
+ 'trash' => 'Send a comment to the trash if trashing is enabled (see constant: EMPTY_TRASH_DAYS).',
+ 'untrash' => 'Untrash a comment. Only works when the comment is in the trash.',
+ ),
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/comments/8/',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'content' => 'This reply is now edited via the API.',
+ 'status' => 'approved',
+ )
+ ),
+ 'example_response' => '
+{
+ "ID": 13,
+ "post": {
+ "ID": 1,
+ "type": "post",
+ "link": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1"
+ },
+ "author": {
+ "ID": 18342963,
+ "email": false,
+ "name": "binarysmash",
+ "URL": "http:\/\/binarysmash.wordpress.com",
+ "avatar_URL": "http:\/\/0.gravatar.com\/avatar\/a178ebb1731d432338e6bb0158720fcc?s=96&d=identicon&r=G",
+ "profile_URL": "http:\/\/en.gravatar.com\/binarysmash"
+ },
+ "date": "2012-04-11T20:16:28+00:00",
+ "URL": "http:\/\/opossumapi.wordpress.com\/2011\/12\/13\/hello-world\/#comment-13",
+ "short_URL": "http:\/\/wp.me\/p23HjV-1%23comment-13",
+ "content": "<p>This reply is very interesting. This is editing a comment reply via the API.<\/p>\n",
+ "status": "approved",
+ "parent": {
+ "ID": 1,
+ "type": "comment",
+ "link": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/1"
+ },
+ "type": "comment",
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183",
+ "post": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1",
+ "replies": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13\/replies\/"
+ }
+ }
+}'
+
+) );
+
+new WPCOM_JSON_API_Update_Comment_Endpoint( array(
+ 'description' => 'Delete a Comment',
+ 'group' => 'Comments',
+ 'stat' => 'comments:1:delete',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/comments/%d/delete',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$comment_ID' => '(int) The comment ID'
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/comments/8/delete/',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ )
+ ),
+
+ 'example_response' => '
+{
+ "ID": 13,
+ "post": {
+ "ID": 1,
+ "type": "post",
+ "link": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1"
+ },
+ "author": {
+ "ID": 18342963,
+ "email": false,
+ "name": "binarysmash",
+ "URL": "http:\/\/binarysmash.wordpress.com",
+ "avatar_URL": "http:\/\/0.gravatar.com\/avatar\/a178ebb1731d432338e6bb0158720fcc?s=96&d=identicon&r=G",
+ "profile_URL": "http:\/\/en.gravatar.com\/binarysmash"
+ },
+ "date": "2012-04-11T20:16:28+00:00",
+ "URL": "http:\/\/opossumapi.wordpress.com\/2011\/12\/13\/hello-world\/#comment-13",
+ "short_URL": "http:\/\/wp.me\/p23HjV-1%23comment-13",
+ "content": "<p>This reply is very interesting. This is editing a comment reply via the API.<\/p>\n",
+ "status": "deleted",
+ "parent": {
+ "ID": 1,
+ "type": "comment",
+ "link": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/1"
+ },
+ "type": "comment",
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183",
+ "post": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1",
+ "replies": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/comments\/13\/replies\/"
+ }
+ }
+}'
+
+) );
+
+/**
+ * Taxonomy Management Endpoints
+ */
+new WPCOM_JSON_API_Get_Taxonomy_Endpoint( array(
+ 'description' => 'Returns information on a single Category',
+ 'group' => 'Taxonomy',
+ 'stat' => 'categories:1',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/categories/slug:%s',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$category' => '(string) The category slug'
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/categories/slug:community?pretty=1'
+) );
+
+new WPCOM_JSON_API_Get_Taxonomy_Endpoint( array(
+ 'description' => 'Returns information on a single Tag',
+ 'group' => 'Taxonomy',
+ 'stat' => 'tags:1',
+
+ 'method' => 'GET',
+ 'path' => '/sites/%s/tags/slug:%s',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$tag' => '(string) The tag slug'
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/tags/slug:wordpresscom?pretty=1'
+) );
+
+new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
+ 'description' => 'Create a new Category',
+ 'group' => 'Taxonomy',
+ 'stat' => 'categories:new',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/categories/new',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ ),
+
+ 'request_format' => array(
+ 'name' => '(string) Name of the category',
+ 'description' => '(string) A description of the category',
+ 'parent' => '(id) ID of the parent category',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/categories/new/',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'name' => 'Puppies',
+ )
+ ),
+ 'example_response' => '
+{
+ "name": "Puppies",
+ "slug": "puppies",
+ "description": "",
+ "post_count": 0,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/puppies",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/puppies\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+}'
+
+) );
+
+new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
+ 'description' => 'Create a new Tag',
+ 'group' => 'Taxonomy',
+ 'stat' => 'tags:new',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/tags/new',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ ),
+
+ 'request_format' => array(
+ 'name' => '(string) Name of the tag',
+ 'description' => '(string) A description of the tag',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/tags/new/',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'name' => 'Kitties'
+ )
+ ),
+ 'example_response' => '
+{
+ "name": "Kitties",
+ "slug": "kitties",
+ "description": "",
+ "post_count": 0,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/kitties",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/kitties\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+}'
+
+) );
+
+new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
+ 'description' => 'Edit a Tag',
+ 'group' => 'Taxonomy',
+ 'stat' => 'tags:1:POST',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/tags/slug:%s',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$tag' => '(string) The tag slug',
+ ),
+
+ 'request_format' => array(
+ 'name' => '(string) Name of the tag',
+ 'description' => '(string) A description of the tag',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/tags/slug:testing-tag',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'description' => 'Kitties are awesome!'
+ )
+ ),
+ 'example_response' => '
+{
+ "name": "testing tag",
+ "slug": "testing-tag",
+ "description": "Kitties are awesome!",
+ "post_count": 0,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/testing-tag",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/tags\/testing-tag\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+}'
+
+) );
+
+new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
+ 'description' => 'Edit a Category',
+ 'group' => 'Taxonomy',
+ 'stat' => 'categories:1:POST',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/categories/slug:%s',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$category' => '(string) The category slug',
+ ),
+
+ 'request_format' => array(
+ 'name' => '(string) Name of the category',
+ 'description' => '(string) A description of the category',
+ 'parent' => '(id) ID of the parent category',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/categories/slug:testing-category',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ 'body' => array(
+ 'description' => 'Puppies are great!'
+ )
+ ),
+ 'example_response' => '
+{
+ "name": "testing category",
+ "slug": "testing-category",
+ "description": "Puppies are great!",
+ "post_count": 0,
+ "parent": 0,
+ "meta": {
+ "links": {
+ "self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/categories\/testing-category",
+ "help": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/categories\/testing-category\/help",
+ "site": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183"
+ }
+ }
+}'
+
+) );
+
+new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
+ 'description' => 'Delete a Category',
+ 'group' => 'Taxonomy',
+ 'stat' => 'categories:1:delete',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/categories/slug:%s/delete',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$category' => '(string) The category slug',
+ ),
+ 'response_format' => array(
+ 'slug' => '(string) The slug of the deleted category',
+ 'success' => '(bool) Was the operation successful?',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/categories/slug:some-category-name/delete',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ ),
+ 'example_response' => '{
+ "slug": "some-category-name",
+ "success": "true"
+}'
+) );
+
+new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
+ 'description' => 'Delete a Tag',
+ 'group' => 'Taxonomy',
+ 'stat' => 'tags:1:delete',
+
+ 'method' => 'POST',
+ 'path' => '/sites/%s/tags/slug:%s/delete',
+ 'path_labels' => array(
+ '$site' => '(int|string) The site ID, The site domain',
+ '$tag' => '(string) The tag slug',
+ ),
+ 'response_format' => array(
+ 'slug' => '(string) The slug of the deleted tag',
+ 'success' => '(bool) Was the operation successful?',
+ ),
+
+ 'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/30434183/tags/slug:some-tag-name/delete',
+ 'example_request_data' => array(
+ 'headers' => array(
+ 'authorization' => 'Bearer YOUR_API_TOKEN'
+ ),
+ ),
+ 'example_response' => '{
+ "slug": "some-tag-name",
+ "success": "true"
+}'
+) );
diff --git a/plugins/jetpack/class.json-api.php b/plugins/jetpack/class.json-api.php
new file mode 100644
index 00000000..5a322eb6
--- /dev/null
+++ b/plugins/jetpack/class.json-api.php
@@ -0,0 +1,443 @@
+<?php
+
+defined( 'WPCOM_JSON_API__DEBUG' ) or define( 'WPCOM_JSON_API__DEBUG', false );
+
+class WPCOM_JSON_API {
+ static $self = null;
+
+ var $endpoints = array();
+
+ var $token_details = array();
+
+ var $method = '';
+ var $url = '';
+ var $path = '';
+ var $query = array();
+ var $post_body = null;
+ var $files = null;
+ var $content_type = null;
+ var $accept = '';
+
+ var $_server_https;
+ var $exit = true;
+ var $public_api_scheme = 'https';
+
+ var $trapped_error = null;
+
+ static function init( $method = null, $url = null, $post_body = null ) {
+ if ( !self::$self ) {
+ $class = function_exists( 'get_called_class' ) ? get_called_class() : __CLASS__;
+ self::$self = new $class( $method, $url, $post_body );
+ }
+ return self::$self;
+ }
+
+ function add( WPCOM_JSON_API_Endpoint $endpoint ) {
+ if ( !isset( $this->endpoints[$endpoint->path] ) ) {
+ $this->endpoints[$endpoint->path] = array();
+ }
+ $this->endpoints[$endpoint->path][$endpoint->method] = $endpoint;
+ }
+
+ static function is_truthy( $value ) {
+ switch ( strtolower( (string) $value ) ) {
+ case '1' :
+ case 't' :
+ case 'true' :
+ return true;
+ }
+
+ return false;
+ }
+
+ function __construct() {
+ $args = func_get_args();
+ call_user_func_array( array( $this, 'setup_inputs' ), $args );
+ }
+
+ function setup_inputs( $method = null, $url = null, $post_body = null ) {
+ if ( is_null( $method ) ) {
+ $this->method = strtoupper( $_SERVER['REQUEST_METHOD'] );
+ } else {
+ $this->method = strtoupper( $method );
+ }
+ if ( is_null( $url ) ) {
+ $this->url = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
+ } else {
+ $this->url = $url;
+ }
+
+ $parsed = parse_url( $this->url );
+ $this->path = $parsed['path'];
+
+ if ( !empty( $parsed['query'] ) ) {
+ wp_parse_str( $parsed['query'], $this->query );
+ }
+
+ if ( isset( $_SERVER['HTTP_ACCEPT'] ) && $_SERVER['HTTP_ACCEPT'] ) {
+ $this->accept = $_SERVER['HTTP_ACCEPT'];
+ }
+
+ if ( 'POST' == $this->method ) {
+ if ( is_null( $post_body ) ) {
+ $this->post_body = file_get_contents( 'php://input' );
+
+ if ( isset( $_SERVER['HTTP_CONTENT_TYPE'] ) && $_SERVER['HTTP_CONTENT_TYPE'] ) {
+ $this->content_type = $_SERVER['HTTP_CONTENT_TYPE'];
+ } elseif ( isset( $_SERVER['CONTENT_TYPE'] ) && $_SERVER['CONTENT_TYPE'] ) {
+ $this->content_type = $_SERVER['CONTENT_TYPE'] ;
+ } elseif ( '{' === $this->post_body[0] ) {
+ $this->content_type = 'application/json';
+ } else {
+ $this->content_type = 'application/x-www-form-urlencoded';
+ }
+
+ if ( 0 === strpos( strtolower( $this->content_type ), 'multipart/' ) ) {
+ $this->post_body = http_build_query( stripslashes_deep( $_POST ) );
+ $this->files = $_FILES;
+ $this->content_type = 'multipart/form-data';
+ }
+ } else {
+ $this->post_body = $post_body;
+ $this->content_type = '{' === $this->post_body[0] ? 'application/json' : 'application/x-www-form-urlencoded';
+ }
+ } else {
+ $this->post_body = null;
+ $this->content_type = null;
+ }
+
+ $this->_server_https = array_key_exists( 'HTTPS', $_SERVER ) ? $_SERVER['HTTPS'] : '--UNset--';
+ }
+
+ function initialize() {
+ $this->token_details['blog_id'] = Jetpack::get_option( 'id' );
+ }
+
+ function serve( $exit = true ) {
+ $this->exit = (bool) $exit;
+
+ add_filter( 'home_url', array( $this, 'ensure_http_scheme_of_home_url' ), 10, 3 );
+
+ add_filter( 'user_can_richedit', '__return_true' );
+
+ add_filter( 'comment_edit_pre', array( $this, 'comment_edit_pre' ) );
+
+ $this->initialize();
+
+ // Normalize path
+ $this->path = untrailingslashit( $this->path );
+ $this->path = preg_replace( '#^/rest/v1#', '', $this->path );
+
+ $allowed_methods = array( 'GET', 'POST' );
+ $four_oh_five = false;
+
+ $is_help = preg_match( '#/help/?$#i', $this->path );
+ $matching_endpoints = array();
+
+ if ( $is_help ) {
+ $this->path = substr( rtrim( $this->path, '/' ), 0, -5 );
+ // Show help for all matching endpoints regardless of method
+ $methods = $allowed_methods;
+ $find_all_matching_endpoints = true;
+ // How deep to truncate each endpoint's path to see if it matches this help request
+ $depth = substr_count( $this->path, '/' ) + 1;
+ if ( false !== stripos( $this->accept, 'javascript' ) || false !== stripos( $this->accept, 'json' ) ) {
+ $help_content_type = 'json';
+ } else {
+ $help_content_type = 'html';
+ }
+ } else {
+ if ( in_array( $this->method, $allowed_methods ) ) {
+ // Only serve requested method
+ $methods = array( $this->method );
+ $find_all_matching_endpoints = false;
+ } else {
+ // We don't allow this requested method - find matching endpoints and send 405
+ $methods = $allowed_methods;
+ $find_all_matching_endpoints = true;
+ $four_oh_five = true;
+ }
+ }
+
+ // Find which endpoint to serve
+ $found = false;
+ foreach ( $this->endpoints as $endpoint_path => $endpoints_by_method ) {
+ foreach ( $methods as $method ) {
+ if ( !isset( $endpoints_by_method[$method] ) ) {
+ continue;
+ }
+
+ // Normalize
+ $endpoint_path = untrailingslashit( $endpoint_path );
+ if ( $is_help ) {
+ // Truncate path at help depth
+ $endpoint_path = join( '/', array_slice( explode( '/', $endpoint_path ), 0, $depth ) );
+ }
+
+ // Generate regular expression from sprintf()
+ $endpoint_path_regex = str_replace( array( '%s', '%d' ), array( '([^/?&]+)', '(\d+)' ), $endpoint_path );
+
+ if ( !preg_match( "#^$endpoint_path_regex\$#", $this->path, $path_pieces ) ) {
+ // This endpoint does not match the requested path.
+ continue;
+ }
+
+ $found = true;
+
+ if ( $find_all_matching_endpoints ) {
+ $matching_endpoints[] = array( $endpoints_by_method[$method], $path_pieces );
+ } else {
+ // The method parameters are now in $path_pieces
+ $endpoint = $endpoints_by_method[$method];
+ break 2;
+ }
+ }
+ }
+
+ if ( !$found ) {
+ return $this->output( 404, '', 'text/plain' );
+ }
+
+ if ( $four_oh_five ) {
+ $allowed_methods = array();
+ foreach ( $matching_endpoints as $matching_endpoint ) {
+ $allowed_methods[] = $matching_endpoint[0]->method;
+ }
+
+ header( 'Allow: ' . strtoupper( join( ',', array_unique( $allowed_methods ) ) ) );
+ return $this->output( 405, array( 'error' => 'not_allowed', 'error_message' => 'Method not allowed' ) );
+ }
+
+ if ( $is_help ) {
+ do_action( 'wpcom_json_api_output', 'help' );
+ if ( 'json' === $help_content_type ) {
+ $docs = array();
+ foreach ( $matching_endpoints as $matching_endpoint ) {
+ if ( !$matching_endpoint[0]->in_testing || WPCOM_JSON_API__DEBUG )
+ $docs[] = call_user_func( array( $matching_endpoint[0], 'generate_documentation' ) );
+ }
+ return $this->output( 200, $docs );
+ } else {
+ status_header( 200 );
+ foreach ( $matching_endpoints as $matching_endpoint ) {
+ if ( !$matching_endpoint[0]->in_testing || WPCOM_JSON_API__DEBUG )
+ call_user_func( array( $matching_endpoint[0], 'document' ) );
+ }
+ }
+ exit;
+ }
+
+ if ( $endpoint->in_testing && !WPCOM_JSON_API__DEBUG ) {
+ return $this->output( 404, '', 'text/plain' );
+ }
+
+ do_action( 'wpcom_json_api_output', $endpoint->stat );
+
+ $response = $this->process_request( $endpoint, $path_pieces );
+
+ if ( !$response ) {
+ return $this->output( 500, '', 'text/plain' );
+ } elseif ( is_wp_error( $response ) ) {
+ $status_code = $response->get_error_data();
+ if ( !$status_code ) {
+ $status_code = 400;
+ }
+ $response = array(
+ 'error' => $response->get_error_code(),
+ 'message' => $response->get_error_message(),
+ );
+ return $this->output( $status_code, $response );
+ }
+
+ return $this->output( 200, $response );
+ }
+
+ function process_request( WPCOM_JSON_API_Endpoint $endpoint, $path_pieces ) {
+ return call_user_func_array( array( $endpoint, 'callback' ), $path_pieces );
+ }
+
+ function output( $status_code, $response = null, $content_type = 'application/json' ) {
+ if ( is_null( $response ) ) {
+ $response = new stdClass;
+ }
+
+ if ( 'text/plain' === $content_type ) {
+ status_header( (int) $status_code );
+ header( 'Content-Type: text/plain' );
+ echo $response;
+ if ( $this->exit ) {
+ exit;
+ }
+
+ return $content_type;
+ }
+
+ if ( isset( $this->query['http_envelope'] ) && self::is_truthy( $this->query['http_envelope'] ) ) {
+ $response = array(
+ 'code' => (int) $status_code,
+ 'headers' => array(
+ array(
+ 'name' => 'Content-Type',
+ 'value' => $content_type,
+ ),
+ ),
+ 'body' => $response,
+ );
+ $status_code = 200;
+ $content_type = 'application/json';
+ }
+
+ status_header( (int) $status_code );
+ header( "Content-Type: $content_type" );
+ if ( isset( $this->query['callback'] ) && is_string( $this->query['callback'] ) ) {
+ $callback = preg_replace( '/[^a-z0-9_.]/i', '', $this->query['callback'] );
+ } else {
+ $callback = false;
+ }
+
+ if ( $callback ) {
+ echo "$callback(";
+ }
+ echo $this->json_encode( $response );
+ if ( $callback ) {
+ echo ");";
+ }
+
+ if ( $this->exit ) {
+ exit;
+ }
+
+ return $content_type;
+ }
+
+ function ensure_http_scheme_of_home_url( $url, $path, $original_scheme ) {
+ if ( $original_scheme ) {
+ return $url;
+ }
+
+ return preg_replace( '#^https:#', 'http:', $url );
+ }
+
+ function comment_edit_pre( $comment_content ) {
+ return htmlspecialchars_decode( $comment_content, ENT_QUOTES );
+ }
+
+ function json_encode( $data ) {
+ return json_encode( $data );
+ }
+
+ function ends_with( $haystack, $needle ) {
+ return $needle === substr( $haystack, -strlen( $needle ) );
+ }
+
+ // Returns the site's blog_id in the WP.com ecosystem
+ function get_blog_id_for_output() {
+ return $this->token_details['blog_id'];
+ }
+
+ // Returns the site's local blog_id
+ function get_blog_id( $blog_id ) {
+ return $GLOBALS['blog_id'];
+ }
+
+ function switch_to_blog_and_validate_user( $blog_id = 0, $verify_token_for_blog = true ) {
+ if ( -1 == get_option( 'blog_public' ) && !current_user_can( 'read' ) ) {
+ return new WP_Error( 'unauthorized', 'User cannot access this private blog.', 403 );
+ }
+
+ return $blog_id;
+ }
+
+ function post_like_count( $blog_id, $post_id ) {
+ return 0;
+ }
+
+ function get_avatar_url( $email ) {
+ add_filter( 'pre_option_show_avatars', '__return_true', 999 );
+ $_SERVER['HTTPS'] = 'off';
+
+ $avatar_img_element = get_avatar( $email, 96, '' );
+
+ if ( !$avatar_img_element || is_wp_error( $avatar_img_element ) ) {
+ $return = '';
+ } elseif ( !preg_match( '#src=([\'"])?(.*?)(?(1)\\1|\s)#', $avatar_img_element, $matches ) ) {
+ $return = '';
+ } else {
+ $return = esc_url_raw( htmlspecialchars_decode( $matches[2] ) );
+ }
+
+ remove_filter( 'pre_option_show_avatars', '__return_true', 999 );
+ if ( '--UNset--' === $this->_server_https ) {
+ unset( $_SERVER['HTTPS'] );
+ } else {
+ $_SERVER['HTTPS'] = $this->_server_https;
+ }
+
+ return $return;
+ }
+
+ /**
+ * Traps `wp_die()` calls and outputs a JSON response instead.
+ * The result is always output, never returned.
+ *
+ * @param string|null $error_code. Call with string to start the trapping. Call with null to stop.
+ */
+ function trap_wp_die( $error_code = null ) {
+ // Stop trapping
+ if ( is_null( $error_code ) ) {
+ $this->trapped_error = null;
+ remove_filter( 'wp_die_handler', array( $this, 'wp_die_handler_callback' ) );
+ return;
+ }
+
+ // If API called via PHP, bail: don't do our custom wp_die(). Do the normal wp_die().
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ if ( ! defined( 'REST_API_REQUEST' ) || ! REST_API_REQUEST ) {
+ return;
+ }
+ } else {
+ if ( ! defined( 'XMLRPC_REQUEST' ) || ! XMLRPC_REQUEST ) {
+ return;
+ }
+ }
+
+ // Start trapping
+ $this->trapped_error = array(
+ 'status' => 500,
+ 'code' => $error_code,
+ 'message' => '',
+ );
+
+ add_filter( 'wp_die_handler', array( $this, 'wp_die_handler_callback' ) );
+ }
+
+ function wp_die_handler_callback() {
+ return array( $this, 'wp_die_handler' );
+ }
+
+ function wp_die_handler( $message, $title = '', $args = array() ) {
+ $args = wp_parse_args( $args, array(
+ 'response' => 500,
+ ) );
+
+ if ( $title ) {
+ $message = "$title: $message";
+ }
+
+ $this->trapped_error['status'] = $args['response'];
+ $this->trapped_error['message'] = wp_kses( $message, array() );
+
+ // We still want to exit so that code execution stops where it should.
+ // Attach the JSON output to WordPress' shutdown handler
+ add_action( 'shutdown', array( $this, 'output_trapped_error' ), 0 );
+ exit;
+ }
+
+ function output_trapped_error() {
+ $this->exit = false; // We're already exiting once. Don't do it twice.
+ $this->output( $this->trapped_error['status'], (object) array(
+ 'error' => $this->trapped_error['code'],
+ 'message' => $this->trapped_error['message'],
+ ) );
+ }
+}
diff --git a/plugins/jetpack/class.photon.php b/plugins/jetpack/class.photon.php
new file mode 100644
index 00000000..c0456885
--- /dev/null
+++ b/plugins/jetpack/class.photon.php
@@ -0,0 +1,554 @@
+<?php
+
+class Jetpack_Photon {
+ /**
+ * Class variables
+ */
+ // Oh look, a singleton
+ private static $__instance = null;
+
+ // Allowed extensions must match http://code.trac.wordpress.org/browser/photon/index.php#L31
+ protected static $extensions = array(
+ 'gif',
+ 'jpg',
+ 'jpeg',
+ 'png'
+ );
+
+ // Don't access this directly. Instead, use self::image_sizes() so it's actually populated with something.
+ protected static $image_sizes = null;
+
+ /**
+ * Singleton implementation
+ *
+ * @return object
+ */
+ public static function instance() {
+ if ( ! is_a( self::$__instance, 'Jetpack_Photon' ) ) {
+ self::$__instance = new Jetpack_Photon;
+ self::$__instance->setup();
+ }
+
+ return self::$__instance;
+ }
+
+ /**
+ * Silence is golden.
+ */
+ private function __construct() {}
+
+ /**
+ * Register actions and filters, but only if basic Photon functions are available.
+ * The basic functions are found in ./functions.photon.php.
+ *
+ * @uses add_action, add_filter
+ * @return null
+ */
+ private function setup() {
+ // Display warning if site is private
+ add_action( 'jetpack_activate_module_photon', array( $this, 'action_jetpack_activate_module_photon' ) );
+
+ if ( ! function_exists( 'jetpack_photon_url' ) )
+ return;
+
+ // Images in post content
+ add_filter( 'the_content', array( __CLASS__, 'filter_the_content' ), 999999 );
+
+ // Core image retrieval
+ add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), 10, 3 );
+
+ // og:image URL
+ add_filter( 'jetpack_open_graph_tags', array( $this, 'filter_open_graph_tags' ), 10, 2 );
+
+ // Helpers for maniuplated images
+ add_action( 'wp_enqueue_scripts', array( $this, 'action_wp_enqueue_scripts' ), 9 );
+ }
+
+ /**
+ * Check if site is private and warn user if it is
+ *
+ * @uses Jetpack::check_privacy
+ * @action jetpack_activate_module_photon
+ * @return null
+ */
+ public function action_jetpack_activate_module_photon() {
+ Jetpack::check_privacy( __FILE__ );
+ }
+
+ /**
+ ** IN-CONTENT IMAGE MANIPULATION FUNCTIONS
+ **/
+
+ /**
+ * Match all images and any relevant <a> tags in a block of HTML.
+ *
+ * @param string $content Some HTML.
+ * @return array An array of $images matches, where $images[0] is
+ * an array of full matches, and the link_url, img_tag,
+ * and img_url keys are arrays of those matches.
+ */
+ public static function parse_images_from_html( $content ) {
+ $images = array();
+
+ if ( preg_match_all( '#(?:<a[^>]+?href=["|\'](?P<link_url>[^\s]+?)["|\'][^>]*?>\s*)?(?P<img_tag><img[^>]+?src=["|\'](?P<img_url>[^\s]+?)["|\'].*?>){1}(?:\s*</a>)?#is', $content, $images ) ) {
+ foreach ( $images as $key => $unused ) {
+ // Simplify the output as much as possible, mostly for confirming test results.
+ if ( is_numeric( $key ) && $key > 0 )
+ unset( $images[$key] );
+ }
+
+ return $images;
+ }
+
+ return array();
+ }
+
+ /**
+ * Try to determine height and width from strings WP appends to resized image filenames.
+ *
+ * @param string $src The image URL.
+ * @return array An array consisting of width and height.
+ */
+ public static function parse_dimensions_from_filename( $src ) {
+ $width_height_string = array();
+
+ if ( preg_match( '#-(\d+)x(\d+)\.(?:' . implode('|', self::$extensions ) . '){1}$#i', $src, $width_height_string ) ) {
+ $width = (int) $width_height_string[1];
+ $height = (int) $width_height_string[2];
+
+ if ( $width && $height )
+ return array( $width, $height );
+ }
+
+ return array( false, false );
+ }
+
+ /**
+ * Identify images in post content, and if images are local (uploaded to the current site), pass through Photon.
+ *
+ * @param string $content
+ * @uses self::validate_image_url, apply_filters, jetpack_photon_url, esc_url
+ * @filter the_content
+ * @return string
+ */
+ public static function filter_the_content( $content ) {
+ $images = Jetpack_Photon::parse_images_from_html( $content );
+
+ if ( ! empty( $images ) ) {
+ global $content_width;
+
+ $image_sizes = self::image_sizes();
+ $upload_dir = wp_upload_dir();
+
+ foreach ( $images[0] as $index => $tag ) {
+ // Default to resize, though fit may be used in certain cases where a dimension cannot be ascertained
+ $transform = 'resize';
+
+ // Start with a clean attachment ID each time
+ $attachment_id = false;
+
+ // Flag if we need to munge a fullsize URL
+ $fullsize_url = false;
+
+ // Identify image source
+ $src = $src_orig = $images['img_url'][ $index ];
+
+ // Allow specific images to be skipped
+ if ( apply_filters( 'jetpack_photon_skip_image', false, $src, $tag ) )
+ continue;
+
+ // Support Automattic's Lazy Load plugin
+ // Can't modify $tag yet as we need unadulterated version later
+ if ( preg_match( '#data-lazy-src=["|\'](.+?)["|\']#i', $images['img_tag'][ $index ], $lazy_load_src ) ) {
+ $placeholder_src = $placeholder_src_orig = $src;
+ $src = $src_orig = $lazy_load_src[1];
+ }
+
+ // Check if image URL should be used with Photon
+ if ( self::validate_image_url( $src ) ) {
+ // Find the width and height attributes
+ $width = $height = false;
+
+ // First, check the image tag
+ if ( preg_match( '#width=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $width_string ) )
+ $width = $width_string[1];
+
+ if ( preg_match( '#height=["|\']?([\d%]+)["|\']?#i', $images['img_tag'][ $index ], $height_string ) )
+ $height = $height_string[1];
+
+ // Can't pass both a relative width and height, so unset the height in favor of not breaking the horizontal layout.
+ if ( false !== strpos( $width, '%' ) && false !== strpos( $height, '%' ) )
+ $width = $height = false;
+
+ // Detect WP registered image size from HTML class
+ if ( preg_match( '#class=["|\']?[^"\']*size-([^"\'\s]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $size ) ) {
+ $size = array_pop( $size );
+
+ if ( false === $width && false === $height && 'full' != $size && array_key_exists( $size, $image_sizes ) ) {
+ $width = (int) $image_sizes[ $size ]['width'];
+ $height = (int) $image_sizes[ $size ]['height'];
+ $transform = $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
+ }
+ } else {
+ unset( $size );
+ }
+
+ // WP Attachment ID, if uploaded to this site
+ if ( preg_match( '#class=["|\']?[^"\']*wp-image-([\d]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $attachment_id ) && ( 0 === strpos( $src, $upload_dir['baseurl'] ) || apply_filters( 'jetpack_photon_image_is_local', false, compact( 'src', 'tag', 'images', 'index' ) ) ) ) {
+ $attachment_id = intval( array_pop( $attachment_id ) );
+
+ if ( $attachment_id ) {
+ $attachment = get_post( $attachment_id );
+
+ // Basic check on returned post object
+ if ( is_object( $attachment ) && ! is_wp_error( $attachment ) && 'attachment' == $attachment->post_type ) {
+ $src_per_wp = wp_get_attachment_image_src( $attachment_id, isset( $size ) ? $size : 'full' );
+
+ if ( self::validate_image_url( $src_per_wp[0] ) ) {
+ $src = $src_per_wp[0];
+ $fullsize_url = true;
+
+ // Prevent image distortion if a detected dimension exceeds the image's natural dimensions
+ if ( ( false !== $width && $width > $src_per_wp[1] ) || ( false !== $height && $height > $src_per_wp[2] ) ) {
+ $width = false == $width ? false : min( $width, $src_per_wp[1] );
+ $height = false == $height ? false : min( $height, $src_per_wp[2] );
+ }
+
+ // If no width and height are found, max out at source image's natural dimensions
+ // Otherwise, respect registered image sizes' cropping setting
+ if ( false == $width && false == $height ) {
+ $width = $src_per_wp[1];
+ $height = $src_per_wp[2];
+ $transform = 'fit';
+ } elseif ( isset( $size ) && array_key_exists( $size, $image_sizes ) && isset( $image_sizes[ $size ]['crop'] ) ) {
+ $transform = (bool) $image_sizes[ $size ]['crop'] ? 'resize' : 'fit';
+ }
+ }
+ } else {
+ unset( $attachment_id );
+ unset( $attachment );
+ }
+ }
+ }
+
+ // If image tag lacks width and height arguments, try to determine from strings WP appends to resized image filenames.
+ if ( false === $width && false === $height ) {
+ list( $width, $height ) = Jetpack_Photon::parse_dimensions_from_filename( $src );
+ }
+
+ // If width is available, constrain to $content_width
+ if ( false !== $width && false === strpos( $width, '%' ) && is_numeric( $content_width ) ) {
+ if ( $width > $content_width && false !== $height && false === strpos( $height, '%' ) ) {
+ $height = round( ( $content_width * $height ) / $width );
+ $width = $content_width;
+ } elseif ( $width > $content_width ) {
+ $width = $content_width;
+ }
+ }
+
+ // Set a width if none is found and $content_width is available
+ // If width is set in this manner and height is available, use `fit` instead of `resize` to prevent skewing
+ if ( false === $width && is_numeric( $content_width ) ) {
+ $width = (int) $content_width;
+
+ if ( false !== $height )
+ $transform = 'fit';
+ }
+
+ // Detect if image source is for a custom-cropped thumbnail and prevent further URL manipulation.
+ if ( ! $fullsize_url && preg_match_all( '#-e[a-z0-9]+(-\d+x\d+)?\.(' . implode('|', self::$extensions ) . '){1}$#i', basename( $src ), $filename ) )
+ $fullsize_url = true;
+
+ // Build URL, first removing WP's resized string so we pass the original image to Photon
+ if ( ! $fullsize_url && preg_match( '#(-\d+x\d+)\.(' . implode('|', self::$extensions ) . '){1}$#i', $src, $src_parts ) )
+ $src = str_replace( $src_parts[1], '', $src );
+
+ // Build array of Photon args and expose to filter before passing to Photon URL function
+ $args = array();
+
+ if ( false !== $width && false !== $height && false === strpos( $width, '%' ) && false === strpos( $height, '%' ) )
+ $args[ $transform ] = $width . ',' . $height;
+ elseif ( false !== $width )
+ $args['w'] = $width;
+ elseif ( false !== $height )
+ $args['h'] = $height;
+
+ $args = apply_filters( 'jetpack_photon_post_image_args', $args, compact( 'tag', 'src', 'src_orig', 'width', 'height' ) );
+
+ $photon_url = jetpack_photon_url( $src, $args );
+
+ // Modify image tag if Photon function provides a URL
+ // Ensure changes are only applied to the current image by copying and modifying the matched tag, then replacing the entire tag with our modified version.
+ if ( $src != $photon_url ) {
+ $new_tag = $tag;
+
+ // If present, replace the link href with a Photoned URL for the full-size image.
+ if ( ! empty( $images['link_url'][ $index ] ) && self::validate_image_url( $images['link_url'][ $index ] ) )
+ $new_tag = preg_replace( '#(href=["|\'])' . $images['link_url'][ $index ] . '(["|\'])#i', '\1' . jetpack_photon_url( $images['link_url'][ $index ] ) . '\2', $new_tag, 1 );
+
+ // Supplant the original source value with our Photon URL
+ $photon_url = esc_url( $photon_url );
+ $new_tag = str_replace( $src_orig, $photon_url, $new_tag );
+
+ // If Lazy Load is in use, pass placeholder image through Photon
+ if ( isset( $placeholder_src ) && self::validate_image_url( $placeholder_src ) ) {
+ $placeholder_src = jetpack_photon_url( $placeholder_src );
+
+ if ( $placeholder_src != $placeholder_src_orig )
+ $new_tag = str_replace( $placeholder_src_orig, esc_url( $placeholder_src ), $new_tag );
+
+ unset( $placeholder_src );
+ }
+
+ // Remove the width and height arguments from the tag to prevent distortion
+ $new_tag = preg_replace( '#(width|height)=["|\']?[\d%]+["|\']?\s?#i', '', $new_tag );
+
+ // Tag an image for dimension checking
+ $new_tag = preg_replace( '#(\s?/)?>(</a>)?$#i', ' data-recalc-dims="1"\1>\2', $new_tag );
+
+ // Replace original tag with modified version
+ $content = str_replace( $tag, $new_tag, $content );
+ }
+ }
+ }
+ }
+
+ return $content;
+ }
+
+ /**
+ ** CORE IMAGE RETRIEVAL
+ **/
+
+ /**
+ * Filter post thumbnail image retrieval, passing images through Photon
+ *
+ * @param string|bool $image
+ * @param int $attachment_id
+ * @param string|array $size
+ * @uses is_admin, apply_filters, wp_get_attachment_url, self::validate_image_url, this::image_sizes, jetpack_photon_url
+ * @filter image_downsize
+ * @return string|bool
+ */
+ public function filter_image_downsize( $image, $attachment_id, $size ) {
+ // Don't foul up the admin side of things, and provide plugins a way of preventing Photon from being applied to images.
+ if ( is_admin() || apply_filters( 'jetpack_photon_override_image_downsize', false, compact( 'image', 'attachment_id', 'size' ) ) )
+ return $image;
+
+ // Get the image URL and proceed with Photon-ification if successful
+ $image_url = wp_get_attachment_url( $attachment_id );
+
+ if ( $image_url ) {
+ // Check if image URL should be used with Photon
+ if ( ! self::validate_image_url( $image_url ) )
+ return $image;
+
+ // If an image is requested with a size known to WordPress, use that size's settings with Photon
+ if ( ( is_string( $size ) || is_int( $size ) ) && array_key_exists( $size, self::image_sizes() ) ) {
+ $image_args = self::image_sizes();
+ $image_args = $image_args[ $size ];
+
+ $photon_args = array();
+
+ // `full` is a special case in WP
+ // To ensure filter receives consistent data regardless of requested size, `$image_args` is overridden with dimensions of original image.
+ if ( 'full' == $size ) {
+ $image_meta = wp_get_attachment_metadata( $attachment_id );
+
+ // 'crop' is true so Photon's `resize` method is used
+ $image_args = array(
+ 'width' => $image_meta['width'],
+ 'height' => $image_meta['height'],
+ 'crop' => true
+ );
+ }
+
+ // Expose determined arguments to a filter before passing to Photon
+ $transform = $image_args['crop'] ? 'resize' : 'fit';
+
+ // Check specified image dimensions and account for possible zero values; photon fails to resize if a dimension is zero.
+ if ( 0 == $image_args['width'] || 0 == $image_args['height'] ) {
+ if ( 0 == $image_args['width'] && 0 < $image_args['height'] )
+ $photon_args['h'] = $image_args['height'];
+ elseif ( 0 == $image_args['height'] && 0 < $image_args['width'] )
+ $photon_args['w'] = $image_args['width'];
+ } else {
+ $photon_args[ $transform ] = $image_args['width'] . ',' . $image_args['height'];
+ }
+
+ $photon_args = apply_filters( 'jetpack_photon_image_downsize_string', $photon_args, compact( 'image_args', 'image_url', 'attachment_id', 'size', 'transform' ) );
+
+ // Generate Photon URL
+ $image = array(
+ jetpack_photon_url( $image_url, $photon_args ),
+ false,
+ false
+ );
+ } elseif ( is_array( $size ) ) {
+ // Pull width and height values from the provided array, if possible
+ $width = isset( $size[0] ) ? (int) $size[0] : false;
+ $height = isset( $size[1] ) ? (int) $size[1] : false;
+
+ // Don't bother if necessary parameters aren't passed.
+ if ( ! $width || ! $height )
+ return $image;
+
+ // Expose arguments to a filter before passing to Photon
+ $photon_args = array(
+ 'fit' => $width . ',' . $height
+ );
+
+ $photon_args = apply_filters( 'jetpack_photon_image_downsize_array', $photon_args, compact( 'width', 'height', 'image_url', 'attachment_id' ) );
+
+ // Generate Photon URL
+ $image = array(
+ jetpack_photon_url( $image_url, $photon_args ),
+ false,
+ false
+ );
+ }
+ }
+
+ return $image;
+ }
+
+ /**
+ ** GENERAL FUNCTIONS
+ **/
+
+ /**
+ * Ensure image URL is valid for Photon.
+ * Though Photon functions address some of the URL issues, we should avoid unnecessary processing if we know early on that the image isn't supported.
+ *
+ * @param string $url
+ * @uses wp_parse_args
+ * @return bool
+ */
+ protected static function validate_image_url( $url ) {
+ $parsed_url = @parse_url( $url );
+
+ if ( ! $parsed_url )
+ return false;
+
+ // Parse URL and ensure needed keys exist, since the array returned by `parse_url` only includes the URL components it finds.
+ $url_info = wp_parse_args( $parsed_url, array(
+ 'scheme' => null,
+ 'host' => null,
+ 'port' => null,
+ 'path' => null
+ ) );
+
+ // Bail if scheme isn't http or port is set that isn't port 80
+ if ( 'http' != $url_info['scheme'] || ! in_array( $url_info['port'], array( 80, null ) ) )
+ return false;
+
+ // Bail if no host is found
+ if ( is_null( $url_info['host'] ) )
+ return false;
+
+ // Bail if the image alredy went through Photon
+ if ( preg_match( '#^i[\d]{1}.wp.com$#i', $url_info['host'] ) )
+ return false;
+
+ // Bail if no path is found
+ if ( is_null( $url_info['path'] ) )
+ return false;
+
+ // Ensure image extension is acceptable
+ if ( ! in_array( strtolower( pathinfo( $url_info['path'], PATHINFO_EXTENSION ) ), self::$extensions ) )
+ return false;
+
+ // If we got this far, we should have an acceptable image URL
+ return true;
+ }
+
+ /**
+ * Provide an array of available image sizes and corresponding dimensions.
+ * Similar to get_intermediate_image_sizes() except that it includes image sizes' dimensions, not just their names.
+ *
+ * @global $wp_additional_image_sizes
+ * @uses get_option
+ * @return array
+ */
+ protected static function image_sizes() {
+ if ( null == self::$image_sizes ) {
+ global $_wp_additional_image_sizes;
+
+ // Populate an array matching the data structure of $_wp_additional_image_sizes so we have a consistent structure for image sizes
+ $images = array(
+ 'thumb' => array(
+ 'width' => intval( get_option( 'thumbnail_size_w' ) ),
+ 'height' => intval( get_option( 'thumbnail_size_h' ) ),
+ 'crop' => (bool) get_option( 'thumbnail_crop' )
+ ),
+ 'medium' => array(
+ 'width' => intval( get_option( 'medium_size_w' ) ),
+ 'height' => intval( get_option( 'medium_size_h' ) ),
+ 'crop' => false
+ ),
+ 'large' => array(
+ 'width' => intval( get_option( 'large_size_w' ) ),
+ 'height' => intval( get_option( 'large_size_h' ) ),
+ 'crop' => false
+ ),
+ 'full' => array(
+ 'width' => null,
+ 'height' => null,
+ 'crop' => false
+ )
+ );
+
+ // Compatibility mapping as found in wp-includes/media.php
+ $images['thumbnail'] = $images['thumb'];
+
+ // Update class variable, merging in $_wp_additional_image_sizes if any are set
+ if ( is_array( $_wp_additional_image_sizes ) && ! empty( $_wp_additional_image_sizes ) )
+ self::$image_sizes = array_merge( $images, $_wp_additional_image_sizes );
+ else
+ self::$image_sizes = $images;
+ }
+
+ return is_array( self::$image_sizes ) ? self::$image_sizes : array();
+ }
+
+ /**
+ * Pass og:image URLs through Photon
+ *
+ * @param array $tags
+ * @param array $parameters
+ * @uses jetpack_photon_url
+ * @return array
+ */
+ function filter_open_graph_tags( $tags, $parameters ) {
+ if ( empty( $tags['og:image'] ) ) {
+ return $tags;
+ }
+
+ $photon_args = array(
+ 'fit' => sprintf( '%d,%d', 2 * $parameters['image_width'], 2 * $parameters['image_height'] ),
+ );
+
+ if ( is_array( $tags['og:image'] ) ) {
+ $images = array();
+ foreach ( $tags['og:image'] as $image ) {
+ $images[] = jetpack_photon_url( $image, $photon_args );
+ }
+ $tags['og:image'] = $images;
+ } else {
+ $tags['og:image'] = jetpack_photon_url( $tags['og:image'], $photon_args );
+ }
+
+ return $tags;
+ }
+
+ /**
+ * Enqueue Photon helper script
+ *
+ * @uses wp_enqueue_script, plugins_url
+ * @action wp_enqueue_script
+ * @return null
+ */
+ public function action_wp_enqueue_scripts() {
+ wp_enqueue_script( 'jetpack-photon', plugins_url( 'modules/photon/photon.js', __FILE__ ), array( 'jquery' ), 20130122, true );
+ }
+}
diff --git a/plugins/jetpack/functions.compat.php b/plugins/jetpack/functions.compat.php
new file mode 100644
index 00000000..5e776c07
--- /dev/null
+++ b/plugins/jetpack/functions.compat.php
@@ -0,0 +1,15 @@
+<?php
+
+if ( !function_exists( 'rawurlencode_deep' ) ) :
+/**
+ * Navigates through an array and raw encodes the values to be used in a URL.
+ *
+ * @since WordPress 3.4.0
+ *
+ * @param array|string $value The array or string to be encoded.
+ * @return array|string $value The encoded array (or string from the callback).
+ */
+function rawurlencode_deep( $value ) {
+ return is_array( $value ) ? array_map( 'rawurlencode_deep', $value ) : rawurlencode( $value );
+}
+endif;
diff --git a/plugins/jetpack/functions.gallery.php b/plugins/jetpack/functions.gallery.php
new file mode 100644
index 00000000..9a9e71b5
--- /dev/null
+++ b/plugins/jetpack/functions.gallery.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * Renders extra controls in the Gallery Settings section of the new media UI.
+ */
+class Jetpack_Gallery_Settings {
+ function __construct() {
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
+ }
+
+ function admin_init() {
+ $this->gallery_types = apply_filters( 'jetpack_gallery_types', array() );
+
+ // Enqueue the media UI only if needed.
+ if ( ! empty( $this->gallery_types ) ) {
+ add_action( 'wp_enqueue_media', array( $this, 'wp_enqueue_media' ) );
+ add_action( 'print_media_templates', array( $this, 'print_media_templates' ) );
+ }
+ }
+
+ /**
+ * Registers/enqueues the gallery settings admin js.
+ */
+ function wp_enqueue_media() {
+ if ( ! wp_script_is( 'jetpack-gallery-settings', 'registered' ) )
+ wp_register_script( 'jetpack-gallery-settings', plugins_url( 'gallery-settings/gallery-settings.js', __FILE__ ), array( 'media-views' ), '20121225' );
+
+ wp_enqueue_script( 'jetpack-gallery-settings' );
+ }
+
+ /**
+ * Outputs a view template which can be used with wp.media.template
+ */
+ function print_media_templates() {
+ ?>
+ <script type="text/html" id="tmpl-jetpack-gallery-settings">
+ <label class="setting">
+ <span><?php _e( 'Type', 'jetpack' ); ?></span>
+ <select class="type" name="type" data-setting="type">
+ <option value="default" <?php selected( true ); ?>><?php _e( 'Default', 'jetpack' ); ?></option>
+ <?php foreach ( $this->gallery_types as $value => $caption ) : ?>
+ <option value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $caption ); ?></option>
+ <?php endforeach; ?>
+ </select>
+ </label>
+ </script>
+ <?php
+ }
+}
+new Jetpack_Gallery_Settings;
diff --git a/plugins/jetpack/functions.opengraph.php b/plugins/jetpack/functions.opengraph.php
new file mode 100644
index 00000000..542d01f1
--- /dev/null
+++ b/plugins/jetpack/functions.opengraph.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * Open Graph Tags
+ *
+ * Add Open Graph tags so that Facebook (and any other service that supports them)
+ * can crawl the site better and we provide a better sharing experience.
+ *
+ * @link http://ogp.me/
+ * @link http://developers.facebook.com/docs/opengraph/
+ */
+add_action( 'wp_head', 'jetpack_og_tags' );
+
+function jetpack_og_tags() {
+ if ( false === apply_filters( 'jetpack_enable_opengraph', true ) ) {
+ _deprecated_function( 'jetpack_enable_opengraph', '2.0.3', 'jetpack_enable_open_graph' );
+ return;
+ }
+
+ // Disable the widont filter on WP.com to avoid stray &nbsps
+ $disable_widont = remove_filter( 'the_title', 'widont' );
+
+ $og_output = "\n<!-- Jetpack Open Graph Tags -->\n";
+ $tags = array();
+
+ $image_width = absint( apply_filters( 'jetpack_open_graph_image_width', 200 ) );
+ $image_height = absint( apply_filters( 'jetpack_open_graph_image_height', 200 ) );
+ $description_length = 197;
+
+ if ( is_home() || is_front_page() ) {
+ $site_type = get_option( 'open_graph_protocol_site_type' );
+ $tags['og:type'] = ! empty( $site_type ) ? $site_type : 'blog';
+ $tags['og:title'] = get_bloginfo( 'name' );
+ $tags['og:description'] = get_bloginfo( 'description' );
+
+ $front_page_id = get_option( 'page_for_posts' );
+ if ( $front_page_id && is_home() )
+ $tags['og:url'] = get_permalink( $front_page_id );
+ else
+ $tags['og:url'] = home_url( '/' );
+
+ // Associate a blog's root path with one or more Facebook accounts
+ $facebook_admins = get_option( 'facebook_admins' );
+ if ( ! empty( $facebook_admins ) )
+ $tags['fb:admins'] = $facebook_admins;
+
+ } else if ( is_author() ) {
+ $tags['og:type'] = 'author';
+
+ $author = get_queried_object();
+
+ $tags['og:title'] = $author->display_name;
+ $tags['og:url'] = get_author_posts_url( $author->ID );
+ $tags['og:description'] = $author->description;
+
+ } else if ( is_singular() ) {
+ global $post;
+ $data = $post; // so that we don't accidentally explode the global
+
+ $tags['og:type'] = 'article';
+ $tags['og:title'] = empty( $data->post_title ) ? ' ' : wp_kses( $data->post_title, array() ) ;
+ $tags['og:url'] = get_permalink( $data->ID );
+ if ( !post_password_required() )
+ $tags['og:description'] = ! empty( $data->post_excerpt ) ? strip_shortcodes( wp_kses( $data->post_excerpt, array() ) ) : wp_trim_words( strip_shortcodes( wp_kses( $data->post_content, array() ) ) );
+ $tags['og:description'] = empty( $tags['og:description'] ) ? ' ' : $tags['og:description'];
+ }
+
+ // Re-enable widont if we had disabled it
+ if ( $disable_widont )
+ add_filter( 'the_title', 'widont' );
+
+ if ( empty( $tags ) )
+ return;
+
+ $tags['og:site_name'] = get_bloginfo( 'name' );
+ $tags['og:image'] = jetpack_og_get_image( $image_width, $image_height );
+
+ // Facebook whines if you give it an empty title
+ if ( empty( $tags['og:title'] ) )
+ $tags['og:title'] = __( '(no title)', 'jetpack' );
+
+ // Shorten the description if it's too long
+ $tags['og:description'] = strlen( $tags['og:description'] ) > $description_length ? mb_substr( $tags['og:description'], 0, $description_length ) . '...' : $tags['og:description'];
+
+ // Add any additional tags here, or modify what we've come up with
+ $tags = apply_filters( 'jetpack_open_graph_tags', $tags, compact( 'image_width', 'image_height' ) );
+
+ foreach ( (array) $tags as $tag_property => $tag_content ) {
+ // to accomodate multiple images
+ $tag_content = (array) $tag_content;
+ $tag_content = array_unique( $tag_content );
+
+ foreach ( $tag_content as $tag_content_single ) {
+ if ( empty( $tag_content_single ) )
+ continue; // Don't ever output empty tags
+ $og_tag = sprintf( '<meta property="%s" content="%s" />', esc_attr( $tag_property ), esc_attr( $tag_content_single ) );
+ $og_output .= apply_filters( 'jetpack_open_graph_output', $og_tag );
+ $og_output .= "\n";
+ }
+ }
+
+ echo $og_output;
+}
+
+function jetpack_og_get_image( $width = 50, $height = 50, $max_images = 4 ) { // Facebook requires thumbnails to be a minimum of 50x50
+ $image = '';
+
+ if ( is_singular() && !is_home() && !is_front_page() ) {
+ global $post;
+ $image = '';
+
+ // Attempt to find something good for this post using our generalized PostImages code
+ if ( class_exists( 'Jetpack_PostImages' ) ) {
+ $post_images = Jetpack_PostImages::get_images( $post->ID, array( 'width' => $width, 'height' => $height ) );
+ if ( $post_images && !is_wp_error( $post_images ) ) {
+ $image = array();
+ foreach ( (array) $post_images as $post_image ) {
+ $image[] = $post_image['src'];
+ }
+ }
+ }
+ } else if ( is_author() ) {
+ $author = get_queried_object();
+ if ( function_exists( 'get_avatar_url' ) ) {
+ $avatar = get_avatar_url( $author->user_email, $width );
+
+ if ( ! empty( $avatar ) ) {
+ if ( is_array( $avatar ) )
+ $image = $avatar[0];
+ else
+ $image = $avatar;
+ }
+ }
+ else {
+ $has_filter = has_filter( 'pre_option_show_avatars', '__return_true' );
+ if ( !$has_filter ) {
+ add_filter( 'pre_option_show_avatars', '__return_true' );
+ }
+ $avatar = get_avatar( $author->user_email, $width );
+ if ( !$has_filter ) {
+ remove_filter( 'pre_option_show_avatars', '__return_true' );
+ }
+
+ if ( !empty( $avatar ) && !is_wp_error( $avatar ) ) {
+ if ( preg_match( '/src=["\']([^"\']+)["\']/', $avatar, $matches ) );
+ $image = wp_specialchars_decode( $matches[1], ENT_QUOTES );
+ }
+ }
+ }
+
+ // Fallback to Blavatar if available
+ if ( function_exists( 'blavatar_domain' ) ) {
+ $blavatar_domain = blavatar_domain( site_url() );
+ if ( empty( $image ) && blavatar_exists( $blavatar_domain ) )
+ $image = blavatar_url( $blavatar_domain, 'img', $width );
+ }
+
+ return $image;
+}
diff --git a/plugins/jetpack/functions.photon.php b/plugins/jetpack/functions.photon.php
new file mode 100644
index 00000000..fc276b31
--- /dev/null
+++ b/plugins/jetpack/functions.photon.php
@@ -0,0 +1,160 @@
+<?php
+
+/**
+ * Generates a Photon URL.
+ *
+ * @see http://developer.wordpress.com/docs/photon/
+ *
+ * @param string $image_url URL to the publicly accessible image you want to manipulate
+ * @param array|string $args An array of arguments, i.e. array( 'w' => '300', 'resize' => array( 123, 456 ) ), or in string form (w=123&h=456)
+ * @return string The raw final URL. You should run this through esc_url() before displaying it.
+ */
+function jetpack_photon_url( $image_url, $args = array(), $scheme = null ) {
+ $image_url = trim( $image_url );
+
+ $image_url = apply_filters( 'jetpack_photon_pre_image_url', $image_url, $args, $scheme );
+ $args = apply_filters( 'jetpack_photon_pre_args', $args, $image_url, $scheme );
+
+ if ( empty( $image_url ) )
+ return $image_url;
+
+ $image_url_parts = @parse_url( $image_url );
+
+ // Unable to parse
+ if ( ! is_array( $image_url_parts ) || empty( $image_url_parts['host'] ) || empty( $image_url_parts['path'] ) )
+ return $image_url;
+
+ if ( is_array( $args ) ){
+ // Convert values that are arrays into strings
+ foreach ( $args as $arg => $value ) {
+ if ( is_array( $value ) ) {
+ $args[$arg] = implode( ',', $value );
+ }
+ }
+
+ // Encode values
+ // See http://core.trac.wordpress.org/ticket/17923
+ $args = rawurlencode_deep( $args );
+ }
+
+ // You can't run a Photon URL through Photon again because query strings are stripped.
+ // So if the image is already a Photon URL, append the new arguments to the existing URL.
+ if ( in_array( $image_url_parts['host'], array( 'i0.wp.com', 'i1.wp.com', 'i2.wp.com' ) ) ) {
+ $photon_url = add_query_arg( $args, $image_url );
+
+ return jetpack_photon_url_scheme( $photon_url, $scheme );
+ }
+
+ // This setting is Photon Server dependent
+ if ( ! apply_filters( 'jetpack_photon_any_extension_for_domain', false, $image_url_parts['host'] ) ) {
+ // Photon doesn't support query strings so we ignore them and look only at the path.
+ // However some source images are served via PHP so check the no-query-string extension.
+ // For future proofing, this is a blacklist of common issues rather than a whitelist.
+ $extension = pathinfo( $image_url_parts['path'], PATHINFO_EXTENSION );
+ if ( empty( $extension ) || in_array( $extension, array( 'php' ) ) )
+ return $image_url;
+ }
+
+ $image_host_path = $image_url_parts['host'] . $image_url_parts['path'];
+
+ // Figure out which CDN subdomain to use
+ srand( crc32( $image_host_path ) );
+ $subdomain = rand( 0, 2 );
+ srand();
+
+ $photon_url = "http://i{$subdomain}.wp.com/$image_host_path";
+
+ // This setting is Photon Server dependent
+ if ( isset( $image_url_parts['query'] ) && apply_filters( 'jetpack_photon_add_query_string_to_domain', false, $image_url_parts['host'] ) ) {
+ $photon_url .= '?q=' . rawurlencode( $image_url_parts['query'] );
+ }
+
+ if ( $args ) {
+ if ( is_array( $args ) ) {
+ $photon_url = add_query_arg( $args, $photon_url );
+ } else {
+ // You can pass a query string for complicated requests but where you still want CDN subdomain help, etc.
+ $photon_url .= '?' . $args;
+ }
+ }
+
+ return jetpack_photon_url_scheme( $photon_url, $scheme );
+}
+
+
+/**
+ * WordPress.com
+ *
+ * If a cropped WP.com-hosted image is the source image, have Photon replicate the crop.
+ */
+add_filter( 'jetpack_photon_pre_args', 'jetpack_photon_parse_wpcom_query_args', 10, 2 );
+
+function jetpack_photon_parse_wpcom_query_args( $args, $image_url ) {
+ $parsed_url = @parse_url( $image_url );
+
+ if ( ! $parsed_url )
+ return $args;
+
+ $image_url_parts = wp_parse_args( $parsed_url, array(
+ 'host' => '',
+ 'query' => ''
+ ) );
+
+ if ( '.files.wordpress.com' != substr( $image_url_parts['host'], -20 ) )
+ return $args;
+
+ if ( empty( $image_url_parts['query'] ) )
+ return $args;
+
+ $wpcom_args = wp_parse_args( $image_url_parts['query'] );
+
+ if ( empty( $wpcom_args['w'] ) || empty( $wpcom_args['h'] ) )
+ return $args;
+
+ // Keep the crop by using "resize"
+ if ( ! empty( $wpcom_args['crop'] ) ) {
+ if ( is_array( $args ) ) {
+ $args = array_merge( array( 'resize' => array( $wpcom_args['w'], $wpcom_args['h'] ) ), $args );
+ } else {
+ $args = 'resize=' . rawurlencode( absint( $wpcom_args['w'] ) . ',' . absint( $wpcom_args['h'] ) ) . '&' . $args;
+ }
+ } else {
+ if ( is_array( $args ) ) {
+ $args = array_merge( array( 'fit' => array( $wpcom_args['w'], $wpcom_args['h'] ) ), $args );
+ } else {
+ $args = 'fit=' . rawurlencode( absint( $wpcom_args['w'] ) . ',' . absint( $wpcom_args['h'] ) ) . '&' . $args;
+ }
+ }
+
+ return $args;
+}
+
+
+/**
+ * Facebook
+ */
+add_filter( 'jetpack_photon_add_query_string_to_domain', 'jetpack_photon_allow_facebook_graph_domain', 10, 2 );
+add_filter( 'jetpack_photon_any_extension_for_domain', 'jetpack_photon_allow_facebook_graph_domain', 10, 2 );
+
+function jetpack_photon_url_scheme( $url, $scheme ) {
+ if ( ! in_array( $scheme, array( 'http', 'https', 'network_path' ) ) ) {
+ $scheme = is_ssl() ? 'https' : 'http';
+ }
+
+ if ( 'network_path' == $scheme ) {
+ $scheme_slashes = '//';
+ } else {
+ $scheme_slashes = "$scheme://";
+ }
+
+ return preg_replace( '#^[a-z:]+//#i', $scheme_slashes, $url );
+}
+
+function jetpack_photon_allow_facebook_graph_domain( $allow = false, $domain ) {
+ switch ( $domain ) {
+ case 'graph.facebook.com' :
+ return true;
+ }
+
+ return $allow;
+} \ No newline at end of file
diff --git a/plugins/jetpack/jetpack.php b/plugins/jetpack/jetpack.php
index 68d7aaed..80b6a3ce 100644
--- a/plugins/jetpack/jetpack.php
+++ b/plugins/jetpack/jetpack.php
@@ -5,7 +5,7 @@
* Plugin URI: http://wordpress.org/extend/plugins/jetpack/
* 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.
* Author: Automattic
- * Version: 1.6.1
+ * Version: 2.2
* Author URI: http://jetpack.me
* License: GPL2+
* Text Domain: jetpack
@@ -14,11 +14,15 @@
defined( 'JETPACK__API_BASE' ) or define( 'JETPACK__API_BASE', 'https://jetpack.wordpress.com/jetpack.' );
define( 'JETPACK__API_VERSION', 1 );
-define( 'JETPACK__MINIMUM_WP_VERSION', '3.2' );
+define( 'JETPACK__MINIMUM_WP_VERSION', '3.3' );
defined( 'JETPACK_CLIENT__AUTH_LOCATION' ) or define( 'JETPACK_CLIENT__AUTH_LOCATION', 'header' );
defined( 'JETPACK_CLIENT__HTTPS' ) or define( 'JETPACK_CLIENT__HTTPS', 'AUTO' );
-define( 'JETPACK__VERSION', '1.6.1' );
+define( 'JETPACK__VERSION', '2.2' );
define( 'JETPACK__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
+defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) or define( 'JETPACK__GLOTPRESS_LOCALES_PATH', JETPACK__PLUGIN_DIR . 'locales.php' );
+
+define( 'JETPACK_MASTER_USER', true );
+
/*
Options:
jetpack_options (array)
@@ -53,13 +57,15 @@ class Jetpack {
'twitter-widget' => array( 'wickett-twitter-widget/wickett-twitter-widget.php', 'Wickett Twitter Widget' ),
'after-the-deadline' => array( 'after-the-deadline/after-the-deadline.php', 'After The Deadline' ),
'contact-form' => array( 'grunion-contact-form/grunion-contact-form.php', 'Grunion Contact Form' ),
+ 'custom-css' => array( 'safecss/safecss.php', 'WordPress.com Custom CSS' ),
);
var $capability_translations = array(
'administrator' => 'manage_options',
-// 'editor' => 'edit_others_posts',
-// 'author' => 'publish_posts',
-// 'contributor' => 'edit_posts',
+ 'editor' => 'edit_others_posts',
+ 'author' => 'publish_posts',
+ 'contributor' => 'edit_posts',
+ 'subscriber' => 'read',
);
/**
@@ -75,6 +81,12 @@ class Jetpack {
var $error = '';
/**
+ * Modules that need more privacy description.
+ * @var string
+ */
+ var $privacy_checks = '';
+
+ /**
* Stats to record once the page loads
*
* @var array
@@ -87,10 +99,15 @@ class Jetpack {
var $sync;
/**
+ * Verified data for JSON authorization request
+ */
+ var $json_api_authorization_request = array();
+
+ /**
* Singleton
* @static
*/
- function init() {
+ public static function init() {
static $instance = false;
if ( !$instance ) {
@@ -132,7 +149,21 @@ class Jetpack {
}
}
- // Future: switch on version? If so, think twice before updating version/old_version.
+ // Upgrade from a single user token to a user_id-indexed array and a master_user ID
+ if ( !Jetpack::get_option( 'user_tokens' ) ) {
+ if ( $user_token = Jetpack::get_option( 'user_token' ) ) {
+ $token_parts = explode( '.', $user_token );
+ if ( isset( $token_parts[2] ) ) {
+ $master_user = $token_parts[2];
+ $user_tokens = array( $master_user => $user_token );
+ Jetpack::update_options( compact( 'master_user', 'user_tokens' ) );
+ Jetpack::delete_option( 'user_token' );
+ } else {
+ // @todo: is this even possible?
+ trigger_error( sprintf( 'Jetpack::plugin_upgrade found no user_id in user_token "%s"', $user_token ), E_USER_WARNING );
+ }
+ }
+ }
}
/**
@@ -141,19 +172,25 @@ class Jetpack {
function Jetpack() {
$this->sync = new Jetpack_Sync;
+ // Modules should do Jetpack_Sync::sync_options( __FILE__, $option, ... ); instead
+ // We access the "internal" method here only because the Jetpack object isn't instantiated yet
+ $this->sync->options( __FILE__,
+ 'home',
+ 'siteurl',
+ 'blogname',
+ 'gmt_offset',
+ 'timezone_string'
+ );
+
if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && isset( $_GET['for'] ) && 'jetpack' == $_GET['for'] ) {
@ini_set( 'display_errors', false ); // Display errors can cause the XML to be not well formed.
require_once dirname( __FILE__ ) . '/class.jetpack-xmlrpc-server.php';
$this->xmlrpc_server = new Jetpack_XMLRPC_Server();
- // Don't let anyone authenticate
- remove_all_filters( 'authenticate' );
-
- if ( $this->is_active() ) {
- // Allow Jetpack authentication
- add_filter( 'authenticate', array( $this, 'authenticate_xml_rpc' ), 10, 3 );
+ $this->require_jetpack_authentication();
+ if ( Jetpack::is_active() ) {
// Hack to preserve $HTTP_RAW_POST_DATA
add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
@@ -166,9 +203,21 @@ class Jetpack {
// Now that no one can authenticate, and we're whitelisting all XML-RPC methods, force enable_xmlrpc on.
add_filter( 'pre_option_enable_xmlrpc', '__return_true' );
+ } elseif ( is_admin() && isset( $_POST['action'] ) && 'jetpack_upload_file' == $_POST['action'] ) {
+ $this->require_jetpack_authentication();
+ $this->add_remote_request_handlers();
+ } else {
+ if ( Jetpack::is_active() ) {
+ add_action( 'login_form_jetpack_json_api_authorization', array( &$this, 'login_form_json_api_authorization' ) );
+ }
+ }
+
+ add_action( 'jetpack_clean_nonces', array( 'Jetpack', 'clean_nonces' ) );
+ if ( !wp_next_scheduled( 'jetpack_clean_nonces' ) ) {
+ wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
}
- add_action( 'jetpack_clean_nonces', array( $this, 'clean_nonces' ) );
+ add_filter( 'xmlrpc_blog_options', array( $this, 'xmlrpc_options' ) );
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
add_action( 'admin_init', array( $this, 'admin_init' ) );
@@ -177,9 +226,43 @@ class Jetpack {
add_action( 'wp_ajax_jetpack-check-news-subscription', array( $this, 'check_news_subscription' ) );
add_action( 'wp_ajax_jetpack-subscribe-to-news', array( $this, 'subscribe_to_news' ) );
+ add_action( 'wp_loaded', array( $this, 'register_assets' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'devicepx' ) );
add_action( 'customize_controls_enqueue_scripts', array( $this, 'devicepx' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'devicepx' ) );
+
+ add_action( 'jetpack_activate_module', array( $this, 'activate_module_actions' ) );
+
+ add_action( 'plugins_loaded', array( $this, 'check_open_graph' ), 999 );
+ }
+
+ function require_jetpack_authentication() {
+ // Don't let anyone authenticate
+ $_COOKIE = array();
+ remove_all_filters( 'authenticate' );
+
+ if ( Jetpack::is_active() ) {
+ // Allow Jetpack authentication
+ add_filter( 'authenticate', array( $this, 'authenticate_jetpack' ), 10, 3 );
+ }
+ }
+
+ /**
+ * Register assets for use in various modules and the Jetpack admin page.
+ *
+ * @uses wp_script_is, wp_register_script, plugins_url
+ * @action wp_loaded
+ * @return null
+ */
+ public function register_assets() {
+ if ( ! wp_script_is( 'spin', 'registered' ) )
+ wp_register_script( 'spin', plugins_url( '_inc/spin.js', __FILE__ ), false, '1.2.4' );
+
+ if ( ! wp_script_is( 'jquery.spin', 'registered' ) )
+ wp_register_script( 'jquery.spin', plugins_url( '_inc/jquery.spin.js', __FILE__ ) , array( 'jquery', 'spin' ) );
+
+ if ( ! wp_script_is( 'jetpack-gallery-settings', 'registered' ) )
+ wp_register_script( 'jetpack-gallery-settings', plugins_url( '_inc/gallery-settings.js', __FILE__ ), array( 'media-views' ), '20121225' );
}
/**
@@ -193,19 +276,77 @@ class Jetpack {
/**
* Is Jetpack active?
*/
- function is_active() {
- return (bool) Jetpack_Data::get_access_token( 1 ); // 1 just means user token
+ public static function is_active() {
+ return (bool) Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
+ }
+
+ /**
+ * Is a given user (or the current user if none is specified) linked to a WordPress.com user?
+ */
+ public static function is_user_connected( $user_id = false ) {
+ $user_id = false === $user_id ? get_current_user_id() : absint( $user_id );
+ if ( !$user_id ) {
+ return false;
+ }
+ return (bool) Jetpack_Data::get_access_token( $user_id );
}
function current_user_is_connection_owner() {
- $user_token = Jetpack_Data::get_access_token( 1 );
+ $user_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
return $user_token && is_object( $user_token ) && isset( $user_token->external_user_id ) && get_current_user_id() === $user_token->external_user_id;
}
/**
+ * Synchronize connected user role changes
+ */
+ function user_role_change( $user_id ) {
+ if ( Jetpack::is_active() && Jetpack::is_user_connected( $user_id ) ) {
+
+ $current_user_id = get_current_user_id();
+ wp_set_current_user( $user_id );
+ $role = $this->translate_current_user_to_role();
+ $signed_role = $this->sign_role( $role );
+ wp_set_current_user( $current_user_id );
+
+ $master_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
+ $master_user_id = absint( $master_token->external_user_id );
+
+ if ( !$master_user_id )
+ return; // this shouldn't happen
+
+ Jetpack::xmlrpc_async_call( 'jetpack.updateRole', $user_id, $signed_role );
+ //@todo retry on failure
+
+ //try to choose a new master if we're demoting the current one
+ if ( $user_id == $master_user_id && 'administrator' != $role ) {
+ $query = new WP_User_Query( array(
+ 'fields' => array( 'id' ),
+ 'role' => 'administrator',
+ 'orderby' => 'id',
+ 'exclude' => array( $master_user_id ),
+ )
+ );
+ $new_master = false;
+ foreach ( $query->results as $result ) {
+ $uid = absint( $result->id );
+ if ( $uid && Jetpack::is_user_connected( $uid ) ) {
+ $new_master = $uid;
+ break;
+ }
+ }
+
+ if ( $new_master ) {
+ Jetpack::update_option( 'master_user', $new_master );
+ }
+ // else disconnect..?
+ }
+ }
+ }
+
+ /**
* Loads the currently active modules.
*/
- function load_modules() {
+ public static function load_modules() {
if ( !Jetpack::is_active() ) {
return;
}
@@ -247,11 +388,61 @@ class Jetpack {
}
do_action( 'jetpack_modules_loaded' );
+
+ // 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.
+ require_once( dirname( __FILE__ ) . '/modules/module-extras.php' );
+ }
+
+ /**
+ * Check if Jetpack's Open Graph tags should be used.
+ * If certain plugins are active, Jetpack's og tags are suppressed.
+ *
+ * @uses Jetpack::get_active_modules, add_filter, get_option, apply_filters
+ * @action plugins_loaded
+ * @return null
+ */
+ public function check_open_graph() {
+ if ( in_array( 'publicize', Jetpack::get_active_modules() ) || in_array( 'sharedaddy', Jetpack::get_active_modules() ) )
+ add_filter( 'jetpack_enable_open_graph', '__return_true', 0 );
+
+ $active_plugins = get_option( 'active_plugins', array() );
+
+ $conflicting_plugins = array(
+ 'facebook/facebook.php', // Official Facebook plugin
+ 'wordpress-seo/wp-seo.php', // WordPress SEO by Yoast
+ 'add-link-to-facebook/add-link-to-facebook.php', // Add Link to Facebook
+ 'facebook-awd/AWD_facebook.php', // Facebook AWD All in one
+ 'header-footer/plugin.php', // Header and Footer
+ 'nextgen-facebook/nextgen-facebook.php', // NextGEN Facebook OG
+ 'seo-facebook-comments/seofacebook.php', // SEO Facebook Comments
+ 'seo-ultimate/seo-ultimate.php', // SEO Ultimate
+ 'sexybookmarks/sexy-bookmarks.php', // Shareaholic
+ 'shareaholic/sexy-bookmarks.php', // Shareaholic
+ 'social-discussions/social-discussions.php', // Social Discussions
+ 'social-networks-auto-poster-facebook-twitter-g/NextScripts_SNAP.php', // NextScripts SNAP
+ 'wordbooker/wordbooker.php', // Wordbooker
+ 'socialize/socialize.php', // Socialize
+ 'simple-facebook-connect/sfc.php', // Simple Facebook Connect
+ 'social-sharing-toolkit/social_sharing_toolkit.php', // Social Sharing Toolkit
+ 'wp-facebook-open-graph-protocol/wp-facebook-ogp.php', // WP Facebook Open Graph protocol
+ 'opengraph/opengraph.php', // Open Graph
+ 'sharepress/sharepress.php', // SharePress
+ );
+
+ foreach ( $conflicting_plugins as $plugin ) {
+ if ( in_array( $plugin, $active_plugins ) ) {
+ add_filter( 'jetpack_enable_open_graph', '__return_false', 99 );
+ break;
+ }
+ }
+
+ if ( apply_filters( 'jetpack_enable_open_graph', false ) )
+ require_once dirname( __FILE__ ) . '/functions.opengraph.php';
}
/* Jetpack Options API */
- function get_option_names( $type = 'compact' ) {
+ public static function get_option_names( $type = 'compact' ) {
switch ( $type ) {
case 'non-compact' :
case 'non_compact' :
@@ -260,17 +451,23 @@ class Jetpack {
'activated',
'active_modules',
'do_activate',
+ 'publicize',
+ 'widget_twitter',
);
}
return array(
'id', // (int) The Client ID/WP.com Blog ID of this site.
'blog_token', // (string) The Client Secret/Blog Token of this site.
- 'user_token', // (string) The User Token of this site.
+ 'user_token', // (string) The User Token of this site. (deprecated)
+ 'publicize_connections', // (array) An array of Publicize connections from WordPress.com
+ 'master_user', // (int) The local User ID of the user who connected this site to jetpack.wordpress.com.
+ 'user_tokens', // (array) User Tokens for each user of this site who has connected to jetpack.wordpress.com.
'version', // (string) Used during upgrade procedure to auto-activate new modules. version:time
'old_version', // (string) Used to determine which modules are the most recently added. previous_version:time
'fallback_no_verify_ssl_certs', // (int) Flag for determining if this host must skip SSL Certificate verification due to misconfigured SSL.
'time_diff', // (int) Offset between Jetpack server's clocks and this server's clocks. Jetpack Server Time = time() + (int) Jetpack::get_option( 'time_diff' )
+ '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.
);
}
@@ -280,7 +477,7 @@ class Jetpack {
* @param string $name Option name
* @param mixed $default (optional)
*/
- function get_option( $name, $default = false ) {
+ public static function get_option( $name, $default = false ) {
if ( in_array( $name, Jetpack::get_option_names( 'non_compact' ) ) ) {
return get_option( "jetpack_$name" );
} else if ( !in_array( $name, Jetpack::get_option_names() ) ) {
@@ -297,141 +494,23 @@ class Jetpack {
}
/**
- * Get a post and associated data in the standard JP format.
- * Cannot be called statically
- *
- * @param int $id Post ID
- * @param bool|array $columns Columns/fields to get.
- * @return Array containing full post details
- */
- function get_post( $id, $columns = true ) {
- $post_obj = get_post( $id );
- if ( !$post_obj )
- return false;
- $post = get_object_vars( $post_obj );
-
- // Only send specific columns if requested
- if ( is_array( $columns ) ) {
- $keys = array_keys( $post );
- foreach ( $keys as $column ) {
- if ( !in_array( $column, $columns ) ) {
- unset( $post[$column] );
- }
- }
- if ( in_array( '_jetpack_backfill', $columns ) ) {
- $post['_jetpack_backfill'] = true;
- }
- }
-
- if ( true === $columns || in_array( 'tax', $columns ) ) {
- $tax = array();
- $taxonomies = get_object_taxonomies( $post_obj );
- foreach ( $taxonomies as $taxonomy ) {
- $t = get_taxonomy( $taxonomy );
- $terms = get_object_term_cache( $post_obj->ID, $taxonomy );
- if ( empty( $terms ) )
- $terms = wp_get_object_terms( $post_obj->ID, $taxonomy );
- $term_names = array();
- foreach ( $terms as $term ) {
- $term_names[] = $term->name;
- }
- $tax[$taxonomy] = $term_names;
- }
- $post['tax'] = $tax;
- }
-
- // Include all postmeta for requests that specifically ask for it, or ask for everything
- if ( true == $columns || in_array( 'meta', $columns ) ) {
- $meta = get_post_meta( $post_obj->ID, false );
- $post['meta'] = array();
- foreach ( $meta as $key => $value ) {
- $post['meta'][$key] = array_map( 'maybe_unserialize', $value );
- }
- }
+ * Stores two secrets and a timestamp so WordPress.com can make a request back and verify an action
+ * Does some extra verification so urls (such as those to public-api, register, etc) cant just be crafted
+ * $name must be a registered option name.
+ */
+ public static function create_nonce( $name ) {
+ $secret = wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 );
+
+ Jetpack::update_option( $name, $secret );
+ @list( $secret_1, $secret_2, $eol ) = explode( ':', Jetpack::get_option( $name ) );
+ if ( empty( $secret_1 ) || empty( $secret_2 ) || $eol < time() )
+ return new Jetpack_Error( 'missing_secrets' );
- $post['extra'] = array(
- 'author' => get_the_author_meta( 'display_name', $post_obj->post_author ),
- 'author_email' => get_the_author_meta( 'email', $post_obj->post_author ),
+ return array(
+ 'secret_1' => $secret_1,
+ 'secret_2' => $secret_2,
+ 'eol' => $eol,
);
-
- $post['permalink'] = get_permalink( $post_obj->ID );
- return $post;
- }
-
- /**
- * Decide whether a post/page/attachment is visible to the public.
- *
- * @param array $post
- * @return bool
- */
- function is_post_public( $post ) {
- if ( ! is_array( $post ) )
- return false;
- if ( ! empty( $post['post_password'] ) )
- return false;
- if ( ! in_array( $post['post_type'], get_post_types( array( 'public' => true ) ) ) )
- return false;
- $post_status = get_post_status( $post['ID'] ); // Inherited status is resolved here.
- if ( ! in_array( $post_status, get_post_stati( array( 'public' => true ) ) ) )
- return false;
- return true;
- }
-
- /**
- * Get a comment and associated data in the standard JP format.
- * Cannot be called statically
- *
- * @param int $id Comment ID
- * @param array $columns Columns/fields to get.
- * @return Array containing full comment details
- */
- function get_comment( $id, $columns = true ) {
- $comment_obj = get_comment( $id );
- if ( !$comment_obj )
- return false;
- $comment = get_object_vars( $comment_obj );
-
- // Only send specific columns if requested
- if ( is_array( $columns ) ) {
- $keys = array_keys( $comment );
- foreach ( $keys as $column ) {
- if ( !in_array( $column, $columns ) ) {
- unset( $comment[$column] );
- }
- }
- }
-
- // Include all commentmeta for requests that specifically ask for it, or ask for everything
- if ( isset( $columns['meta'] ) || true == $columns ) {
- $meta = get_comment_meta( $id, false );
- $comment['meta'] = array();
- foreach ( $meta as $key => $value ) {
- $comment['meta'][$key] = array_map( 'maybe_unserialize', $value );
- }
- }
-
- return $comment;
- }
-
- function get_taxonomy( $id, $columns = true, $type ) {
- $taxonomy_obj = get_term_by( 'slug', $id, $type );
-
- if ( !$taxonomy_obj )
- return false;
- $taxonomy = get_object_vars( $taxonomy_obj );
-
- // Only send specific columns if requested
- if ( is_array( $columns ) ) {
- $keys = array_keys( $taxonomy );
- foreach ( $keys as $column ) {
- if ( !in_array( $column, $columns ) ) {
- unset( $taxonomy[$column] );
- }
- }
- }
-
- $taxonomy['type'] = $type;
- return $taxonomy;
}
/**
@@ -440,7 +519,7 @@ class Jetpack {
* @param string $name Option name
* @param mixed $value Option value
*/
- function update_option( $name, $value ) {
+ public static function update_option( $name, $value ) {
if ( in_array( $name, Jetpack::get_option_names( 'non_compact' ) ) ) {
return update_option( "jetpack_$name", $value );
} else if ( !in_array( $name, Jetpack::get_option_names() ) ) {
@@ -463,7 +542,7 @@ class Jetpack {
*
* @param array $array array( option name => option value, ... )
*/
- function update_options( $array ) {
+ public static function update_options( $array ) {
$names = array_keys( $array );
foreach ( array_diff( $names, Jetpack::get_option_names(), Jetpack::get_option_names( 'non_compact' ) ) as $unknown_name ) {
@@ -490,7 +569,7 @@ class Jetpack {
*
* @param string|array $names
*/
- function delete_option( $names ) {
+ public static function delete_option( $names ) {
$names = (array) $names;
foreach ( array_diff( $names, Jetpack::get_option_names(), Jetpack::get_option_names( 'non_compact' ) ) as $unknown_name ) {
@@ -512,20 +591,42 @@ class Jetpack {
unset( $options[$name] );
}
- return update_option( 'jetpack_options', $options );;
+ return update_option( 'jetpack_options', $options );
}
return true;
}
/**
+ * Enters a user token into the user_tokens option
+ *
+ * @param int $user_id
+ * @param string $token
+ * return bool
+ */
+ public static function update_user_token( $user_id, $token, $is_master_user ) {
+ // not designed for concurrent updates
+ $user_tokens = Jetpack::get_option( 'user_tokens' );
+ if ( ! is_array( $user_tokens ) )
+ $user_tokens = array();
+ $user_tokens[$user_id] = $token;
+ if ( $is_master_user ) {
+ $master_user = $user_id;
+ $options = compact('user_tokens', 'master_user');
+ } else {
+ $options = compact('user_tokens');
+ }
+ return Jetpack::update_options( $options );
+ }
+
+ /**
* Returns an array of all PHP files in the specified absolute path.
* Equivalent to glob( "$absolute_path/*.php" ).
*
* @param string $absolute_path The absolute path of the directory to search.
* @return array Array of absolute paths to the PHP files.
*/
- function glob_php( $absolute_path ) {
+ public static function glob_php( $absolute_path ) {
$absolute_path = untrailingslashit( $absolute_path );
$files = array();
if ( !$dir = @opendir( $absolute_path ) ) {
@@ -551,8 +652,8 @@ class Jetpack {
return $files;
}
- function activate_new_modules() {
- if ( !$this->is_active() ) {
+ public function activate_new_modules() {
+ if ( ! Jetpack::is_active() ) {
return;
}
@@ -584,6 +685,10 @@ class Jetpack {
Jetpack::deactivate_module( $active_module );
}
+ if ( version_compare( $jetpack_version, '1.9.2', '<' ) && version_compare( '1.9-something', JETPACK__VERSION, '<' ) ) {
+ add_action( 'jetpack_activate_default_modules', array( $this->sync, 'sync_all_registered_options' ), 1000 );
+ }
+
Jetpack::update_options( array(
'version' => JETPACK__VERSION . ':' . time(),
'old_version' => $jetpack_old_version,
@@ -599,7 +704,7 @@ class Jetpack {
* List available Jetpack modules. Simply lists .php files in /modules/.
* Make sure to tuck away module "library" files in a sub-directory.
*/
- function get_available_modules( $min_version = false, $max_version = false ) {
+ public static function get_available_modules( $min_version = false, $max_version = false ) {
static $modules = null;
if ( !isset( $modules ) ) {
@@ -639,15 +744,31 @@ class Jetpack {
/**
* Default modules loaded on activation.
*/
- function get_default_modules( $min_version = false, $max_version = false ) {
+ public static function get_default_modules( $min_version = false, $max_version = false ) {
$return = array();
foreach ( Jetpack::get_available_modules( $min_version, $max_version ) as $module ) {
// Add special cases here for modules to avoid auto-activation
switch ( $module ) {
+
+ // These modules are default off: they change things blog-side
case 'comments' :
case 'carousel' :
- continue;
+ case 'minileven':
+ case 'infinite-scroll' :
+ case 'photon' :
+ case 'tiled-gallery' :
+ case 'likes' :
+ break;
+
+ // These modules are default off if we think the site is a private one
+ case 'enhanced-distribution' :
+ case 'json-api' :
+ if ( !Jetpack::get_option( 'public' ) ) {
+ break;
+ }
+ // else no break
+ // The rest are default on
default :
$return[] = $module;
}
@@ -659,14 +780,14 @@ class Jetpack {
/**
* Extract a module's slug from its full path.
*/
- function get_module_slug( $file ) {
+ public static function get_module_slug( $file ) {
return str_replace( '.php', '', basename( $file ) );
}
/**
* Generate a module's path from its slug.
*/
- function get_module_path( $slug ) {
+ public static function get_module_path( $slug ) {
return dirname( __FILE__ ) . "/modules/$slug.php";
}
@@ -675,7 +796,7 @@ class Jetpack {
* plugin headers to avoid them being identified as standalone
* plugins on the WordPress plugins page.
*/
- function get_module( $module ) {
+ public static function get_module( $module ) {
$headers = array(
'name' => 'Module Name',
'description' => 'Module Description',
@@ -706,7 +827,7 @@ class Jetpack {
/**
* Get a list of activated modules as an array of module slugs.
*/
- function get_active_modules() {
+ public static function get_active_modules() {
$active = Jetpack::get_option( 'active_modules' );
if ( !is_array( $active ) )
$active = array();
@@ -718,7 +839,7 @@ class Jetpack {
return array_unique( $active );
}
- function is_module( $module ) {
+ public static function is_module( $module ) {
return !empty( $module ) && !validate_file( $module, Jetpack::get_available_modules() );
}
@@ -729,7 +850,7 @@ class Jetpack {
*
* @static
*/
- function catch_errors( $catch ) {
+ public static function catch_errors( $catch ) {
static $display_errors, $error_reporting;
if ( $catch ) {
@@ -746,11 +867,11 @@ class Jetpack {
/**
* Saves any generated PHP errors in ::state( 'php_errors', {errors} )
*/
- function catch_errors_on_shutdown() {
+ public static function catch_errors_on_shutdown() {
Jetpack::state( 'php_errors', ob_get_clean() );
}
- function activate_default_modules( $min_version = false, $max_version = false, $other_modules = array() ) {
+ public static function activate_default_modules( $min_version = false, $max_version = false, $other_modules = array() ) {
$jetpack = Jetpack::init();
$modules = Jetpack::get_default_modules( $min_version, $max_version );
@@ -784,6 +905,8 @@ class Jetpack {
exit;
}
+ do_action( 'jetpack_before_activate_default_modules', $min_version, $max_version, $other_modules );
+
// Check each module for fatal errors, a la wp-admin/plugins.php::activate before activating
$redirect = menu_page_url( 'jetpack', false );
Jetpack::restate();
@@ -816,6 +939,7 @@ class Jetpack {
Jetpack::state( 'module', $module );
ob_start();
require $file;
+ do_action( 'jetpack_activate_module', $module );
$active[] = $module;
$state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules';
if ( $active_state = Jetpack::state( $state ) ) {
@@ -831,9 +955,10 @@ class Jetpack {
Jetpack::state( 'error', false );
Jetpack::state( 'module', false );
Jetpack::catch_errors( false );
+ do_action( 'jetpack_activate_default_modules', $min_version, $max_version, $other_modules );
}
- function activate_module( $module ) {
+ public static function activate_module( $module ) {
$jetpack = Jetpack::init();
if ( !Jetpack::is_active() )
@@ -872,7 +997,7 @@ class Jetpack {
Jetpack::catch_errors( true );
ob_start();
require Jetpack::get_module_path( $module );
- do_action( "jetpack_activate_module_$module" );
+ do_action( 'jetpack_activate_module', $module );
$active[] = $module;
Jetpack::update_option( 'active_modules', array_unique( $active ) );
Jetpack::state( 'error', false ); // the override
@@ -883,7 +1008,13 @@ class Jetpack {
exit;
}
- function deactivate_module( $module ) {
+ function activate_module_actions( $module ) {
+ do_action( "jetpack_activate_module_$module" );
+
+ $this->sync->sync_all_module_options( $module );
+ }
+
+ public static function deactivate_module( $module ) {
$active = Jetpack::get_active_modules();
$new = array();
foreach ( $active as $check ) {
@@ -895,34 +1026,34 @@ class Jetpack {
return Jetpack::update_option( 'active_modules', array_unique( $new ) );
}
- function enable_module_configurable( $module ) {
+ public static function enable_module_configurable( $module ) {
$module = Jetpack::get_module_slug( $module );
add_filter( 'jetpack_module_configurable_' . $module, '__return_true' );
}
- function module_configuration_url( $module ) {
+ public static function module_configuration_url( $module ) {
$module = Jetpack::get_module_slug( $module );
return Jetpack::admin_url( array( 'configure' => $module ) );
}
- function module_configuration_load( $module, $method ) {
+ public static function module_configuration_load( $module, $method ) {
$module = Jetpack::get_module_slug( $module );
add_action( 'jetpack_module_configuration_load_' . $module, $method );
}
- function module_configuration_head( $module, $method ) {
+ public static function module_configuration_head( $module, $method ) {
$module = Jetpack::get_module_slug( $module );
add_action( 'jetpack_module_configuration_head_' . $module, $method );
}
- function module_configuration_screen( $module, $method ) {
+ public static function module_configuration_screen( $module, $method ) {
$module = Jetpack::get_module_slug( $module );
add_action( 'jetpack_module_configuration_screen_' . $module, $method );
}
/* Installation */
- function bail_on_activation( $message, $deactivate = true ) {
+ public static function bail_on_activation( $message, $deactivate = true ) {
?>
<!doctype html>
<html>
@@ -967,7 +1098,7 @@ p {
* Attached to activate_{ plugin_basename( __FILES__ ) } by register_activation_hook()
* @static
*/
- function plugin_activation( $network_wide ) {
+ public static function plugin_activation( $network_wide ) {
Jetpack::update_option( 'activated', 1 );
if ( version_compare( $GLOBALS['wp_version'], JETPACK__MINIMUM_WP_VERSION, '<' ) ) {
@@ -984,7 +1115,7 @@ p {
* Sets the internal version number and activation state.
* @static
*/
- function plugin_initialize() {
+ public static function plugin_initialize() {
if ( !Jetpack::get_option( 'activated' ) ) {
Jetpack::update_option( 'activated', 2 );
}
@@ -1003,7 +1134,7 @@ p {
* Removes all connection options
* @static
*/
- function plugin_deactivation( $network_wide ) {
+ public static function plugin_deactivation( $network_wide ) {
Jetpack::disconnect( false );
}
@@ -1012,7 +1143,7 @@ p {
* Forgets all connection details and tells the Jetpack servers to do the same.
* @static
*/
- function disconnect( $update_activated_state = true ) {
+ public static function disconnect( $update_activated_state = true ) {
wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
Jetpack::clean_nonces( true );
@@ -1024,6 +1155,8 @@ p {
'register',
'blog_token',
'user_token',
+ 'user_tokens',
+ 'master_user',
'time_diff',
'fallback_no_verify_ssl_certs',
) );
@@ -1034,10 +1167,35 @@ p {
}
/**
+ * Unlinks the current user from the linked WordPress.com user
+ */
+ function unlink_user() {
+ if ( !$tokens = Jetpack::get_option( 'user_tokens' ) )
+ return false;
+
+ $user_id = get_current_user_id();
+
+ if ( Jetpack::get_option( 'master_user' ) == $user_id )
+ return false;
+
+ if ( !isset( $tokens[$user_id] ) )
+ return false;
+
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client( compact( 'user_id' ) );
+ $xml->query( 'jetpack.unlink_user', $user_id );
+
+ unset( $tokens[$user_id] );
+
+ Jetpack::update_option( 'user_tokens', $tokens );
+
+ return true;
+ }
+
+ /**
* Attempts Jetpack registration. If it fail, a state flag is set: @see ::admin_page_load()
- * @static
*/
- function try_registration() {
+ public static function try_registration() {
$result = Jetpack::register();
// If there was an error with registration and the site was not registered, record this so we can show a message.
@@ -1062,9 +1220,7 @@ p {
Jetpack::plugin_initialize();
}
- $is_active = Jetpack::is_active();
-
- if ( !$is_active ) {
+ if ( !Jetpack::is_active() ) {
if ( 4 != Jetpack::get_option( 'activated' ) ) {
// Show connect notice on dashboard and plugins pages
add_action( 'load-index.php', array( $this, 'prepare_connect_notice' ) );
@@ -1087,10 +1243,13 @@ p {
add_action( 'wp_ajax_jetpack_debug', array( $this, 'ajax_debug' ) );
- if ( $is_active ) {
+ if ( Jetpack::is_active() ) {
// Artificially throw errors in certain whitelisted cases during plugin activation
add_action( 'activate_plugin', array( $this, 'throw_error_on_activate_plugin' ) );
+ // Kick off synchronization of user role when it changes
+ add_action( 'set_user_role', array( $this, 'user_role_change' ) );
+
// Add retina images hotfix to admin
global $wp_db_version;
if ( $wp_db_version > 19470 ) {
@@ -1154,7 +1313,7 @@ p {
foreach ( $this->plugins_to_deactivate as $module => $deactivate_me ) {
if ( "plugin-activation-error_{$deactivate_me[0]}" == $action ) {
- $this->bail_on_activation( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), $deactivate_me[1] ), false );
+ Jetpack::bail_on_activation( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), $deactivate_me[1] ), false );
}
}
}
@@ -1172,7 +1331,7 @@ p {
&&
( $new_modules_count = count( $new_modules ) )
&&
- $this->is_active()
+ Jetpack::is_active()
) {
$new_modules_count_i18n = number_format_i18n( $new_modules_count );
$span_title = esc_attr( sprintf( _n( 'One New Jetpack Module', '%s New Jetpack Modules', $new_modules_count, 'jetpack' ), $new_modules_count_i18n ) );
@@ -1181,7 +1340,7 @@ p {
$title = __( 'Jetpack', 'jetpack' );
}
- $hook = add_menu_page( 'Jetpack', $title, 'manage_options', 'jetpack', array( $this, 'admin_page' ), 'div' );
+ $hook = add_menu_page( 'Jetpack', $title, 'read', 'jetpack', array( $this, 'admin_page' ), 'div' );
add_action( "load-$hook", array( $this, 'admin_page_load' ) );
@@ -1203,6 +1362,126 @@ p {
do_action( 'jetpack_admin_menu' );
}
+ function add_remote_request_handlers() {
+ add_action( 'wp_ajax_nopriv_jetpack_upload_file', array( $this, 'remote_request_handlers' ) );
+ }
+
+ function remote_request_handlers() {
+ switch ( current_filter() ) {
+ case 'wp_ajax_nopriv_jetpack_upload_file' :
+ $response = $this->upload_handler();
+ break;
+ default :
+ $response = new Jetpack_Error( 'unknown_handler', 'Unknown Handler', 400 );
+ break;
+ }
+
+ if ( !$response ) {
+ $response = new Jetpack_Error( 'unknown_error', 'Unknown Error', 400 );
+ }
+
+ if ( is_wp_error( $response ) ) {
+ $status_code = $response->get_error_data();
+ $error = $response->get_error_code();
+ $error_description = $response->get_error_message();
+
+ if ( !is_int( $status_code ) ) {
+ $status_code = 400;
+ }
+
+ status_header( $status_code );
+ die( json_encode( (object) compact( 'error', 'error_description' ) ) );
+ }
+
+ status_header( 200 );
+ if ( true === $response ) {
+ exit;
+ }
+
+ die( json_encode( (object) $response ) );
+ }
+
+ function upload_handler() {
+ if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
+ return new Jetpack_Error( 405, get_status_header_desc( 405 ), 405 );
+ }
+
+ $user = wp_authenticate( '', '' );
+ if ( !$user || is_wp_error( $user ) ) {
+ return new Jetpack_Error( 403, get_status_header_desc( 403 ), 403 );
+ }
+
+ wp_set_current_user( $user->ID );
+
+ if ( !current_user_can( 'upload_files' ) ) {
+ return new Jetpack_Error( 'cannot_upload_files', 'User does not have permission to upload files', 403 );
+ }
+
+ if ( empty( $_FILES ) ) {
+ return new Jetpack_Error( 'no_files_uploaded', 'No files were uploaded: nothing to process', 400 );
+ }
+
+ foreach ( array_keys( $_FILES ) as $files_key ) {
+ if ( !isset( $_POST["_jetpack_file_hmac_{$files_key}"] ) ) {
+ return new Jetpack_Error( 'missing_hmac', 'An HMAC for one or more files is missing', 400 );
+ }
+ }
+
+ $media_keys = array_keys( $_FILES['media'] );
+
+ $token = Jetpack_Data::get_access_token( get_current_user_id() );
+ if ( !$token || is_wp_error( $token ) ) {
+ return new Jetpack_Error( 'unknown_token', 'Unknown Jetpack token', 403 );
+ }
+
+ $uploaded_files = array();
+ $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
+ unset( $GLOBALS['post'] );
+ foreach ( $_FILES['media']['name'] as $index => $name ) {
+ $file = array();
+ foreach ( $media_keys as $media_key ) {
+ $file[$media_key] = $_FILES['media'][$media_key][$index];
+ }
+
+ list( $hmac_provided, $salt ) = explode( ':', $_POST['_jetpack_file_hmac_media'][$index] );
+
+ $hmac_file = hash_hmac_file( 'sha1', $file['tmp_name'], $salt . $token->secret );
+ if ( $hmac_provided !== $hmac_file ) {
+ $uploaded_files[$index] = (object) array( 'error' => 'invalid_hmac', 'error_description' => 'The corresponding HMAC for this file does not match' );
+ continue;
+ }
+
+ $_FILES['.jetpack.upload.'] = $file;
+ $post_id = isset( $_POST['post_id'][$index] ) ? absint( $_POST['post_id'][$index] ) : 0;
+ if ( !current_user_can( 'edit_post', $post_id ) ) {
+ $post_id = 0;
+ }
+ $attachment_id = media_handle_upload( '.jetpack.upload.', $post_id, array(), array(
+ 'action' => 'jetpack_upload_file',
+ ) );
+
+ if ( !$attachment_id ) {
+ $uploaded_files[$index] = (object) array( 'error' => 'unknown', 'error_description' => 'An unknown problem occurred processing the upload on the Jetpack site' );
+ } elseif ( is_wp_error( $attachment_id ) ) {
+ $uploaded_files[$index] = (object) array( 'error' => 'attachment_' . $attachment_id->get_error_code(), 'error_description' => $attachment_id->get_error_message() );
+ } else {
+ $attachment = get_post( $attachment_id );
+ $uploaded_files[$index] = (object) array(
+ 'id' => (string) $attachment_id,
+ 'file' => $attachment->post_title,
+ 'url' => wp_get_attachment_url( $attachment_id ),
+ 'type' => $attachment->post_mime_type,
+ 'meta' => wp_get_attachment_metadata( $attachment_id ),
+ );
+ }
+ }
+ if ( !is_null( $global_post ) ) {
+ $GLOBALS['post'] = $global_post;
+ }
+
+ return $uploaded_files;
+ }
+
/**
* Add help to the Jetpack page
*
@@ -1240,19 +1519,21 @@ p {
) );
// Screen Content
- $current_screen->add_help_tab( array(
- 'id' => 'modules',
- 'title' => __( 'Modules', 'jetpack' ),
- 'content' =>
- '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
- '<p>' . __( 'You can activate or deactivate individual Jetpack modules to suit your needs.', 'jetpack' ) . '</p>' .
- '<ol>' .
- '<li>' . __( 'Find the component you want to manage', 'jetpack' ) . '</li>' .
- '<li>' . __( 'Click on Learn More', 'jetpack' ) . '</li>' .
- '<li>' . __( 'An Activate or Deactivate button will appear', 'jetpack' ) . '</li>' .
- '<li>' . __( 'If additional settings are available, a link to them will appear', 'jetpack' ) . '</li>' .
- '</ol>'
- ) );
+ if ( current_user_can( 'manage_options' ) ) {
+ $current_screen->add_help_tab( array(
+ 'id' => 'modules',
+ 'title' => __( 'Modules', 'jetpack' ),
+ 'content' =>
+ '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
+ '<p>' . __( 'You can activate or deactivate individual Jetpack modules to suit your needs.', 'jetpack' ) . '</p>' .
+ '<ol>' .
+ '<li>' . __( 'Find the component you want to manage', 'jetpack' ) . '</li>' .
+ '<li>' . __( 'Click on Learn More', 'jetpack' ) . '</li>' .
+ '<li>' . __( 'An Activate or Deactivate button will appear', 'jetpack' ) . '</li>' .
+ '<li>' . __( 'If additional settings are available, a link to them will appear', 'jetpack' ) . '</li>' .
+ '</ol>'
+ ) );
+ }
// Help Sidebar
$current_screen->set_help_sidebar(
@@ -1264,20 +1545,20 @@ p {
function admin_menu_css() { ?>
<style type="text/css" id="jetpack-menu-css">
- #toplevel_page_jetpack .wp-menu-image {
- background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite.png' ) ?> ) 0 90% no-repeat;
+ #toplevel_page_jetpack .wp-menu-image {
+ background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite.png' ) ?> ) 0 90% no-repeat;
}
/* Retina Jetpack Menu Icon */
@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) {
- #toplevel_page_jetpack .wp-menu-image {
+ #toplevel_page_jetpack .wp-menu-image {
background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite-2x.png' ) ?> ) 0 90% no-repeat;
background-size:30px 64px;
}
}
- #toplevel_page_jetpack.current .wp-menu-image,
- #toplevel_page_jetpack.wp-has-current-submenu .wp-menu-image,
- #toplevel_page_jetpack:hover .wp-menu-image {
- background-position: top left;
+ #toplevel_page_jetpack.current .wp-menu-image,
+ #toplevel_page_jetpack.wp-has-current-submenu .wp-menu-image,
+ #toplevel_page_jetpack:hover .wp-menu-image {
+ background-position: top left;
}
</style><?php
}
@@ -1301,20 +1582,21 @@ p {
}
function admin_head() {
- if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) )
+ if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) )
do_action( 'jetpack_module_configuration_head_' . $_GET['configure'] );
}
function admin_styles() {
global $wp_styles;
- wp_enqueue_style( 'jetpack', plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/jetpack.css' ), false, JETPACK__VERSION . '-20120701' );
+ wp_enqueue_style( 'jetpack', plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/jetpack.css' ), false, JETPACK__VERSION . '-20121016' );
$wp_styles->add_data( 'jetpack', 'rtl', true );
}
function admin_scripts() {
- wp_enqueue_script( 'jetpack-js', plugins_url( basename( dirname( __FILE__ ) ) ) . '/_inc/jetpack.js', array( 'jquery' ), JETPACK__VERSION . '-20111115' );
+ wp_enqueue_script( 'jetpack-js', plugins_url( basename( dirname( __FILE__ ) ) ) . '/_inc/jetpack.js', array( 'jquery' ), JETPACK__VERSION . '-20121111' );
wp_localize_script( 'jetpack-js', 'jetpackL10n', array(
'ays_disconnect' => "This will deactivate all Jetpack modules.\nAre you sure you want to disconnect?",
+ '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?",
'ays_dismiss' => "This will deactivate Jetpack.\nAre you sure you want to deactivate Jetpack?",
) );
add_action( 'admin_footer', array( $this, 'do_stats' ) );
@@ -1349,7 +1631,7 @@ p {
<div class="jetpack-text-container">
<h4>
<?php if ( 1 == Jetpack::get_option( 'activated' ) ) : ?>
- <p><?php _e( '<strong>Your Jetpack is almost ready</strong> &#8211; A connection to WordPress.com is needed to enabled features like Comments, Stats, Contact Forms, and Subscriptions. Connect now to get fueled up!', 'jetpack' ); ?></p>
+ <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>
<?php else : ?>
<p><?php _e( '<strong>Jetpack is installed</strong> and ready to bring awesome, WordPress.com cloud-powered features to your site.', 'jetpack' ) ?></p>
<?php endif; ?>
@@ -1377,8 +1659,8 @@ p {
</div>
<?php
}
-
- function jetpack_comment_notice() {
+
+ public static function jetpack_comment_notice() {
if ( in_array( 'comments', Jetpack::get_active_modules() ) ) {
return '';
}
@@ -1398,7 +1680,7 @@ p {
}
}
- return '<br /><br />' . sprintf(
+ return '<br /><br />' . sprintf(
__( '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' ),
wp_nonce_url(
Jetpack::admin_url( array(
@@ -1423,17 +1705,17 @@ p {
* xmlrpc.php?for=jetpack: RPC method: jetpack.verifyRegistration, Parameters: secret_1
* - The XML-RPC request verifies secret_1, deletes both secrets and responds with: secret_2
* - https://jetpack.wordpress.com/jetpack.register/1/ verifies that XML-RPC response (secret_2) then finally responds itself with
- * jetpack_id, jetpack_secret
+ * jetpack_id, jetpack_secret, jetpack_public
* - ::register() then stores jetpack_options: id => jetpack_id, blog_token => jetpack_secret
* 4 - redirect to https://jetpack.wordpress.com/jetpack.authorize/1/
* 5 - user logs in with WP.com account
* 6 - redirect to this site's wp-admin/index.php?page=jetpack&action=authorize with
- * code <-- OAuth2 style authorization code
+ * code <-- OAuth2 style authorization code
* 7 - ::admin_page_load() action=authorize
* 8 - Jetpack_Client_Server::authorize()
* 9 - Jetpack_Client_Server::get_token()
* 10- GET https://jetpack.wordpress.com/jetpack.token/1/ with
- * client_id, client_secret, grant_type, code, redirect_uri:action=authorize, state, scope, user_email
+ * client_id, client_secret, grant_type, code, redirect_uri:action=authorize, state, scope, user_email, user_login
* 11- which responds with
* access_token, token_type, scope
* 12- Jetpack_Client_Server::authorize() stores jetpack_options: user_token => access_token.$user_id
@@ -1456,10 +1738,25 @@ p {
Jetpack::restate();
}
+ if ( isset( $_GET['connect_url_redirect'] ) ) {
+ // User clicked in the iframe to link their accounts
+ if ( ! Jetpack::is_user_connected() ) {
+ $connect_url = $this->build_connect_url( true );
+ if ( isset( $_GET['notes_iframe'] ) )
+ $connect_url .= '&notes_iframe';
+ wp_redirect( $connect_url );
+ exit;
+ } else {
+ Jetpack::state( 'message', 'already_authorized' );
+ wp_safe_redirect( Jetpack::admin_url() );
+ exit;
+ }
+ }
+
if ( isset( $_GET['action'] ) ) {
switch ( $_GET['action'] ) {
case 'authorize' :
- if ( Jetpack::is_active() ) {
+ if ( Jetpack::is_active() && Jetpack::is_user_connected() ) {
Jetpack::state( 'message', 'already_authorized' );
wp_safe_redirect( Jetpack::admin_url() );
exit;
@@ -1495,22 +1792,30 @@ p {
exit;
case 'disconnect' :
check_admin_referer( 'jetpack-disconnect' );
- $this->disconnect();
+ Jetpack::disconnect();
wp_safe_redirect( Jetpack::admin_url() );
exit;
case 'deactivate' :
- $module = stripslashes( $_GET['module'] );
- check_admin_referer( "jetpack_deactivate-$module" );
- Jetpack::deactivate_module( $module );
- Jetpack::state( 'message', 'module_deactivated' );
- Jetpack::state( 'module', $module );
+ $modules = stripslashes( $_GET['module'] );
+ check_admin_referer( "jetpack_deactivate-$modules" );
+ foreach ( explode( ',', $modules ) as $module ) {
+ Jetpack::deactivate_module( $module );
+ Jetpack::state( 'message', 'module_deactivated' );
+ }
+ Jetpack::state( 'module', $modules );
+ wp_safe_redirect( Jetpack::admin_url() );
+ exit;
+ case 'unlink' :
+ check_admin_referer( 'jetpack-unlink' );
+ $this->unlink_user();
+ Jetpack::state( 'message', 'unlinked' );
wp_safe_redirect( Jetpack::admin_url() );
exit;
}
}
if ( !$error = $error ? $error : Jetpack::state( 'error' ) ) {
- Jetpack::activate_new_modules();
+ $this->activate_new_modules();
}
switch ( $error ) {
@@ -1663,10 +1968,35 @@ p {
break;
case 'module_deactivated' :
- if ( $module = Jetpack::get_module( Jetpack::state( 'module' ) ) ) {
- $this->message = sprintf( __( '<strong>%s Deactivated!</strong> You can activate it again at any time using the activate button on the module card.', 'jetpack' ), $module['name'] );
- $this->stat( 'module-deactivated', Jetpack::state( 'module' ) );
+ $modules = Jetpack::state( 'module' );
+ if ( !$modules ) {
+ break;
}
+
+ $module_names = array();
+ foreach ( explode( ',', $modules ) as $module_slug ) {
+ $module = Jetpack::get_module( $module_slug );
+ if ( $module ) {
+ $module_names[] = $module['name'];
+ }
+
+ $this->stat( 'module-deactivated', $module_slug );
+ }
+
+ if ( !$module_names ) {
+ break;
+ }
+
+ $this->message = wp_sprintf(
+ _nx(
+ '<strong>%l Deactivated!</strong> You can activate it again at any time using the activate button on the module card.',
+ '<strong>%l Deactivated!</strong> You can activate them again at any time using the activate buttons on their module cards.',
+ count( $module_names ),
+ '%l = list of Jetpack module/feature names',
+ 'jetpack'
+ ),
+ $module_names
+ );
break;
case 'module_configured' :
@@ -1683,6 +2013,16 @@ p {
$this->message .= __( 'The features below are now active. Click the learn more buttons to explore each feature.', 'jetpack' );
$this->message .= Jetpack::jetpack_comment_notice();
break;
+
+ case 'linked' :
+ $this->message = __( "<strong>You&#8217;re fueled up and ready to go.</strong> ", 'jetpack' );
+ $this->message .= Jetpack::jetpack_comment_notice();
+ break;
+
+ case 'unlinked' :
+ $user = wp_get_current_user();
+ $this->message = sprintf( __( '<strong>You have unlinked your account (%s) from WordPress.com.</strong>', 'jetpack' ), $user->user_login );
+ break;
}
$deactivated_plugins = Jetpack::state( 'deactivated_plugins' );
@@ -1721,11 +2061,13 @@ p {
}
}
- if ( $this->message || $this->error ) {
+ $this->privacy_checks = Jetpack::state( 'privacy_checks' );
+
+ if ( $this->message || $this->error || $this->privacy_checks ) {
add_action( 'jetpack_notices', array( $this, 'admin_notices' ) );
}
- if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) ) {
+ if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
do_action( 'jetpack_module_configuration_load_' . $_GET['configure'] );
}
@@ -1755,7 +2097,64 @@ p {
</div>
</div>
<?php
+
}
+
+ if ( $this->privacy_checks ) :
+ $module_names = $module_slugs = array();
+
+ $privacy_checks = explode( ',', $this->privacy_checks );
+ foreach ( $privacy_checks as $module_slug ) {
+ $module = Jetpack::get_module( $module_slug );
+ if ( !$module ) {
+ continue;
+ }
+
+ $module_slugs[] = $module_slug;
+ $module_names[] = "<strong>{$module['name']}</strong>";
+ }
+
+ $module_slugs = join( ',', $module_slugs );
+?>
+<div id="message" class="jetpack-message jetpack-err">
+ <div class="squeezer">
+ <h4><strong><?php esc_html_e( 'Is this site private?', 'jetpack' ); ?></strong></h4><br />
+ <p><?php
+ echo wp_kses( wptexturize( wp_sprintf(
+ _nx(
+ "Like your site's RSS feeds, %l allows access to your posts and other content to third parties.",
+ "Like your site's RSS feeds, %l allow access to your posts and other content to third parties.",
+ count( $privacy_checks ),
+ '%l = list of Jetpack module/feature names',
+ 'jetpack'
+ ),
+ $module_names
+ ) ), array( 'strong' => true ) );
+
+ echo "\n<br />\n";
+
+ echo wp_kses( sprintf(
+ _nx(
+ 'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating this feature</a>.',
+ 'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating these features</a>.',
+ count( $privacy_checks ),
+ '%1$s = deactivation URL, %2$s = "Deactivate {list of Jetpack module/feature names}',
+ 'jetpack'
+ ),
+ wp_nonce_url(
+ Jetpack::admin_url( array(
+ 'action' => 'deactivate',
+ 'module' => urlencode( $module_slugs ),
+ ) ),
+ "jetpack_deactivate-$module_slugs"
+ ),
+ esc_attr( wp_kses( wp_sprintf( _x( 'Deactivate %l', '%l = list of Jetpack module/feature names', 'jetpack' ), $module_names ), array() ) )
+ ), array( 'a' => array( 'href' => true, 'title' => true ) ) );
+ ?></p>
+ </div>
+</div>
+<?php
+ endif;
}
/**
@@ -1802,7 +2201,7 @@ p {
return false;
}
- $token = Jetpack_Data::get_access_token( 0 );
+ $token = Jetpack_Data::get_access_token();
if ( !$token || is_wp_error( $token ) ) {
return false;
}
@@ -1810,7 +2209,7 @@ p {
return $role . ':' . hash_hmac( 'md5', "{$role}|{$user_id}", $token->secret );
}
- function build_connect_url( $raw = false ) {
+ function build_connect_url( $raw = false, $redirect = false ) {
if ( !Jetpack::get_option( 'blog_token' ) ) {
$url = wp_nonce_url( add_query_arg( 'action', 'register', menu_page_url( 'jetpack', false ) ), 'jetpack-register' );
} else {
@@ -1819,16 +2218,21 @@ p {
$user = wp_get_current_user();
+ $redirect = $redirect ? esc_url_raw( $redirect ) : '';
+
$args = urlencode_deep( array(
'response_type' => 'code',
'client_id' => Jetpack::get_option( 'id' ),
'redirect_uri' => add_query_arg( array(
'action' => 'authorize',
- '_wpnonce' => wp_create_nonce( "jetpack-authorize_$role" ),
+ '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
+ 'redirect' => $redirect ? urlencode( $redirect ) : false,
), menu_page_url( 'jetpack', false ) ),
'state' => $user->ID,
'scope' => $signed_role,
'user_email' => $user->user_email,
+ 'user_login' => $user->user_login,
+ 'is_active' => Jetpack::is_active(),
) );
$url = add_query_arg( $args, Jetpack::api_url( 'authorize' ) );
@@ -1837,8 +2241,8 @@ p {
return $raw ? $url : esc_url( $url );
}
- function admin_url( $args = null ) {
- $url = menu_page_url( 'jetpack', false );
+ public static function admin_url( $args = null ) {
+ $url = admin_url( 'admin.php?page=jetpack' );
if ( is_array( $args ) )
$url = add_query_arg( $args, $url );
return $url;
@@ -1860,6 +2264,9 @@ p {
$role = $this->translate_current_user_to_role();
$is_connected = Jetpack::is_active();
+ $user_token = Jetpack_Data::get_access_token($current_user->ID);
+ $is_user_connected = $user_token && !is_wp_error($user_token);
+ $is_master_user = $current_user->ID == Jetpack::get_option( 'master_user' );
$module = false;
?>
<div class="wrap" id="jetpack-settings">
@@ -1869,9 +2276,17 @@ p {
<div id="jp-header"<?php if ( $is_connected ) : ?> class="small"<?php endif; ?>>
<div id="jp-clouds">
<?php if ( $is_connected ) : ?>
- <div id="jp-disconnect">
- <a href="<?php echo wp_nonce_url( Jetpack::admin_url( array( 'action' => 'disconnect' ) ), 'jetpack-disconnect' ); ?>"><?php _e( 'Connected to WordPress.com', 'jetpack' ); ?></a>
- <span><?php _e( 'Disconnect from WordPress.com', 'jetpack' ) ?></span>
+ <div id="jp-disconnectors">
+ <?php if ( current_user_can( 'manage_options' ) ) : ?>
+ <div id="jp-disconnect" class="jp-disconnect">
+ <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>
+ </div>
+ <?php endif; ?>
+ <?php if ( $is_user_connected && !$is_master_user ) : ?>
+ <div id="jp-unlink" class="jp-disconnect">
+ <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>
+ </div>
+ <?php endif; ?>
</div>
<?php endif; ?>
<h3><?php _e( 'Jetpack by WordPress.com', 'jetpack' ) ?></h3>
@@ -1910,11 +2325,28 @@ p {
</div>
</div>
+ <?php elseif ( ! $is_user_connected ) : ?>
+
+ <div id="message" class="updated jetpack-message jp-connect">
+ <div class="jetpack-wrap-container">
+ <div class="jetpack-text-container">
+ <h4>
+ <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>
+ </h4>
+ </div>
+ <div class="jetpack-install-container">
+ <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>
+ </div>
+ </div>
+ </div>
+
+ <?php else /* blog and user are connected */ : ?>
+ <?php /* TODO: if not master user, show user disconnect button? */ ?>
<?php endif; ?>
<?php
// If we select the configure option for a module, show the configuration screen.
- if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) ) :
+ if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) :
$this->admin_screen_configure_module( $_GET['configure'] );
// List all the available modules.
@@ -1975,19 +2407,23 @@ p {
<a href="http://jetpack.me/" target="_blank">Jetpack <?php echo esc_html( JETPACK__VERSION ); ?></a> |
<a href="http://automattic.com/privacy/" target="_blank"><?php _e( 'Privacy Policy', 'jetpack' ); ?></a> |
<a href="http://wordpress.com/tos/" target="_blank"><?php _e( 'Terms of Service', 'jetpack' ); ?></a> |
+<?php if ( current_user_can( 'manage_options' ) ) : ?>
<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> |
+<?php endif; ?>
<a href="http://jetpack.me/support/" target="_blank"><?php _e( 'Support', 'jetpack' ); ?></a>
</p>
</div>
<div id="jetpack-configuration" style="display:none;">
- <p><img src="<?php echo esc_url( admin_url( 'images/wpspin_dark.gif' ) ); ?>" alt="Loading ..." /></p>
+ <p><img width="16" src="<?php echo esc_url( plugins_url( '_inc/images/wpspin_light-2x.gif', __FILE__ ) ); ?>" alt="Loading ..." /></p>
</div>
</div>
<?php
}
function ajax_debug() {
+ nocache_headers();
+
check_ajax_referer( 'jetpack_debug' );
if ( !current_user_can( 'manage_options' ) ) {
@@ -1997,18 +2433,31 @@ p {
<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>
<ul>
<?php
+ // Extract the current_user's token
+ $user_id = get_current_user_id();
+ $user_tokens = Jetpack::get_option( 'user_tokens' );
+ if ( is_array( $user_tokens ) && array_key_exists( $user_id, $user_tokens ) ) {
+ $user_token = $user_tokens[$user_id];
+ } else {
+ $user_token = '[this user has no token]';
+ }
+ unset( $user_tokens );
+
foreach ( array(
'CLIENT_ID' => 'id',
'BLOG_TOKEN' => 'blog_token',
- 'USER_TOKEN' => 'user_token',
+ 'MASTER_USER' => 'master_user',
'CERT' => 'fallback_no_verify_ssl_certs',
'TIME_DIFF' => 'time_diff',
'VERSION' => 'version',
'OLD_VERSION' => 'old_version',
+ 'PUBLIC' => 'public',
) as $label => $option_name ) :
?>
<li><?php echo esc_html( $label ); ?>: <code><?php echo esc_html( Jetpack::get_option( $option_name ) ); ?></code></li>
<?php endforeach; ?>
+ <li>USER_ID: <code><?php echo esc_html( $user_id ); ?></code></li>
+ <li>USER_TOKEN: <code><?php echo esc_html( $user_token ); ?></code></li>
<li>PHP_VERSION: <code><?php echo esc_html( PHP_VERSION ); ?></code></li>
<li>WORDPRESS_VERSION: <code><?php echo esc_html( $GLOBALS['wp_version'] ); ?></code></li>
</ul>
@@ -2017,7 +2466,7 @@ p {
}
function admin_screen_configure_module( $module_id ) {
- if ( !in_array( $module_id, $this->get_active_modules() ) )
+ if ( !in_array( $module_id, Jetpack::get_active_modules() ) || !current_user_can( 'manage_options' ) )
return false; ?>
<div id="jp-settings-screen" style="position: relative">
@@ -2033,7 +2482,7 @@ p {
</div><?php
}
- function sort_modules( $a, $b ) {
+ public static function sort_modules( $a, $b ) {
if ( $a['sort'] == $b['sort'] )
return 0;
@@ -2142,17 +2591,17 @@ p {
<div class="jetpack-module-actions">
<?php if ( $jetpack_connected ) : ?>
- <?php if ( !$activated ) : ?>
- <a href="<?php echo esc_url( $toggle_url ); ?>" class="jetpack-toggle-button<?php echo ( 'inactive' == $css ? ' button-primary' : ' button' ); ?>"><?php echo $toggle; ?></a>&nbsp;
+ <?php if ( !$activated && current_user_can( 'manage_options' ) && apply_filters( 'jetpack_can_activate_' . $module, true ) ) : ?>
+ <a href="<?php echo esc_url( $toggle_url ); ?>" class="<?php echo ( 'inactive' == $css ? ' button-primary' : ' button-secondary' ); ?>"><?php echo $toggle; ?></a>&nbsp;
<?php endif; ?>
<?php do_action( 'jetpack_learn_more_button_' . $module ) ?>
<?php
- if ( apply_filters( 'jetpack_module_configurable_' . $module, false ) ) {
- echo '<a href="' . esc_attr( Jetpack::module_configuration_url( $module ) ) . '" class="jetpack-configure-button button">' . __( 'Configure', 'jetpack' ) . '</a>';
+ if ( current_user_can( 'manage_options' ) && apply_filters( 'jetpack_module_configurable_' . $module, false ) ) {
+ echo '<a href="' . esc_attr( Jetpack::module_configuration_url( $module ) ) . '" class="jetpack-configure-button button-secondary">' . __( 'Configure', 'jetpack' ) . '</a>';
}
- ?><?php if ( $activated && $module_data['deactivate'] ) : ?><a style="display: none;" href="<?php echo esc_url( $toggle_url ); ?>" class="jetpack-deactivate-button button"><?php echo $toggle; ?></a>&nbsp;<?php endif; ?>
+ ?><?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; ?>
<?php else : ?>
<?php do_action( 'jetpack_learn_more_button_' . $module ) ?>
@@ -2197,9 +2646,9 @@ p {
exit;
}
- $this->load_xml_rpc_client();
+ Jetpack::load_xml_rpc_client();
$xml = new Jetpack_IXR_Client( array(
- 'user_id' => $GLOBALS['current_user']->ID
+ 'user_id' => JETPACK_MASTER_USER,
) );
$xml->query( 'jetpack.checkNewsSubscription' );
if ( $xml->isError() ) {
@@ -2215,9 +2664,9 @@ p {
exit;
}
- $this->load_xml_rpc_client();
+ Jetpack::load_xml_rpc_client();
$xml = new Jetpack_IXR_Client( array(
- 'user_id' => $GLOBALS['current_user']->ID
+ 'user_id' => JETPACK_MASTER_USER,
) );
$xml->query( 'jetpack.subscribeToNews' );
if ( $xml->isError() ) {
@@ -2233,17 +2682,16 @@ p {
/**
* Returns the requested Jetpack API URL
*
- * @static
* @return string
*/
- function api_url( $relative_url ) {
+ public static function api_url( $relative_url ) {
return trailingslashit( JETPACK__API_BASE . $relative_url ) . JETPACK__API_VERSION . '/';
}
/**
* Some hosts disable the OpenSSL extension and so cannot make outgoing HTTPS requsets
*/
- function fix_url_for_bad_hosts( $url, &$args ) {
+ public static function fix_url_for_bad_hosts( $url, &$args ) {
if ( 0 !== strpos( $url, 'https://' ) ) {
return $url;
}
@@ -2270,19 +2718,17 @@ p {
/**
* Returns the Jetpack XML-RPC API
*
- * @static
* @return string
*/
- function xmlrpc_api_url() {
+ public static function xmlrpc_api_url() {
$base = preg_replace( '#(https?://[^?/]+)(/?.*)?$#', '\\1', JETPACK__API_BASE );
return untrailingslashit( $base ) . '/xmlrpc.php';
}
/**
- * @static
* @return bool|WP_Error
*/
- function register() {
+ public static function register() {
Jetpack::update_option( 'register', wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 ) );
@list( $secret_1, $secret_2, $secret_eol ) = explode( ':', Jetpack::get_option( 'register' ) );
@@ -2337,24 +2783,38 @@ p {
$code_type = intval( $code / 100 );
if ( 5 == $code_type ) {
- return new Jetpack_error( 'wpcom_5??', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
+ return new Jetpack_Error( 'wpcom_5??', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
} elseif ( 408 == $code ) {
- return new Jetpack_error( 'wpcom_408', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
+ return new Jetpack_Error( 'wpcom_408', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
} elseif ( !empty( $json->error ) ) {
$error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
return new Jetpack_Error( (string) $json->error, $error_description, $code );
} elseif ( 200 != $code ) {
- return new Jetpack_error( 'wpcom_bad_response', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
+ return new Jetpack_Error( 'wpcom_bad_response', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
+ }
+
+ // Jetpack ID error block
+ if ( empty( $json->jetpack_id ) ) {
+ return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is empty. Do not publicly post this error message! %s', 'jetpack' ), $entity ), $entity );
+ } elseif ( ! is_scalar( $json->jetpack_id ) ) {
+ 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 );
+ } elseif ( preg_match( '/[^0-9]/', $json->jetpack_id ) ) {
+ 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);
}
- if ( empty( $json->jetpack_id ) || !is_scalar( $json->jetpack_id ) || preg_match( '/[^0-9]/', $json->jetpack_id ) )
- return new Jetpack_Error( 'jetpack_id', '', $code );
if ( empty( $json->jetpack_secret ) || !is_string( $json->jetpack_secret ) )
return new Jetpack_Error( 'jetpack_secret', '', $code );
+ if ( isset( $json->jetpack_public ) ) {
+ $jetpack_public = (int) $json->jetpack_public;
+ } else {
+ $jetpack_public = false;
+ }
+
Jetpack::update_options( array(
'id' => (int) $json->jetpack_id,
'blog_token' => (string) $json->jetpack_secret,
+ 'public' => $jetpack_public,
) );
return true;
@@ -2366,23 +2826,21 @@ p {
/**
* Loads the Jetpack XML-RPC client
*/
- function load_xml_rpc_client() {
+ public static function load_xml_rpc_client() {
require_once ABSPATH . WPINC . '/class-IXR.php';
require_once dirname( __FILE__ ) . '/class.jetpack-ixr-client.php';
}
/**
- * Authenticates XML-RPC requests from the Jetpack Server
- *
- * We don't actually know who the real user is; we set it to the account that created the connection.
+ * Authenticates XML-RPC and other requests from the Jetpack Server
*/
- function authenticate_xml_rpc( $user, $username, $password ) {
+ function authenticate_jetpack( $user, $username, $password ) {
if ( is_a( $user, 'WP_User' ) ) {
return $user;
}
// It's not for us
- if ( !isset( $_GET['for'] ) || 'jetpack' != $_GET['for'] || !isset( $_GET['token'] ) || empty( $_GET['signature'] ) ) {
+ if ( !isset( $_GET['token'] ) || empty( $_GET['signature'] ) ) {
return $user;
}
@@ -2409,7 +2867,34 @@ p {
require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
$jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
- $signature = $jetpack_signature->sign_current_request( array( 'body' => $this->HTTP_RAW_POST_DATA ) );
+ if ( isset( $_POST['_jetpack_is_multipart'] ) ) {
+ $post_data = $_POST;
+ $file_hashes = array();
+ foreach ( $post_data as $post_data_key => $post_data_value ) {
+ if ( 0 !== strpos( $post_data_key, '_jetpack_file_hmac_' ) ) {
+ continue;
+ }
+ $post_data_key = substr( $post_data_key, strlen( '_jetpack_file_hmac_' ) );
+ $file_hashes[$post_data_key] = $post_data_value;
+ }
+
+ foreach ( $file_hashes as $post_data_key => $post_data_value ) {
+ unset( $post_data["_jetpack_file_hmac_{$post_data_key}"] );
+ $post_data[$post_data_key] = $post_data_value;
+ }
+
+ ksort( $post_data );
+
+ $body = http_build_query( stripslashes_deep( $post_data ) );
+ } elseif ( is_null( $this->HTTP_RAW_POST_DATA ) ) {
+ $body = file_get_contents( 'php://input' );
+ } else {
+ $body = null;
+ }
+ $signature = $jetpack_signature->sign_current_request( array(
+ 'body' => is_null( $body ) ? $this->HTTP_RAW_POST_DATA : $body
+ ) );
+
if ( !$signature ) {
return $user;
} else if ( is_wp_error( $signature ) ) {
@@ -2418,7 +2903,10 @@ p {
return $user;
}
- if ( !$this->add_nonce( $_GET['timestamp'], $_GET['nonce'] ) ) {
+ $timestamp = (int) $_GET['timestamp'];
+ $nonce = stripslashes( (string) $_GET['nonce'] );
+
+ if ( !$this->add_nonce( $timestamp, $nonce ) ) {
return $user;
}
@@ -2429,8 +2917,15 @@ p {
function add_nonce( $timestamp, $nonce ) {
global $wpdb;
+ static $nonces_used_this_request = array();
+
+ if ( isset( $nonces_used_this_request["$timestamp:$nonce"] ) ) {
+ return $nonces_used_this_request["$timestamp:$nonce"];
+ }
// This should always have gone through Jetpack_Signature::sign_request() first to check $timestamp an $nonce
+ $timestamp = (int) $timestamp;
+ $nonce = $wpdb->escape( $nonce );
// Raw query so we can avoid races: add_option will also update
$show_errors = $wpdb->show_errors( false );
@@ -2441,6 +2936,9 @@ p {
'no'
) );
$wpdb->show_errors( $show_errors );
+
+ $nonces_used_this_request["$timestamp:$nonce"] = $return;
+
return $return;
}
@@ -2453,7 +2951,22 @@ p {
return $methods;
}
- function clean_nonces( $all = false ) {
+ function xmlrpc_options( $options ) {
+ $options['jetpack_version'] = array(
+ 'desc' => __( 'Jetpack Plugin Version' , 'jetpack'),
+ 'readonly' => true,
+ 'value' => JETPACK__VERSION,
+ );
+
+ $options['jetpack_client_id'] = array(
+ 'desc' => __( 'The Client ID/WP.com Blog ID of this site' , 'jetpack'),
+ 'readonly' => true,
+ 'value' => Jetpack::get_option( 'id' ),
+ );
+ return $options;
+ }
+
+ public static function clean_nonces( $all = false ) {
global $wpdb;
$sql = "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE %s";
@@ -2464,7 +2977,15 @@ p {
$sql_args[] = time() - 3600;
}
- $wpdb->query( $wpdb->prepare( $sql, $sql_args ) );
+ $sql .= ' LIMIT 100';
+
+ $sql = $wpdb->prepare( $sql, $sql_args );
+
+ for ( $i = 0; $i < 1000; $i++ ) {
+ if ( !$wpdb->query( $sql ) ) {
+ break;
+ }
+ }
}
/**
@@ -2475,10 +2996,8 @@ p {
* @param string $key
* @param string $value
* @param bool $restate private
- *
- * @static
*/
- function state( $key = null, $value = null, $restate = false ) {
+ public static function state( $key = null, $value = null, $restate = false ) {
static $state = array();
static $path, $domain;
if ( !isset( $path ) ) {
@@ -2526,17 +3045,50 @@ p {
}
}
- /**
- * @static
- */
- function restate() {
+ public static function restate() {
Jetpack::state( null, null, true );
}
+ public static function check_privacy( $file ) {
+ static $is_site_publicly_accessible = null;
+
+ if ( is_null( $is_site_publicly_accessible ) ) {
+ $is_site_publicly_accessible = false;
+
+ Jetpack::load_xml_rpc_client();
+ $rpc = new Jetpack_IXR_Client();
+
+ $success = $rpc->query( 'jetpack.isSitePubliclyAccessible', home_url() );
+ if ( $success ) {
+ $response = $rpc->getResponse();
+ if ( $response ) {
+ $is_site_publicly_accessible = true;
+ }
+ }
+
+ Jetpack::update_option( 'public', (int) $is_site_publicly_accessible );
+ }
+
+ if ( $is_site_publicly_accessible ) {
+ return;
+ }
+
+ $module_slug = self::get_module_slug( $file );
+
+ $privacy_checks = Jetpack::state( 'privacy_checks' );
+ if ( !$privacy_checks ) {
+ $privacy_checks = $module_slug;
+ } else {
+ $privacy_checks .= ",$module_slug";
+ }
+
+ Jetpack::state( 'privacy_checks', $privacy_checks );
+ }
+
/**
* Helper method for multicall XMLRPC.
*/
- function xmlrpc_async_call() {
+ public static function xmlrpc_async_call() {
global $blog_id;
static $clients = array();
@@ -2545,7 +3097,7 @@ p {
if ( !isset( $clients[$client_blog_id] ) ) {
Jetpack::load_xml_rpc_client();
$clients[$client_blog_id] = new Jetpack_IXR_ClientMulticall( array(
- 'user_id' => get_current_user_id()
+ 'user_id' => JETPACK_MASTER_USER,
) );
ignore_user_abort( true );
add_action( 'shutdown', array( 'Jetpack', 'xmlrpc_async_call' ) );
@@ -2579,7 +3131,12 @@ p {
}
}
- function staticize_subdomain( $url ) {
+ public static function staticize_subdomain( $url ) {
+ $host = parse_url( $url, PHP_URL_HOST );
+ if ( !preg_match( '/.?(?:wordpress|wp)\.com$/', $host ) ) {
+ return $url;
+ }
+
if ( is_ssl() ) {
return preg_replace( '|https?://[^/]++/|', 'https://s-ssl.wordpress.com/', $url );
}
@@ -2590,16 +3147,149 @@ p {
return preg_replace( '|://[^/]+?/|', "://s$static_counter.wp.com/", $url );
}
+
+/* JSON API Authorization */
+
+ /**
+ * Handles the login action for Authorizing the JSON API
+ */
+ function login_form_json_api_authorization() {
+ $this->verify_json_api_authorization_request();
+
+ add_action( 'wp_login', array( &$this, 'store_json_api_authorization_token' ), 10, 2 );
+
+ add_action( 'login_message', array( &$this, 'login_message_json_api_authorization' ) );
+ add_action( 'login_form', array( &$this, 'preserve_action_in_login_form_for_json_api_authorization' ) );
+ add_filter( 'site_url', array( &$this, 'post_login_form_to_signed_url' ), 10, 3 );
+ }
+
+ // Make sure the login form is POSTed to the signed URL so we can reverify the request
+ function post_login_form_to_signed_url( $url, $path, $scheme ) {
+ if ( 'wp-login.php' !== $path || 'login_post' !== $scheme ) {
+ return $url;
+ }
+
+ return "$url?{$_SERVER['QUERY_STRING']}";
+ }
+
+ // Make sure the POSTed request is handled by the same action
+ function preserve_action_in_login_form_for_json_api_authorization() {
+ echo "<input type='hidden' name='action' value='jetpack_json_api_authorization' />\n";
+ }
+
+ // If someone logs in to approve API access, store the Access Code in usermeta
+ function store_json_api_authorization_token( $user_login, $user ) {
+ add_filter( 'login_redirect', array( &$this, 'add_token_to_login_redirect_json_api_authorization' ), 10, 3 );
+ add_filter( 'allowed_redirect_hosts', array( &$this, 'allow_wpcom_public_api_domain' ) );
+ $token = wp_generate_password( 32, false );
+ update_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], $token );
+ }
+
+ // Add public-api.wordpress.com to the safe redirect whitelist - only added when someone allows API access
+ function allow_wpcom_public_api_domain( $domains ) {
+ $domains[] = 'public-api.wordpress.com';
+ return $domains;
+ }
+
+ // Add the Access Code details to the public-api.wordpress.com redirect
+ function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) {
+ return add_query_arg( urlencode_deep( array(
+ 'jetpack-code' => get_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], true ),
+ 'jetpack-user-id' => (int) $user->ID,
+ 'jetpack-state' => $this->json_api_authorization_request['state'],
+ ) ), $redirect_to );
+ }
+
+ // Verifies the request by checking the signature
+ function verify_json_api_authorization_request() {
+ require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
+
+ $token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
+ if ( !$token || empty( $token->secret ) ) {
+ wp_die( __( 'You must connect your Jetpack plugin to WordPress.com to use this feature.' , 'jetpack') );
+ }
+
+ $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' );
+
+ $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
+ $signature = $jetpack_signature->sign_current_request( array( 'body' => null, 'method' => 'GET' ) );
+ if ( !$signature ) {
+ wp_die( $die_error );
+ } else if ( is_wp_error( $signature ) ) {
+ wp_die( $die_error );
+ } else if ( $signature !== $_GET['signature'] ) {
+ if ( is_ssl() ) {
+ // 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
+ $signature = $jetpack_signature->sign_current_request( array( 'scheme' => 'http', 'body' => null, 'method' => 'GET' ) );
+ if ( !$signature || is_wp_error( $signature ) || $signature !== $_GET['signature'] ) {
+ wp_die( $die_error );
+ }
+ } else {
+ wp_die( $die_error );
+ }
+ }
+
+ $timestamp = (int) $_GET['timestamp'];
+ $nonce = stripslashes( (string) $_GET['nonce'] );
+
+ if ( !$this->add_nonce( $timestamp, $nonce ) ) {
+ // De-nonce the nonce, at least for 5 minutes.
+ // 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)
+ $old_nonce_time = get_option( "jetpack_nonce_{$timestamp}_{$nonce}" );
+ if ( $old_nonce_time < time() - 300 ) {
+ wp_die( __( 'The authorization process expired. Please go back and try again.' , 'jetpack') );
+ }
+ }
+
+ $data = json_decode( base64_decode( stripslashes( $_GET['data'] ) ) );
+ $data_filters = array(
+ 'state' => 'opaque',
+ 'client_id' => 'int',
+ 'client_title' => 'string',
+ 'client_image' => 'url',
+ );
+
+ foreach ( $data_filters as $key => $sanitation ) {
+ if ( !isset( $data->$key ) ) {
+ wp_die( $die_error );
+ }
+
+ switch ( $sanitation ) {
+ case 'int' :
+ $this->json_api_authorization_request[$key] = (int) $data->$key;
+ break;
+ case 'opaque' :
+ $this->json_api_authorization_request[$key] = (string) $data->$key;
+ break;
+ case 'string' :
+ $this->json_api_authorization_request[$key] = wp_kses( (string) $data->$key, array() );
+ break;
+ case 'url' :
+ $this->json_api_authorization_request[$key] = esc_url_raw( (string) $data->$key );
+ break;
+ }
+ }
+
+ if ( empty( $this->json_api_authorization_request['client_id'] ) ) {
+ wp_die( $die_error );
+ }
+ }
+
+ function login_message_json_api_authorization( $message ) {
+ return '<p class="message">' . sprintf(
+ esc_html__( '%s wants to access your site&#8217;s data. Log in to authorize that access.' , 'jetpack'),
+ '<strong>' . esc_html( $this->json_api_authorization_request['client_title'] ) . '</strong>'
+ ) . '<img src="' . esc_url( $this->json_api_authorization_request['client_image'] ) . '" /></p>';
+ }
}
class Jetpack_Client {
/**
* Makes an authorized remote request using Jetpack_Signature
*
- * @static
* @return array|WP_Error WP HTTP response on success
*/
- function remote_request( $args, $body = null ) {
+ public static function remote_request( $args, $body = null ) {
$defaults = array(
'url' => '',
'user_id' => 0,
@@ -2612,14 +3302,13 @@ class Jetpack_Client {
$args = wp_parse_args( $args, $defaults );
- $args['user_id'] = (int) $args['user_id'];
$args['blog_id'] = (int) $args['blog_id'];
if ( 'header' != $args['auth_location'] ) {
$args['auth_location'] = 'query_string';
}
- $token = Jetpack_Data::get_access_token( $args );
+ $token = Jetpack_Data::get_access_token( $args['user_id'] );
if ( !$token ) {
return new Jetpack_Error( 'missing_token' );
}
@@ -2715,10 +3404,9 @@ class Jetpack_Client {
* @todo: Better fallbacks (bundled certs?), feedback, UI, ....
* @see Jetpack::fix_url_for_bad_hosts()
*
- * @static
* @return array|WP_Error WP HTTP response on success
*/
- function _wp_remote_request( $url, $args, $set_fallback = false ) {
+ public static function _wp_remote_request( $url, $args, $set_fallback = false ) {
$fallback = Jetpack::get_option( 'fallback_no_verify_ssl_certs' );
if ( false === $fallback ) {
Jetpack::update_option( 'fallback_no_verify_ssl_certs', 0 );
@@ -2777,7 +3465,7 @@ class Jetpack_Client {
return $response;
}
- function set_time_diff( &$response, $force_set = false ) {
+ public static function set_time_diff( &$response, $force_set = false ) {
$code = wp_remote_retrieve_response_code( $response );
// Only trust the Date header on some responses
@@ -2810,23 +3498,28 @@ class Jetpack_Data {
/**
* Gets locally stored token
*
- * @static
* @return object|false
*/
- function get_access_token( $args ) {
- if ( is_numeric( $args ) ) {
- $args = array( 'user_id' => $args );
- }
-
- if ( $args['user_id'] ) {
- if ( !$token = Jetpack::get_option( 'user_token' ) ) {
+ public static function get_access_token( $user_id = false ) {
+ if ( $user_id ) {
+ if ( !$tokens = Jetpack::get_option( 'user_tokens' ) ) {
+ return false;
+ }
+ if ( $user_id === JETPACK_MASTER_USER ) {
+ if ( !$user_id = Jetpack::get_option( 'master_user' ) ) {
+ return false;
+ }
+ }
+ if ( !isset( $tokens[$user_id] ) || !$token = $tokens[$user_id] ) {
return false;
}
$token_chunks = explode( '.', $token );
if ( empty( $token_chunks[1] ) || empty( $token_chunks[2] ) ) {
return false;
}
- $args['user_id'] = $token_chunks[2];
+ if ( $user_id != $token_chunks[2] ) {
+ return false;
+ }
$token = "{$token_chunks[0]}.{$token_chunks[1]}";
} else {
$token = Jetpack::get_option( 'blog_token' );
@@ -2837,7 +3530,7 @@ class Jetpack_Data {
return (object) array(
'secret' => $token,
- 'external_user_id' => (int) $args['user_id'],
+ 'external_user_id' => (int) $user_id,
);
}
}
@@ -2854,6 +3547,8 @@ class Jetpack_Client_Server {
$args = array();
+ $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
+
do {
$jetpack = Jetpack::init();
$role = $jetpack->translate_current_user_to_role();
@@ -2868,7 +3563,7 @@ class Jetpack_Client_Server {
break;
}
- check_admin_referer( "jetpack-authorize_$role" );
+ check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
if ( !empty( $data['error'] ) ) {
Jetpack::state( 'error', $data['error'] );
@@ -2914,8 +3609,18 @@ class Jetpack_Client_Server {
break;
}
- Jetpack::update_option( 'user_token', sprintf( '%s.%d', $token, $current_user_id ), true );
- Jetpack::state( 'message', 'authorized' );
+ $is_master_user = ! Jetpack::is_active();
+
+ Jetpack::update_user_token( $current_user_id, sprintf( '%s.%d', $token, $current_user_id ), $is_master_user );
+
+
+ if ( $is_master_user ) {
+ Jetpack::state( 'message', 'authorized' );
+ } else {
+ Jetpack::state( 'message', 'linked' );
+ // Don't activate anything since we are just connecting a user.
+ break;
+ }
if ( $active_modules = Jetpack::get_option( 'active_modules' ) ) {
Jetpack::delete_option( 'active_modules' );
@@ -2925,16 +3630,23 @@ class Jetpack_Client_Server {
Jetpack::activate_default_modules();
}
+ $jetpack->sync->register( 'noop' ); // Spawn a sync to make sure the Jetpack Servers know what modules are active.
+
// Start nonce cleaner
wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
} while ( false );
- wp_safe_redirect( Jetpack::admin_url() );
+ if ( wp_validate_redirect( $redirect ) ) {
+ wp_safe_redirect( $redirect );
+ } else {
+ wp_safe_redirect( Jetpack::admin_url() );
+ }
+
exit;
}
- function deactivate_plugin( $probable_file, $probable_title ) {
+ public static function deactivate_plugin( $probable_file, $probable_title ) {
if ( is_plugin_active( $probable_file ) ) {
deactivate_plugins( $probable_file );
return 1;
@@ -2964,11 +3676,13 @@ class Jetpack_Client_Server {
return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
}
- $client_secret = Jetpack_Data::get_access_token( 0 );
+ $client_secret = Jetpack_Data::get_access_token();
if ( !$client_secret ) {
return new Jetpack_Error( 'client_secret', __( 'You need to register your Jetpack before connecting it.', 'jetpack' ) );
}
+ $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
+
$body = array(
'client_id' => Jetpack::get_option( 'id' ),
'client_secret' => $client_secret->secret,
@@ -2976,7 +3690,8 @@ class Jetpack_Client_Server {
'code' => $data['code'],
'redirect_uri' => add_query_arg( array(
'action' => 'authorize',
- '_wpnonce' => wp_create_nonce( "jetpack-authorize_$role" ),
+ '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
+ 'redirect' => $redirect ? urlencode( $redirect ) : false,
), menu_page_url( 'jetpack', false ) ),
);
@@ -3044,64 +3759,119 @@ class Jetpack_Client_Server {
* Jetpack server for remote processing/notifications/etc
*/
class Jetpack_Sync {
- var $sync = array();
+ // What modules want to sync what content
+ var $sync_conditions = array( 'posts' => array(), 'comments' => array() );
+
+ // We keep track of all the options registered for sync so that we can sync them all if needed
+ var $sync_options = array();
+
+ // 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.
var $post_transitions = array();
+ var $comment_transitions = array();
+
+ // Objects to sync
+ var $sync = array();
- function Jetpack_Sync() {
- add_action( 'transition_post_status', array( $this, 'track_post_transition' ), 1, 3 );
+ function __construct() {
+ // WP Cron action. Only used on upgrade
+ add_action( 'jetpack_sync_all_registered_options', array( $this, 'sync_all_registered_options' ) );
}
- function track_post_transition( $new_status, $old_status, $post ) {
- if ( empty( $post->ID ) ) {
- return;
- }
+/* Static Methods for Modules */
- if ( isset( $this->post_transitions[$post->ID] ) ) {
- $this->post_transitions[$post->ID][0] = $new_status;
- return;
- }
+ /**
+ * @param string $file __FILE__
+ * @param array settings:
+ * post_types => array( post_type slugs ): The post types to sync. Default: post, page
+ * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
+ */
+ static function sync_posts( $file, array $settings = null ) {
+ $jetpack = Jetpack::init();
+ $args = func_get_args();
+ return call_user_func_array( array( $jetpack->sync, 'posts' ), $args );
+ }
- $this->post_transitions[$post->ID] = array( $new_status, $old_status );
+ /**
+ * @param string $file __FILE__
+ * @param array settings:
+ * post_types => array( post_type slugs ): The post types to sync. Default: post, page
+ * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
+ * comment_types => array( comment_type slugs ): The comment types to sync. Default: '', comment, trackback, pingback
+ * comment_stati => array( comment_status slugs ): The comment stati to sync. Default: approved
+ */
+ static function sync_comments( $file, array $settings = null ) {
+ $jetpack = Jetpack::init();
+ $args = func_get_args();
+ return call_user_func_array( array( $jetpack->sync, 'comments' ), $args );
+ }
+
+ /**
+ * @param string $file __FILE__
+ * @param string $option, Option name to sync
+ * @param string $option ...
+ */
+ static function sync_options( $file, $option /*, $option, ... */ ) {
+ $jetpack = Jetpack::init();
+ $args = func_get_args();
+ return call_user_func_array( array( $jetpack->sync, 'options' ), $args );
}
+/* Internal Methods */
+
/**
* Create a sync object/request
*
- * @param string $object Type of object to sync -- [ post | comment ]
+ * @param string $object Type of object to sync -- [ post | comment | option ]
* @param int $id Unique identifier
- * @param array $specifics Specific fields/elements of that object to sync. Defaults to syncing all data for the $object
+ * @param array $settings
*/
- function register( $object, $id = false, $specifics = true ) {
+ function register( $object, $id = false, array $settings = null ) {
// Since we've registered something for sync, hook it up to execute on shutdown if we haven't already
if ( !$this->sync ) {
ignore_user_abort( true );
add_action( 'shutdown', array( $this, 'sync' ), 9 ); // Right before async XML-RPC
}
- $this->add_to_array( $this->sync, $object, $id, $specifics );
- return true;
- }
+ $defaults = array(
+ 'on_behalf_of' => array(), // What modules want this data
+ );
+ $settings = wp_parse_args( $settings, $defaults );
- function add_to_array( &$array, $object, $id, $data ) {
- if ( !isset( $array[$object] ) ) {
- $array[$object] = array( $id => $data );
- } else if ( !isset( $array[$object][$id] ) ) {
- $array[$object][$id] = $data;
+ if ( !isset( $this->sync[$object] ) ) {
+ $this->sync[$object] = array();
+ }
+
+ // Store the settings for this object
+ if (
+ // First time for this object
+ !isset( $this->sync[$object][$id] )
+ ) {
+ // Easy: store the current settings
+ $this->sync[$object][$id] = $settings;
} else {
- if ( true === $array[$object][$id] || true === $data )
- $array[$object][$id] = true;
- else
- $array[$object][$id] = array_merge( $array[$object][$id], $data );
+ // Not as easy: we have to manually merge the settings from previous runs for this object with the settings for this run
+
+ $this->sync[$object][$id]['on_behalf_of'] = array_unique( array_merge( $this->sync[$object][$id]['on_behalf_of'], $settings['on_behalf_of'] ) );
}
- }
- /**
- * Set up all the data and queue it for the outgoing XML-RPC request
- */
- function sync() {
- global $wpdb;
- $jetpack = Jetpack::init();
+ $delete_prefix = 'delete_';
+ if ( 0 === strpos( $object, $delete_prefix ) ) {
+ $unset_object = substr( $object, strlen( $delete_prefix ) );
+ } else {
+ $unset_object = "{$delete_prefix}{$object}";
+ }
+
+ // Ensure post ... delete_post yields a delete operation
+ // Ensure delete_post ... post yields a sync post operation
+ // Ensure update_option() ... delete_option() ends up as a delete
+ // Ensure delete_option() ... update_option() ends up as an update
+ // Etc.
+ unset( $this->sync[$unset_object][$id] );
+
+ return true;
+ }
+ function get_common_sync_data() {
$available_modules = Jetpack::get_available_modules();
$active_modules = Jetpack::get_active_modules();
$modules = array();
@@ -3110,174 +3880,599 @@ class Jetpack_Sync {
}
$modules['vaultpress'] = class_exists( 'VaultPress' ) || function_exists( 'vaultpress_contact_service' );
- $sync_data = compact( 'modules' );
-
- if ( count( $this->sync ) ) {
- foreach ( $this->sync as $obj => $data ) {
- switch ( $obj ) {
- case 'post':
- $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
- $GLOBALS['post'] = null;
- foreach ( $data as $post => $columns ) {
- $sync_data['post'][$post] = $jetpack->get_post( $post, $columns );
- if ( isset( $this->post_transitions[$post] ) ) {
- $sync_data['post'][$post]['transitions'] = $this->post_transitions[$post];
- } else {
- $sync_data['post'][$post]['transitions'] = array( false, false );
- }
- }
- $GLOBALS['post'] = $global_post;
- unset( $global_post );
- break;
+ $sync_data = array(
+ 'modules' => $modules,
+ 'version' => JETPACK__VERSION,
+ );
- case 'delete_post':
- foreach ( $data as $post => $true ) {
- $sync_data['delete_post'][$post] = true;
- }
- break;
+ return $sync_data;
+ }
- case 'comment':
- $global_comment = isset( $GLOBALS['comment'] ) ? $GLOBALS['comment'] : null;
- unset( $GLOBALS['comment'] );
- foreach ( $data as $comment => $columns ) {
- $sync_data['comment'][$comment] = $jetpack->get_comment( $comment, $columns );
- }
- $GLOBALS['comment'] = $global_comment;
- unset( $global_comment );
- break;
+ /**
+ * Set up all the data and queue it for the outgoing XML-RPC request
+ */
+ function sync() {
+ if ( !$this->sync ) {
+ return false;
+ }
- case 'delete_comment':
- foreach ( $data as $comment => $true ) {
- $sync_data['delete_comment'][$comment] = true;
- }
- break;
+ $sync_data = $this->get_common_sync_data();
- case 'tag':
- foreach ( $data as $taxonomy => $columns ) {
- $sync_data['tag'][$taxonomy] = $jetpack->get_taxonomy( $taxonomy, $columns, 'post_tag' );
- }
- break;
+ $wp_importing = defined( 'WP_IMPORTING' ) && WP_IMPORTING;
- case 'delete_tag':
- foreach ( $data as $taxonomy => $columns ) {
- $sync_data['delete_tag'][$taxonomy] = $columns;
- }
+ foreach ( $this->sync as $sync_operation_type => $sync_operations ) {
+ switch ( $sync_operation_type ) {
+ case 'post':
+ if ( $wp_importing ) {
break;
+ }
- case 'category':
- foreach ( $data as $taxonomy => $columns ) {
- $sync_data['category'][$taxonomy] = $jetpack->get_taxonomy( $taxonomy, $columns, 'category' );
+ $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
+ $GLOBALS['post'] = null;
+ foreach ( $sync_operations as $post_id => $settings ) {
+ $sync_data['post'][$post_id] = $this->get_post( $post_id );
+ if ( isset( $this->post_transitions[$post_id] ) ) {
+ $sync_data['post'][$post_id]['transitions'] = $this->post_transitions[$post_id];
+ } else {
+ $sync_data['post'][$post_id]['transitions'] = array( false, false );
}
+ $sync_data['post'][$post_id]['on_behalf_of'] = $settings['on_behalf_of'];
+ }
+ $GLOBALS['post'] = $global_post;
+ unset( $global_post );
+ break;
+ case 'comment':
+ if ( $wp_importing ) {
break;
+ }
- case 'delete_category':
- foreach ( $data as $taxonomy => $columns ) {
- $sync_data['delete_category'][$taxonomy] = $columns;
+ $global_comment = isset( $GLOBALS['comment'] ) ? $GLOBALS['comment'] : null;
+ unset( $GLOBALS['comment'] );
+ foreach ( $sync_operations as $comment_id => $settings ) {
+ $sync_data['comment'][$comment_id] = $this->get_comment( $comment_id );
+ if ( isset( $this->comment_transitions[$comment_id] ) ) {
+ $sync_data['comment'][$comment_id]['transitions'] = $this->comment_transitions[$comment_id];
+ } else {
+ $sync_data['comment'][$comment_id]['transitions'] = array( false, false );
}
- break;
+ $sync_data['comment'][$comment_id]['on_behalf_of'] = $settings['on_behalf_of'];
}
- }
+ $GLOBALS['comment'] = $global_comment;
+ unset( $global_comment );
+ break;
+ case 'option' :
+ foreach ( $sync_operations as $option => $settings ) {
+ $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
+ }
+ break;
- Jetpack::xmlrpc_async_call( 'jetpack.syncContent', $sync_data );
+ case 'delete_post':
+ case 'delete_comment':
+ foreach ( $sync_operations as $object_id => $settings ) {
+ $sync_data[$sync_operation_type][$object_id] = array( 'on_behalf_of' => $settings['on_behalf_of'] );
+ }
+ break;
+ case 'delete_option' :
+ foreach ( $sync_operations as $object_id => $settings ) {
+ $sync_data[$sync_operation_type][$object_id] = true;
+ }
+ break;
+ }
}
+
+ Jetpack::xmlrpc_async_call( 'jetpack.syncContent', $sync_data );
}
- function taxonomy( $slug, $fields = true, $type ) {
- if ( !get_term_by( 'slug', $slug, $type ) ) {
- return false;
+ /**
+ * Format and return content data from a direct xmlrpc request for it.
+ *
+ * @param array $content_ids: array( 'posts' => array of ids, 'comments' => array of ids, 'options' => array of options )
+ */
+ function get_content( $content_ids ) {
+ $sync_data = $this->get_common_sync_data();
+
+ if ( isset( $content_ids['posts'] ) ) {
+ foreach ( $content_ids['posts'] as $id ) {
+ $sync_data['post'][$id] = $this->get_post( $id );
+ }
}
- if ( 'post_tag' == $type )
- return $this->register( 'tag', $slug, $fields );
- else
- return $this->register( 'category', $slug, $fields );
+ if ( isset( $content_ids['comments'] ) ) {
+ foreach ( $content_ids['comments'] as $id ) {
+ $sync_data['comment'][$id] = $this->get_post( $id );
+ }
+ }
+
+ if ( isset( $content_ids['options'] ) ) {
+ foreach ( $content_ids['options'] as $option ) {
+ $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
+ }
+ }
+
+ return $sync_data;
}
/**
- * Request that a post be deleted remotely
+ * Helper method for registering a post for sync
*
- * @param int $id The post_ID
+ * @param int $id wp_posts.ID
+ * @param array $settings Sync data
*/
- function delete_taxonomy( $slugs, $type ) {
- if ( 'post_tag' == $type )
- return $this->register( 'delete_tag', 1, $slugs );
- else
- return $this->register( 'delete_category', 1, $slugs );
+ function register_post( $id, array $settings = null ) {
+ $id = (int) $id;
+ if ( !$id ) {
+ return false;
+ }
+
+ $post = get_post( $id );
+ if ( !$post ) {
+ return false;
+ }
+
+ $settings = wp_parse_args( $settings, array(
+ 'on_behalf_of' => array(),
+ ) );
+
+ return $this->register( 'post', $id, $settings );
}
/**
- * Helper method for easily requesting a sync of a post.
+ * Helper method for registering a comment for sync
*
- * @param int $id wp_posts.ID
- * @param array $fields Array containing field/column names to sync (optional, defaults to all fields)
+ * @param int $id wp_comments.comment_ID
+ * @param array $settings Sync data
*/
- function post( $id, $fields = true ) {
- if ( !$id = (int) $id ) {
+ function register_comment( $id, array $settings = null ) {
+ $id = (int) $id;
+ if ( !$id ) {
return false;
}
- if ( false === $fields ) {
- $fields = array( '_jetpack_backfill' );
- }
- if ( is_array( $fields ) ) {
- $fields = array_merge( $fields, array( 'ID', 'post_title', 'post_name', 'guid', 'post_date', 'post_date_gmt', 'post_parent', 'post_type', 'post_status' ) );
+ $comment = get_comment( $id );
+ if ( !$comment || empty( $comment->comment_post_ID ) ) {
+ return false;
}
- if ( !$post = get_post( $id ) ) {
+ $post = get_post( $comment->comment_post_ID );
+ if ( !$post ) {
return false;
}
- if (
- !empty( $post->post_password )
- ||
- !in_array( $post->post_type, get_post_types( array( 'public' => true ) ) )
- ||
- !in_array( $post->post_status, get_post_stati( array( 'public' => true ) ) )
- ) {
+ $settings = wp_parse_args( $settings, array(
+ 'on_behalf_of' => array(),
+ ) );
+
+ return $this->register( 'comment', $id, $settings );
+ }
+
+/* Posts Sync */
+
+ function posts( $file, array $settings = null ) {
+ $module_slug = Jetpack::get_module_slug( $file );
+
+ $defaults = array(
+ 'post_types' => array( 'post', 'page' ),
+ 'post_stati' => array( 'publish' ),
+ );
+
+ $this->sync_conditions['posts'][$module_slug] = wp_parse_args( $settings, $defaults );
+
+ add_action( 'transition_post_status', array( $this, 'transition_post_status_action' ), 10, 3 );
+ add_action( 'delete_post', array( $this, 'delete_post_action' ) );
+ }
+
+ function delete_post_action( $post_id ) {
+ $post = get_post( $post_id );
+ if ( !$post ) {
+ return $this->register( 'delete_post', (int) $post_id );
+ }
+
+ $this->transition_post_status_action( 'delete', $post->post_status, $post );
+ }
+
+ function transition_post_status_action( $new_status, $old_status, $post ) {
+ $sync = $this->get_post_sync_operation( $new_status, $old_status, $post, $this->sync_conditions['posts'] );
+ if ( !$sync ) {
+ // No module wants to sync this post
return false;
}
- return $this->register( 'post', (int) $id, $fields );
+ // Track post transitions
+ if ( isset( $this->post_transitions[$post->ID] ) ) {
+ // status changed more than once - keep tha most recent $new_status
+ $this->post_transitions[$post->ID][0] = $new_status;
+ } else {
+ $this->post_transitions[$post->ID] = array( $new_status, $old_status );
+ }
+
+ $operation = $sync['operation'];
+ unset( $sync['operation'] );
+
+ switch ( $operation ) {
+ case 'delete' :
+ return $this->register( 'delete_post', (int) $post->ID, $sync );
+ case 'submit' :
+ return $this->register_post( (int) $post->ID, $sync );
+ }
+ }
+
+ function get_post_sync_operation( $new_status, $old_status, $post, $module_conditions ) {
+ $delete_on_behalf_of = array();
+ $submit_on_behalf_of = array();
+ $delete_stati = array( 'delete' );
+
+ foreach ( $module_conditions as $module => $conditions ) {
+ if ( !in_array( $post->post_type, $conditions['post_types'] ) ) {
+ continue;
+ }
+
+ $deleted_post = in_array( $new_status, $delete_stati );
+
+ if ( $deleted_post ) {
+ $delete_on_behalf_of[] = $module;
+ } else {
+ clean_post_cache( $post->ID );
+ $new_status = get_post_status( $post->ID ); // Inherited status is resolved here
+ }
+
+ $old_status_in_stati = in_array( $old_status, $conditions['post_stati'] );
+ $new_status_in_stati = in_array( $new_status, $conditions['post_stati'] );
+
+ if ( $old_status_in_stati && !$new_status_in_stati ) {
+ // Jetpack no longer needs the post
+ if ( !$deleted_post ) {
+ $delete_on_behalf_of[] = $module;
+ } // else, we've already flagged it above
+ continue;
+ }
+
+ if ( !$new_status_in_stati ) {
+ continue;
+ }
+
+ // At this point, we know we want to sync the post, not delete it
+ $submit_on_behalf_of[] = $module;
+ }
+
+ if ( !empty( $submit_on_behalf_of ) ) {
+ return array( 'operation' => 'submit', 'on_behalf_of' => $submit_on_behalf_of );
+ }
+
+ if ( !empty( $delete_on_behalf_of ) ) {
+ return array( 'operation' => 'delete', 'on_behalf_of' => $delete_on_behalf_of );
+ }
+
+ return false;
}
/**
- * Request that a post be deleted remotely
+ * Get a post and associated data in the standard JP format.
+ * Cannot be called statically
*
- * @param int $id The post_ID
+ * @param int $id Post ID
+ * @return Array containing full post details
*/
- function delete_post( $id ) {
- return $this->register( 'delete_post', (int) $id, true );
+ function get_post( $id ) {
+ $post_obj = get_post( $id );
+ if ( !$post_obj )
+ return false;
+
+ if ( is_callable( $post_obj, 'to_array' ) ) {
+ // WP >= 3.5
+ $post = $post_obj->to_array();
+ } else {
+ // WP < 3.5
+ $post = get_object_vars( $post_obj );
+ }
+
+ if ( 0 < strlen( $post['post_password'] ) ) {
+ $post['post_password'] = 'auto-' . wp_generate_password( 10, false ); // We don't want the real password. Just pass something random.
+ }
+
+ // local optimizations
+ unset(
+ $post['filter'],
+ $post['ancestors'],
+ $post['post_content_filtered'],
+ $post['to_ping'],
+ $post['pinged']
+ );
+
+ if ( $this->is_post_public( $post ) ) {
+ $post['post_is_public'] = Jetpack::get_option( 'public' );
+ } else {
+ //obscure content
+ $post['post_content'] = '';
+ $post['post_excerpt'] = '';
+ $post['post_is_public'] = false;
+ }
+ $post_type_obj = get_post_type_object( $post['post_type'] );
+ $post['post_is_excluded_from_search'] = $post_type_obj->exclude_from_search;
+
+ $post['tax'] = array();
+ $taxonomies = get_object_taxonomies( $post_obj );
+ foreach ( $taxonomies as $taxonomy ) {
+ $terms = get_object_term_cache( $post_obj->ID, $taxonomy );
+ if ( empty( $terms ) )
+ $terms = wp_get_object_terms( $post_obj->ID, $taxonomy );
+ $term_names = array();
+ foreach ( $terms as $term ) {
+ $term_names[] = $term->name;
+ }
+ $post['tax'][$taxonomy] = $term_names;
+ }
+
+ $meta = get_post_meta( $post_obj->ID, false );
+ $post['meta'] = array();
+ foreach ( $meta as $key => $value ) {
+ $post['meta'][$key] = array_map( 'maybe_unserialize', $value );
+ }
+
+ $post['extra'] = array(
+ 'author' => get_the_author_meta( 'display_name', $post_obj->post_author ),
+ 'author_email' => get_the_author_meta( 'email', $post_obj->post_author ),
+ );
+
+ if ( $fid = get_post_thumbnail_id( $id ) ) {
+ $feature = wp_get_attachment_image_src( $fid, 'large' );
+ if ( !empty( $feature[0] ) )
+ $post['extra']['featured_image'] = $feature[0];
+ }
+
+ $post['permalink'] = get_permalink( $post_obj->ID );
+ $post['shortlink'] = wp_get_shortlink( $post_obj->ID );
+ return $post;
}
/**
- * Helper method for easily requesting a sync of a comment.
+ * Decide whether a post/page/attachment is visible to the public.
*
- * @param int $id wp_comments.ID
- * @param array $fields Array containing field/column names to sync (optional, defaults to all fields). Should always use default.
+ * @param array $post
+ * @return bool
+ */
+ function is_post_public( $post ) {
+ if ( !is_array( $post ) ) {
+ $post = (array) $post;
+ }
+
+ if ( 0 < strlen( $post['post_password'] ) )
+ return false;
+ if ( ! in_array( $post['post_type'], get_post_types( array( 'public' => true ) ) ) )
+ return false;
+ $post_status = get_post_status( $post['ID'] ); // Inherited status is resolved here.
+ if ( ! in_array( $post_status, get_post_stati( array( 'public' => true ) ) ) )
+ return false;
+ return true;
+ }
+
+/* Comments Sync */
+
+ function comments( $file, array $settings = null ) {
+ $module_slug = Jetpack::get_module_slug( $file );
+
+ $defaults = array(
+ 'post_types' => array( 'post', 'page' ), // For what post types will we sync comments?
+ 'post_stati' => array( 'publish' ), // For what post stati will we sync comments?
+ 'comment_types' => array( '', 'comment', 'trackback', 'pingback' ), // What comment types will we sync?
+ 'comment_stati' => array( 'approved' ), // What comment stati will we sync?
+ );
+
+ $settings = wp_parse_args( $settings, $defaults );
+
+ $this->sync_conditions['comments'][$module_slug] = $settings;
+
+ add_action( 'wp_insert_comment', array( $this, 'wp_insert_comment_action' ), 10, 2 );
+ add_action( 'transition_comment_status', array( $this, 'transition_comment_status_action' ), 10, 3 );
+ add_action( 'edit_comment', array( $this, 'edit_comment_action' ) );
+ }
+
+ /*
+ * This is really annoying. If you edit a comment, but don't change the status, WordPress doesn't fire the transition_comment_status hook.
+ * 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.
*/
- function comment( $id, $fields = true ) {
- if ( !$comment = get_comment( $id ) ) {
+ function edit_comment_action( $comment_id ) {
+ $comment = get_comment( $comment_id );
+ $new_status = $this->translate_comment_status( $comment->comment_approved );
+ add_action( "comment_{$new_status}_{$comment->comment_type}", array( $this, 'transition_comment_status_for_comments_whose_status_does_not_change' ), 10, 2 );
+ }
+
+ function wp_insert_comment_action( $comment_id, $comment ) {
+ $this->transition_comment_status_action( $comment->comment_approved, 'new', $comment );
+ }
+
+ function transition_comment_status_for_comments_whose_status_does_not_change( $comment_id, $comment ) {
+ if ( isset( $this->comment_transitions[$comment_id] ) ) {
+ return $this->transition_comment_status_action( $comment->comment_approved, $this->comment_transitions[$comment_id][1], $comment );
+ }
+
+ return $this->transition_comment_status_action( $comment->comment_approved, $comment->comment_approved, $comment );
+ }
+
+ function translate_comment_status( $status ) {
+ switch ( (string) $status ) {
+ case '0' :
+ case 'hold' :
+ return 'unapproved';
+ case '1' :
+ case 'approve' :
+ return 'approved';
+ }
+
+ return $status;
+ }
+
+ function transition_comment_status_action( $new_status, $old_status, $comment ) {
+ $post = get_post( $comment->comment_post_ID );
+ if ( !$post ) {
return false;
}
- if ( !$comment->comment_post_ID ) {
+
+ foreach ( array( 'new_status', 'old_status' ) as $_status ) {
+ $$_status = $this->translate_comment_status( $$_status );
+ }
+
+ // Track comment transitions
+ if ( isset( $this->comment_transitions[$comment->comment_ID] ) ) {
+ // status changed more than once - keep tha most recent $new_status
+ $this->comment_transitions[$comment->comment_ID][0] = $new_status;
+ } else {
+ $this->comment_transitions[$comment->comment_ID] = array( $new_status, $old_status );
+ }
+
+ $post_sync = $this->get_post_sync_operation( $post->post_status, '_jetpack_test_sync', $post, $this->sync_conditions['comments'] );
+
+ if ( !$post_sync ) {
+ // No module wants to sync this comment because its post doesn't match any sync conditions
return false;
}
- if ( !$this->post( $comment->comment_post_ID, false ) ) {
+
+ if ( 'delete' == $post_sync['operation'] ) {
+ // Had we been looking at post sync operations (instead of comment sync operations),
+ // this comment's post would have been deleted. Don't sync the comment.
return false;
}
- return $this->register( 'comment', (int) $id, $fields );
+
+ $delete_on_behalf_of = array();
+ $submit_on_behalf_of = array();
+ $delete_stati = array( 'delete' );
+
+ foreach ( $this->sync_conditions['comments'] as $module => $conditions ) {
+ if ( !in_array( $comment->comment_type, $conditions['comment_types'] ) ) {
+ continue;
+ }
+
+ $deleted_comment = in_array( $new_status, $delete_stati );
+
+ if ( $deleted_comment ) {
+ $delete_on_behalf_of[] = $module;
+ }
+
+ $old_status_in_stati = in_array( $old_status, $conditions['comment_stati'] );
+ $new_status_in_stati = in_array( $new_status, $conditions['comment_stati'] );
+
+ if ( $old_status_in_stati && !$new_status_in_stati ) {
+ // Jetpack no longer needs the comment
+ if ( !$deleted_comment ) {
+ $delete_on_behalf_of[] = $module;
+ } // else, we've already flagged it above
+ continue;
+ }
+
+ if ( !$new_status_in_stati ) {
+ continue;
+ }
+
+ // At this point, we know we want to sync the comment, not delete it
+ $submit_on_behalf_of[] = $module;
+ }
+
+ if ( ! empty( $submit_on_behalf_of ) ) {
+ $this->register_post( $comment->comment_post_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
+ return $this->register_comment( $comment->comment_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
+ }
+
+ if ( !empty( $delete_on_behalf_of ) ) {
+ return $this->register( 'delete_comment', $comment->comment_ID, array( 'on_behalf_of' => $delete_on_behalf_of ) );
+ }
+
+ return false;
}
/**
- * Request that a comment be deleted remotely
+ * Get a comment and associated data in the standard JP format.
+ * Cannot be called statically
*
- * @param int $id The comment_ID
+ * @param int $id Comment ID
+ * @return Array containing full comment details
*/
- function delete_comment( $id ) {
- return $this->register( 'delete_comment', (int) $id, true );
+ function get_comment( $id ) {
+ $comment_obj = get_comment( $id );
+ if ( !$comment_obj )
+ return false;
+ $comment = get_object_vars( $comment_obj );
+
+ $meta = get_comment_meta( $id, false );
+ $comment['meta'] = array();
+ foreach ( $meta as $key => $value ) {
+ $comment['meta'][$key] = array_map( 'maybe_unserialize', $value );
+ }
+
+ return $comment;
+ }
+
+/* Options Sync */
+
+ /* Ah... so much simpler than Posts and Comments :) */
+ function options( $file, $option /*, $option, ... */ ) {
+ $options = func_get_args();
+ $file = array_shift( $options );
+
+ $module_slug = Jetpack::get_module_slug( $file );
+
+ if ( !isset( $this->sync_options[$module_slug] ) ) {
+ $this->sync_options[$module_slug] = array();
+ }
+
+ foreach ( $options as $option ) {
+ $this->sync_options[$module_slug][] = $option;
+ add_action( "delete_option_{$option}", array( $this, 'deleted_option_action' ) );
+ add_action( "update_option_{$option}", array( $this, 'updated_option_action' ) );
+ add_action( "add_option_{$option}", array( $this, 'added_option_action' ) );
+ }
+
+ $this->sync_options[$module_slug] = array_unique( $this->sync_options[$module_slug] );
+ }
+
+ function deleted_option_action( $option ) {
+ $this->register( 'delete_option', $option );
+ }
+
+ function updated_option_action( $old_value ) {
+ // The value of $option isn't passed to the filter
+ // Calculate it
+ $option = current_filter();
+ $prefix = 'update_option_';
+ if ( 0 !== strpos( $option, $prefix ) ) {
+ return;
+ }
+ $option = substr( $option, strlen( $prefix ) );
+
+ $this->added_option_action( $option );
+ }
+
+ function added_option_action( $option ) {
+ $this->register( 'option', $option );
+ }
+
+ function sync_all_module_options( $module_slug ) {
+ if ( empty( $this->sync_options[$module_slug] ) ) {
+ return;
+ }
+
+ foreach ( $this->sync_options[$module_slug] as $option ) {
+ $this->added_option_action( $option );
+ }
+ }
+
+ function sync_all_registered_options( $options = array() ) {
+ if ( 'jetpack_sync_all_registered_options' == current_filter() ) {
+ $all_registered_options = array_unique( call_user_func_array( 'array_merge', $this->sync_options ) );
+ foreach ( $all_registered_options as $option ) {
+ $this->added_option_action( $option );
+ }
+ } else {
+ wp_schedule_single_event( time(), 'jetpack_sync_all_registered_options', array( $this->sync_options ) );
+ }
}
}
+require_once dirname( __FILE__ ) . '/class.jetpack-user-agent.php';
+require_once dirname( __FILE__ ) . '/class.jetpack-post-images.php';
+require_once dirname( __FILE__ ) . '/class.photon.php';
+require dirname( __FILE__ ) . '/functions.photon.php';
+require dirname( __FILE__ ) . '/functions.compat.php';
+require dirname( __FILE__ ) . '/functions.gallery.php';
+
class Jetpack_Error extends WP_Error {}
register_activation_hook( __FILE__, array( 'Jetpack', 'plugin_activation' ) );
@@ -3286,3 +4481,5 @@ register_deactivation_hook( __FILE__, array( 'Jetpack', 'plugin_deactivation' )
add_action( 'init', array( 'Jetpack', 'init' ) );
add_action( 'plugins_loaded', array( 'Jetpack', 'load_modules' ), 100 );
add_filter( 'jetpack_static_url', array( 'Jetpack', 'staticize_subdomain' ) );
+
+Jetpack_Sync::sync_options( __FILE__, 'widget_twitter' );
diff --git a/plugins/jetpack/languages/jetpack-ar.mo b/plugins/jetpack/languages/jetpack-ar.mo
new file mode 100644
index 00000000..254be8e6
--- /dev/null
+++ b/plugins/jetpack/languages/jetpack-ar.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-az.mo b/plugins/jetpack/languages/jetpack-az.mo
index 40f5771b..033f8593 100644
--- a/plugins/jetpack/languages/jetpack-az.mo
+++ b/plugins/jetpack/languages/jetpack-az.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-bs_BA.mo b/plugins/jetpack/languages/jetpack-bs_BA.mo
index e53b9559..67cd4468 100644
--- a/plugins/jetpack/languages/jetpack-bs_BA.mo
+++ b/plugins/jetpack/languages/jetpack-bs_BA.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-ca.mo b/plugins/jetpack/languages/jetpack-ca.mo
index 9a25543b..2daa9e1c 100644
--- a/plugins/jetpack/languages/jetpack-ca.mo
+++ b/plugins/jetpack/languages/jetpack-ca.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-cs_CZ.mo b/plugins/jetpack/languages/jetpack-cs_CZ.mo
index 0977a8b9..5e088773 100644
--- a/plugins/jetpack/languages/jetpack-cs_CZ.mo
+++ b/plugins/jetpack/languages/jetpack-cs_CZ.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-da_DK.mo b/plugins/jetpack/languages/jetpack-da_DK.mo
index dd4a5ae2..773e5b51 100644
--- a/plugins/jetpack/languages/jetpack-da_DK.mo
+++ b/plugins/jetpack/languages/jetpack-da_DK.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-de_DE.mo b/plugins/jetpack/languages/jetpack-de_DE.mo
index c21d78b2..a93c1c7c 100644
--- a/plugins/jetpack/languages/jetpack-de_DE.mo
+++ b/plugins/jetpack/languages/jetpack-de_DE.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-el.mo b/plugins/jetpack/languages/jetpack-el.mo
new file mode 100644
index 00000000..8538e68c
--- /dev/null
+++ b/plugins/jetpack/languages/jetpack-el.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-es_ES.mo b/plugins/jetpack/languages/jetpack-es_ES.mo
index 9102fc81..3cc9243e 100644
--- a/plugins/jetpack/languages/jetpack-es_ES.mo
+++ b/plugins/jetpack/languages/jetpack-es_ES.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-fa_IR.mo b/plugins/jetpack/languages/jetpack-fa_IR.mo
index 864aa9bd..f34c74e6 100644
--- a/plugins/jetpack/languages/jetpack-fa_IR.mo
+++ b/plugins/jetpack/languages/jetpack-fa_IR.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-fi.mo b/plugins/jetpack/languages/jetpack-fi.mo
index fae02a3e..591c0472 100644
--- a/plugins/jetpack/languages/jetpack-fi.mo
+++ b/plugins/jetpack/languages/jetpack-fi.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-fr_FR.mo b/plugins/jetpack/languages/jetpack-fr_FR.mo
index 15385ae5..165c2b9e 100644
--- a/plugins/jetpack/languages/jetpack-fr_FR.mo
+++ b/plugins/jetpack/languages/jetpack-fr_FR.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-gl_ES.mo b/plugins/jetpack/languages/jetpack-gl_ES.mo
index 1fb3e4c4..e5f4c09a 100644
--- a/plugins/jetpack/languages/jetpack-gl_ES.mo
+++ b/plugins/jetpack/languages/jetpack-gl_ES.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-he_IL.mo b/plugins/jetpack/languages/jetpack-he_IL.mo
index 3bbb699d..90d820c7 100644
--- a/plugins/jetpack/languages/jetpack-he_IL.mo
+++ b/plugins/jetpack/languages/jetpack-he_IL.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-hr.mo b/plugins/jetpack/languages/jetpack-hr.mo
index 6dfab5c0..8765f205 100644
--- a/plugins/jetpack/languages/jetpack-hr.mo
+++ b/plugins/jetpack/languages/jetpack-hr.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-hu_HU.mo b/plugins/jetpack/languages/jetpack-hu_HU.mo
index f9e1b630..11715656 100644
--- a/plugins/jetpack/languages/jetpack-hu_HU.mo
+++ b/plugins/jetpack/languages/jetpack-hu_HU.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-id_ID.mo b/plugins/jetpack/languages/jetpack-id_ID.mo
index 3e16a67d..8d3427dd 100644
--- a/plugins/jetpack/languages/jetpack-id_ID.mo
+++ b/plugins/jetpack/languages/jetpack-id_ID.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-it_IT.mo b/plugins/jetpack/languages/jetpack-it_IT.mo
index 1aa7c72a..7165de10 100644
--- a/plugins/jetpack/languages/jetpack-it_IT.mo
+++ b/plugins/jetpack/languages/jetpack-it_IT.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-ja.mo b/plugins/jetpack/languages/jetpack-ja.mo
index 82c715ef..f715cc91 100644
--- a/plugins/jetpack/languages/jetpack-ja.mo
+++ b/plugins/jetpack/languages/jetpack-ja.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-ko_KR.mo b/plugins/jetpack/languages/jetpack-ko_KR.mo
new file mode 100644
index 00000000..3a7a5295
--- /dev/null
+++ b/plugins/jetpack/languages/jetpack-ko_KR.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-lt_LT.mo b/plugins/jetpack/languages/jetpack-lt_LT.mo
new file mode 100644
index 00000000..55f190a5
--- /dev/null
+++ b/plugins/jetpack/languages/jetpack-lt_LT.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-mk_MK.mo b/plugins/jetpack/languages/jetpack-mk_MK.mo
index a567c77d..804e8a3b 100644
--- a/plugins/jetpack/languages/jetpack-mk_MK.mo
+++ b/plugins/jetpack/languages/jetpack-mk_MK.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-my_MM.mo b/plugins/jetpack/languages/jetpack-my_MM.mo
index ba1e6945..1d1604b7 100644
--- a/plugins/jetpack/languages/jetpack-my_MM.mo
+++ b/plugins/jetpack/languages/jetpack-my_MM.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-nb_NO.mo b/plugins/jetpack/languages/jetpack-nb_NO.mo
index 7c6bf66c..5600cf1d 100644
--- a/plugins/jetpack/languages/jetpack-nb_NO.mo
+++ b/plugins/jetpack/languages/jetpack-nb_NO.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-nl_NL.mo b/plugins/jetpack/languages/jetpack-nl_NL.mo
index 9bd9ffb3..a125514d 100644
--- a/plugins/jetpack/languages/jetpack-nl_NL.mo
+++ b/plugins/jetpack/languages/jetpack-nl_NL.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-nn_NO.mo b/plugins/jetpack/languages/jetpack-nn_NO.mo
index f5061e15..1157c955 100644
--- a/plugins/jetpack/languages/jetpack-nn_NO.mo
+++ b/plugins/jetpack/languages/jetpack-nn_NO.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-pl_PL.mo b/plugins/jetpack/languages/jetpack-pl_PL.mo
index c8ba1dd6..3a5df93c 100644
--- a/plugins/jetpack/languages/jetpack-pl_PL.mo
+++ b/plugins/jetpack/languages/jetpack-pl_PL.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-pt_BR.mo b/plugins/jetpack/languages/jetpack-pt_BR.mo
index b32d48f8..da51355f 100644
--- a/plugins/jetpack/languages/jetpack-pt_BR.mo
+++ b/plugins/jetpack/languages/jetpack-pt_BR.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-pt_PT.mo b/plugins/jetpack/languages/jetpack-pt_PT.mo
index 226b63d2..62d6331b 100644
--- a/plugins/jetpack/languages/jetpack-pt_PT.mo
+++ b/plugins/jetpack/languages/jetpack-pt_PT.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-ro_RO.mo b/plugins/jetpack/languages/jetpack-ro_RO.mo
index a3100506..6a76116e 100644
--- a/plugins/jetpack/languages/jetpack-ro_RO.mo
+++ b/plugins/jetpack/languages/jetpack-ro_RO.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-ru_RU.mo b/plugins/jetpack/languages/jetpack-ru_RU.mo
index 7c3dc2dd..392de6d0 100644
--- a/plugins/jetpack/languages/jetpack-ru_RU.mo
+++ b/plugins/jetpack/languages/jetpack-ru_RU.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-sa_IN.mo b/plugins/jetpack/languages/jetpack-sa_IN.mo
index 10f549d0..f7bfee62 100644
--- a/plugins/jetpack/languages/jetpack-sa_IN.mo
+++ b/plugins/jetpack/languages/jetpack-sa_IN.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-sk_SK.mo b/plugins/jetpack/languages/jetpack-sk_SK.mo
index b9360173..0f6a8ea8 100644
--- a/plugins/jetpack/languages/jetpack-sk_SK.mo
+++ b/plugins/jetpack/languages/jetpack-sk_SK.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-sq.mo b/plugins/jetpack/languages/jetpack-sq.mo
index 39c037cf..795f5abb 100644
--- a/plugins/jetpack/languages/jetpack-sq.mo
+++ b/plugins/jetpack/languages/jetpack-sq.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-sr_RS.mo b/plugins/jetpack/languages/jetpack-sr_RS.mo
index 9e7db3c6..62d2959a 100644
--- a/plugins/jetpack/languages/jetpack-sr_RS.mo
+++ b/plugins/jetpack/languages/jetpack-sr_RS.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-sv_SE.mo b/plugins/jetpack/languages/jetpack-sv_SE.mo
index ca682a7c..382cbc3e 100644
--- a/plugins/jetpack/languages/jetpack-sv_SE.mo
+++ b/plugins/jetpack/languages/jetpack-sv_SE.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-th.mo b/plugins/jetpack/languages/jetpack-th.mo
new file mode 100644
index 00000000..13499189
--- /dev/null
+++ b/plugins/jetpack/languages/jetpack-th.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-tr_TR.mo b/plugins/jetpack/languages/jetpack-tr_TR.mo
index 83a6b84e..24eeccec 100644
--- a/plugins/jetpack/languages/jetpack-tr_TR.mo
+++ b/plugins/jetpack/languages/jetpack-tr_TR.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-zh_CN.mo b/plugins/jetpack/languages/jetpack-zh_CN.mo
new file mode 100644
index 00000000..17900fb1
--- /dev/null
+++ b/plugins/jetpack/languages/jetpack-zh_CN.mo
Binary files differ
diff --git a/plugins/jetpack/languages/jetpack-zh_TW.mo b/plugins/jetpack/languages/jetpack-zh_TW.mo
new file mode 100644
index 00000000..38662136
--- /dev/null
+++ b/plugins/jetpack/languages/jetpack-zh_TW.mo
Binary files differ
diff --git a/plugins/jetpack/locales.php b/plugins/jetpack/locales.php
index 41075cdd..e910fbfc 100644
--- a/plugins/jetpack/locales.php
+++ b/plugins/jetpack/locales.php
@@ -13,22 +13,22 @@ class GP_Locale {
var $preferred_sans_serif_font_family = null;
var $facebook_locale = null;
// TODO: days, months, decimals, quotes
-
+
function GP_Locale( $args = array() ) {
foreach( $args as $key => $value ) {
$this->$key = $value;
}
}
-
+
static function __set_state( $state ) {
return new GP_Locale( $state );
}
-
+
function combined_name() {
/* translators: combined name for locales: 1: name in English, 2: native name */
- return sprintf( _x( '%1$s/%2$s', 'locales' ), $this->english_name, $this->native_name );
+ return sprintf( _x( '%1$s/%2$s', 'locales', 'jetpack' ), $this->english_name, $this->native_name );
}
-
+
function numbers_for_index( $index, $how_many = 3, $test_up_to = 1000 ) {
$numbers = array();
for( $number = 0; $number < $test_up_to; ++$number ) {
@@ -39,7 +39,7 @@ class GP_Locale {
}
return $numbers;
}
-
+
function index_for_number( $number ) {
if ( !isset( $this->_index_for_number ) ) {
$expression = Gettext_Translations::parenthesize_plural_exression( $this->plural_expression );
@@ -51,9 +51,9 @@ class GP_Locale {
}
class GP_Locales {
-
+
var $locales = array();
-
+
function GP_Locales() {
$aa = new GP_Locale();
$aa->english_name = 'Afar';
@@ -144,7 +144,7 @@ class GP_Locales {
$av->native_name = 'авар мацӀ';
$av->lang_code_iso_639_1 = 'av';
$av->lang_code_iso_639_2 = 'ava';
- $av->country_code = '';
+ $av->country_code = '';
$av->slug = 'av';
$ay = new GP_Locale();
@@ -167,7 +167,7 @@ class GP_Locales {
$az->slug = 'az';
$az->google_code = 'az';
$az->facebook_locale = 'az_AZ';
-
+
$az_tr = new GP_Locale();
$az_tr->english_name = 'Azerbaijani (Turkey)';
$az_tr->native_name = 'Azərbaycan Türkcəsi';
@@ -398,7 +398,7 @@ class GP_Locales {
$da->slug = 'da';
$da->google_code = 'da';
$da->facebook_locale = 'da_DK';
-
+
$de = new GP_Locale();
$de->english_name = 'German';
$de->native_name = 'Deutsch';
@@ -408,7 +408,7 @@ class GP_Locales {
$de->slug = 'de';
$de->google_code = 'de';
$de->facebook_locale = 'de_DE';
-
+
$dv = new GP_Locale();
$dv->english_name = 'Divehi';
$dv->native_name = 'Þ‹Þ¨ÞˆÞ¬Þ€Þ¨';
@@ -419,7 +419,7 @@ class GP_Locales {
$dv->slug = 'dv';
$dv->google_code = 'dv';
$dv->rtl = true;
-
+
$dz = new GP_Locale();
$dz->english_name = 'Dzongkha';
$dz->native_name = 'རྫོང་à½';
@@ -429,7 +429,7 @@ class GP_Locales {
$dz->slug = 'dz';
$dz->nplurals = 1;
$dz->plural_expression = '0';
-
+
$ee = new GP_Locale();
$ee->english_name = 'Ewe';
$ee->native_name = 'EÊ‹egbe';
@@ -456,7 +456,7 @@ class GP_Locales {
$el->slug = 'el';
$el->google_code = 'el';
$el->facebook_locale = 'el_GR';
-
+
$en = new GP_Locale();
$en->english_name = 'English';
$en->native_name = 'English';
@@ -466,28 +466,28 @@ class GP_Locales {
$en->slug = 'en';
$en->google_code = 'en';
$en->facebook_locale = 'en_US';
-
+
$en_ca = new GP_Locale();
$en_ca->english_name = 'English (Canada)';
$en_ca->native_name = 'English (Canada)';
$en_ca->lang_code_iso_639_1 = 'en';
- $en_ca->lang_code_iso_639_2 = 'eng';
+ $en_ca->lang_code_iso_639_2 = 'eng';
$en_ca->lang_code_iso_639_3 = 'eng';
$en_ca->country_code = 'ca';
$en_ca->wp_locale = 'en_CA';
$en_ca->slug = 'en-ca';
$en_ca->google_code = 'en';
-
+
$en_gb = new GP_Locale();
$en_gb->english_name = 'English (UK)';
$en_gb->native_name = 'English (UK)';
$en_gb->lang_code_iso_639_1 = 'en';
- $en_gb->lang_code_iso_639_2 = 'eng';
+ $en_gb->lang_code_iso_639_2 = 'eng';
$en_gb->lang_code_iso_639_3 = 'eng';
$en_gb->country_code = 'gb';
$en_gb->wp_locale = 'en_GB';
$en_gb->slug = 'en-gb';
- $en_gb->google_code = 'en';
+ $en_gb->google_code = 'en';
$en_gb->facebook_locale = 'en_GB';
$eo = new GP_Locale();
@@ -533,7 +533,7 @@ class GP_Locales {
$es_pr->slug = 'es-pr';
$es_pr->google_code = 'es';
$es_pr->facebook_locale = 'es_LA';
-
+
$es_ve = new GP_Locale();
$es_ve->english_name = 'Spanish (Venezuela)';
$es_ve->native_name = 'Español de Venezuela';
@@ -565,7 +565,7 @@ class GP_Locales {
$es->slug = 'es';
$es->google_code = 'es';
$es->facebook_locale = 'es_ES';
-
+
$et = new GP_Locale();
$et->english_name = 'Estonian';
$et->native_name = 'Eesti';
@@ -601,7 +601,7 @@ class GP_Locales {
$fa->nplurals = 1;
$fa->plural_expression = '0';
$fa->rtl = true;
-
+
$fa_af = new GP_Locale();
$fa_af->english_name = 'Persian (Afghanistan)';
$fa_af->native_name = '(Ùارسی (اÙغانستان';
@@ -614,7 +614,7 @@ class GP_Locales {
$fa_af->nplurals = 1;
$fa_af->plural_expression = '0';
$fa_af->rtl = true;
-
+
$fi = new GP_Locale();
$fi->english_name = 'Finnish';
$fi->native_name = 'Suomi';
@@ -643,7 +643,7 @@ class GP_Locales {
$fo->wp_locale = 'fo';
$fo->slug = 'fo';
$fo->facebook_locale = 'fo_FO';
-
+
$fr = new GP_Locale();
$fr->english_name = 'French (France)';
$fr->native_name = 'Français';
@@ -691,7 +691,7 @@ class GP_Locales {
$fy->facebook_locale = 'fy_NL';
$fy->slug = 'fy';
$fy->wp_locale = 'fy';
-
+
$ga = new GP_Locale();
$ga->english_name = 'Irish';
$ga->native_name = 'Gaelige';
@@ -703,7 +703,7 @@ class GP_Locales {
$ga->facebook_locale = 'ga_IE';
$ga->nplurals = 5;
$ga->plural_expression = 'n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4';
-
+
$gd = new GP_Locale();
$gd->english_name = 'Scottish Gaelic';
$gd->native_name = 'Gàidhlig';
@@ -715,7 +715,7 @@ class GP_Locales {
$gd->slug = 'gd';
$gd->google_code = 'gd';
$gd->nplurals = 4;
- $gd->plural_expression = '(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3';
+ $gd->plural_expression = '(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3';
$gl = new GP_Locale();
$gl->english_name = 'Galician';
@@ -755,7 +755,7 @@ class GP_Locales {
$ha->country_code = '';
$ha->slug = 'ha';
$ha->rtl = true;
-
+
$haw = new GP_Locale();
$haw->english_name = 'Hawaiian';
$haw->native_name = 'Ōlelo Hawaiʻi';
@@ -1007,18 +1007,18 @@ class GP_Locales {
$lb->country_code = 'lu';
$lb->wp_locale = 'lb_LU';
$lb->slug = 'lb';
-
+
$li = new GP_Locale();
$li->english_name = 'Limburgish';
$li->native_name = 'Limburgs';
$li->lang_code_iso_639_1 = 'li';
$li->lang_code_iso_639_2 = 'lim';
- $li->lang_code_iso_639_3 = 'lim';
+ $li->lang_code_iso_639_3 = 'lim';
$li->country_code = 'nl';
$li->wp_locale = 'li';
$li->slug = 'li';
$li->google_code = 'li';
-
+
$lo = new GP_Locale();
$lo->english_name = 'Lao';
$lo->native_name = 'ພາສາລາວ';
@@ -1037,6 +1037,7 @@ class GP_Locales {
$lt->lang_code_iso_639_1 = 'lt';
$lt->lang_code_iso_639_2 = 'lit';
$lt->country_code = 'lt';
+ $lt->wp_locale = 'lt_LT';
$lt->slug = 'lt';
$lt->google_code = 'lt';
$lt->facebook_locale = 'lt_LT';
@@ -1055,7 +1056,7 @@ class GP_Locales {
$lv->facebook_locale = 'lv_LV';
$lv->nplurals = 3;
$lv->plural_expression = '(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)';
-
+
$me = new GP_Locale();
$me->english_name = 'Montenegrin';
$me->native_name = 'Crnogorski jezik';
@@ -1064,7 +1065,9 @@ class GP_Locales {
$me->wp_locale = 'me_ME';
$me->google_code = 'srp';
$me->slug = 'me';
-
+ $me->nplurals = 3;
+ $me->plural_expression = '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)';
+
$mg = new GP_Locale();
$mg->english_name = 'Malagasy';
$mg->native_name = 'Malagasy';
@@ -1073,7 +1076,7 @@ class GP_Locales {
$mg->country_code = 'mg';
$mg->wp_locale = 'mg_MG';
$mg->slug = 'mg';
-
+
$mhr = new GP_Locale();
$mhr->english_name = 'Mari (Meadow)';
$mhr->native_name = 'олык марий';
@@ -1082,8 +1085,8 @@ class GP_Locales {
$mhr->lang_code_iso_639_3 = 'mhr';
$mhr->country_code = 'ru';
$mhr->slug = 'mhr';
- $mhr->google_code = 'chm';
-
+ $mhr->google_code = 'chm';
+
$mk = new GP_Locale();
$mk->english_name = 'Macedonian';
$mk->native_name = 'македонÑки јазик';
@@ -1125,7 +1128,7 @@ class GP_Locales {
$mr->country_code = '';
$mr->slug = 'mr';
$mr->google_code = 'mr';
-
+
$mrj = new GP_Locale();
$mrj->english_name = 'Mari (Hill)';
$mrj->native_name = 'кырык мары';
@@ -1134,7 +1137,7 @@ class GP_Locales {
$mrj->lang_code_iso_639_3 = 'mrj';
$mrj->country_code = 'ru';
$mrj->slug = 'mrj';
- $mrj->google_code = 'chm';
+ $mrj->google_code = 'chm';
$ms = new GP_Locale();
$ms->english_name = 'Malay';
@@ -1208,7 +1211,7 @@ class GP_Locales {
$nl_be->wp_locale = 'nl_BE';
$nl_be->slug = 'nl-be';
$nl_be->google_code = 'nl';
-
+
$nn = new GP_Locale();
$nn->english_name = 'Norwegian (Nynorsk)';
$nn->native_name = 'Norsk nynorsk';
@@ -1244,7 +1247,7 @@ class GP_Locales {
$os->wp_locale = 'os';
$os->country_code = '';
$os->slug = 'os';
-
+
$pa = new GP_Locale();
$pa->english_name = 'Punjabi';
$pa->native_name = 'ਪੰਜਾਬੀ';
@@ -1281,7 +1284,7 @@ class GP_Locales {
$pt_br->facebook_locale = 'pt_BR';
$pt_br->nplurals = 2;
$pt_br->plural_expression = '(n > 1)';
-
+
$pt = new GP_Locale();
$pt->english_name = 'Portuguese (Portugal)';
$pt->native_name = 'Português';
@@ -1291,7 +1294,7 @@ class GP_Locales {
$pt->slug = 'pt';
$pt->google_code = 'pt-PT';
$pt->facebook_locale = 'pt_PT';
-
+
$ps = new GP_Locale();
$ps->english_name = 'Pashto';
$ps->native_name = 'پښتو';
@@ -1301,7 +1304,7 @@ class GP_Locales {
$ps->slug = 'ps';
$ps->google_code = 'ps';
$ps->facebook_locale = 'ps_AF';
- $ps->rtl = true;
+ $ps->rtl = true;
$ro = new GP_Locale();
$ro->english_name = 'Romanian';
@@ -1340,7 +1343,7 @@ class GP_Locales {
$ru_ua->google_code = 'ru';
$ru_ua->nplurals = 3;
$ru_ua->plural_expression = '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)';
-
+
$rue = new GP_Locale();
$rue->english_name = 'Rusyn';
$rue->native_name = 'РуÑиньÑкый';
@@ -1351,8 +1354,8 @@ class GP_Locales {
$rue->wp_locale = 'rue';
$rue->slug = 'rue';
$rue->nplurals = 3;
- $rue->plural_expression = '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)';
-
+ $rue->plural_expression = '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)';
+
$rup = new GP_Locale();
$rup->english_name = 'Aromanian';
$rup->native_name = 'Armãneashce';
@@ -1427,18 +1430,18 @@ class GP_Locales {
$sl->facebook_locale = 'sl_SI';
$sl->nplurals = 4;
$sl->plural_expression = '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)';
-
+
$so = new GP_Locale();
$so->english_name = 'Somali';
$so->native_name = 'Afsoomaali';
$so->lang_code_iso_639_1 = 'so';
$so->lang_code_iso_639_2 = 'som';
- $so->lang_code_iso_639_3 = 'som';
+ $so->lang_code_iso_639_3 = 'som';
$so->country_code = 'so';
$so->wp_locale = 'so_SO';
$so->slug = 'so';
$so->google_code = 'so';
-
+
$sq = new GP_Locale();
$sq->english_name = 'Albanian';
$sq->native_name = 'Shqip';
@@ -1515,7 +1518,7 @@ class GP_Locales {
$ta->slug = 'ta';
$ta->google_code = 'ta';
$ta->facebook_locale = 'ta_IN';
-
+
$ta_lk = new GP_Locale();
$ta_lk->english_name = 'Tamil (Sri Lanka)';
$ta_lk->native_name = 'தமிழà¯';
@@ -1537,6 +1540,18 @@ class GP_Locales {
$te->google_code = 'te';
$te->facebook_locale = 'te_IN';
+ $tg = new GP_Locale();
+ $tg->english_name = 'Tajik';
+ $tg->native_name = 'тоҷикӣ';
+ $tg->lang_code_iso_639_1 = 'tg';
+ $tg->lang_code_iso_639_2 = 'tgk';
+ $tg->country_code = '';
+ $tg->wp_locale = 'tg';
+ $tg->slug = 'tg';
+ $tg->google_code = 'tg';
+ $tg->nplurals = 2;
+ $tg->plural_expression = 'n != 1;';
+
$th = new GP_Locale();
$th->english_name = 'Thai';
$th->native_name = 'ไทย';
@@ -1549,7 +1564,7 @@ class GP_Locales {
$th->facebook_locale = 'th_TH';
$th->nplurals = 1;
$th->plural_expression = '0';
-
+
$tlh = new GP_Locale();
$tlh->english_name = 'Klingon';
$tlh->native_name = 'TlhIngan';
@@ -1686,6 +1701,14 @@ class GP_Locales {
$yi->slug = 'yi';
$yi->google_code = 'yi';
$yi->rtl = true;
+
+ $yo = new GP_Locale();
+ $yo->english_name = 'Yorùbá';
+ $yo->native_name = 'èdè Yorùbá';
+ $yo->lang_code_iso_639_1 = 'yo';
+ $yo->lang_code_iso_639_2 = 'yor';
+ $yo->country_code = '';
+ $yo->slug = 'yo';
$zh_cn = new GP_Locale();
$zh_cn->english_name = 'Chinese (China)';
@@ -1744,28 +1767,28 @@ class GP_Locales {
$zh->slug = 'zh';
$zh->nplurals = 1;
$zh->plural_expression = '0';
-
+
foreach( get_defined_vars() as $locale ) {
$this->locales[$locale->slug] = $locale;
}
}
-
+
function &instance() {
if ( !isset( $GLOBALS['gp_locales'] ) )
- $GLOBALS['gp_locales'] = &new GP_Locales();
+ $GLOBALS['gp_locales'] = new GP_Locales;
return $GLOBALS['gp_locales'];
}
-
+
function locales() {
$instance = GP_Locales::instance();
return $instance->locales;
}
-
+
function exists( $slug ) {
$instance = GP_Locales::instance();
return isset( $instance->locales[$slug] );
}
-
+
function by_slug( $slug ) {
$instance = GP_Locales::instance();
return isset( $instance->locales[$slug] )? $instance->locales[$slug] : null;
diff --git a/plugins/jetpack/modules/after-the-deadline.php b/plugins/jetpack/modules/after-the-deadline.php
index b187de35..606f6488 100644
--- a/plugins/jetpack/modules/after-the-deadline.php
+++ b/plugins/jetpack/modules/after-the-deadline.php
@@ -14,7 +14,7 @@ function AtD_load() {
}
function AtD_configuration_load() {
- wp_safe_redirect( admin_url( 'profile.php#atd' ) );
+ wp_safe_redirect( get_edit_profile_url( get_current_user_id() ) . '#atd' );
exit;
}
diff --git a/plugins/jetpack/modules/after-the-deadline/config-options.php b/plugins/jetpack/modules/after-the-deadline/config-options.php
index 31cc4da3..097b062d 100644
--- a/plugins/jetpack/modules/after-the-deadline/config-options.php
+++ b/plugins/jetpack/modules/after-the-deadline/config-options.php
@@ -45,7 +45,7 @@ function AtD_display_options_form() {
?>
<table class="form-table">
<tr valign="top">
- <th scope="row"> <a name="atd"></a> <?php _e( 'Proofreading', 'jetpack' ); ?></th>
+ <th scope="row"> <a id="atd"></a> <?php _e( 'Proofreading', 'jetpack' ); ?></th>
<td>
<p><?php _e( 'Automatically proofread content when:', 'jetpack' ); ?>
@@ -86,7 +86,7 @@ function AtD_display_options_form() {
<p style="font-weight: bold"><?php _e( 'Language', 'jetpack' ); ?></font>
<p><?php printf(
- _x( 'The proofreader supports English, French, German, Portuguese, and Spanish. Your <a href="%1$s">%2%s</a> value is the default proofreading language.', '%1$s = http://codex.wordpress.org/Installing_WordPress_in_Your_Language, %2$s = WPLANG', 'jetpack' ),
+ _x( 'The proofreader supports English, French, German, Portuguese, and Spanish. Your <a href="%1$s">%2$s</a> value is the default proofreading language.', '%1$s = http://codex.wordpress.org/Installing_WordPress_in_Your_Language, %2$s = WPLANG', 'jetpack' ),
'http://codex.wordpress.org/Installing_WordPress_in_Your_Language',
'WPLANG'
); ?></p>
diff --git a/plugins/jetpack/modules/carousel/jetpack-carousel-ie8fix.css b/plugins/jetpack/modules/carousel/jetpack-carousel-ie8fix.css
new file mode 100644
index 00000000..9f2f6cff
--- /dev/null
+++ b/plugins/jetpack/modules/carousel/jetpack-carousel-ie8fix.css
@@ -0,0 +1,8 @@
+.jp-carousel .jp-carousel-slide {
+ display: none !important;
+}
+
+.jp-carousel .selected {
+ margin: 0 auto;
+ display: block !important;
+}
diff --git a/plugins/jetpack/modules/carousel/jetpack-carousel.css b/plugins/jetpack/modules/carousel/jetpack-carousel.css
index aa2b1d0f..49bdad8e 100644
--- a/plugins/jetpack/modules/carousel/jetpack-carousel.css
+++ b/plugins/jetpack/modules/carousel/jetpack-carousel.css
@@ -11,7 +11,7 @@ div.jp-carousel-fadeaway {
background: -webkit-gradient(linear, left bottom, left top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0)));
position: fixed;
bottom: 0;
- z-index: 99999;
+ z-index: 2147483647;
width: 100%;
height: 15px;
}
@@ -199,13 +199,11 @@ div.jp-carousel-buttons a:hover {
.jp-carousel-close-hint {
color: #999;
cursor: default;
- font: 16px/1 "Helvetica Neue", sans-serif !important;
- font-weight: 600 !important;
letter-spacing: 0 !important;
- padding:0.55em 0 0;
- text-align: left;
- width: 100%;
+ padding:0.35em 0 0;
position: absolute;
+ text-align: left;
+ width: 90%;
-webkit-transition: color 200ms linear;
-moz-transition: color 200ms linear;
-o-transition: color 200ms linear;
@@ -213,16 +211,17 @@ div.jp-carousel-buttons a:hover {
}
.jp-carousel-close-hint span {
- cursor:pointer;
+ cursor: pointer;
background-color: black;
background-color: rgba(0,0,0,0.8);
- height: 26px;
- width: 26px;
display: block;
- text-align: center;
- vertical-align: middle;
+ height: 22px;
+ font: 400 24px/1 "Helvetica Neue", sans-serif !important;
line-height: 22px;
margin: 0 0 0 0.4em;
+ text-align: center;
+ vertical-align: middle;
+ width: 22px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
@@ -482,7 +481,10 @@ div#carousel-reblog-box {
display: none;
}
-h1:before, h1:after {
+.jp-carousel-photo-info h1:before,
+.jp-carousel-photo-info h1:after,
+.jp-carousel-left-column-wrapper h1:before,
+.jp-carousel-left-column-wrapper h1:after {
content:none !important;
}
/** Title and Desc End **/
@@ -631,6 +633,8 @@ a.jp-carousel-image-download:hover {
width:auto;
display: inline;
float:none;
+ border:none;
+ margin:0;
}
.jp-carousel-comment .comment-author a {
@@ -644,6 +648,7 @@ a.jp-carousel-image-download:hover {
.jp-carousel-comment .comment-content {
border:none;
margin-left:85px;
+ padding: 0;
}
.jp-carousel-comment .avatar {
@@ -1037,3 +1042,63 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
background: -moz-linear-gradient(bottom, rgba(255,255,255,0.75), rgba(255,255,255,0));
background: -webkit-gradient(linear, left bottom, left top, from(rgba(255,255,255,0.75)), to(rgba(255,255,255,0)));
}
+
+/* Small screens */
+@media only screen and (max-width: 760px) {
+
+ .jp-carousel-info {
+ margin: 0 10px !important;
+ }
+
+ .jp-carousel-next-button, .jp-carousel-previous-button {
+ display: none !important;
+ }
+
+ .jp-carousel-buttons {
+ display: none !important;
+ }
+
+ .jp-carousel-image-meta {
+ float: none !important;
+ width: 100% !important;
+ -moz-box-sizing:border-box;
+ -webkit-box-sizing:border-box;
+ box-sizing: border-box;
+ }
+
+ .jp-carousel-close-hint {
+ font-weight: 800 !important;
+ font-size: 26px !important;
+ position: fixed !important;
+ top: -10px;
+ }
+
+ .jp-carousel-slide img {
+ filter: alpha(opacity=100);
+ opacity: 1;
+ }
+
+ .jp-carousel-wrap {
+ background-color: #000;
+ }
+
+ .jp-carousel-fadeaway {
+ display: none;
+ }
+
+ #jp-carousel-comment-form-container {
+ display: none !important;
+ }
+
+ .jp-carousel-titleanddesc {
+ padding-top: 0 !important;
+ border: none !important;
+ }
+ .jp-carousel-titleanddesc-title {
+ font-size: 1em !important;
+ }
+
+ .jp-carousel-left-column-wrapper {
+ padding: 0;
+ }
+}
diff --git a/plugins/jetpack/modules/carousel/jetpack-carousel.js b/plugins/jetpack/modules/carousel/jetpack-carousel.js
index 5760811e..43f1d1f7 100644
--- a/plugins/jetpack/modules/carousel/jetpack-carousel.js
+++ b/plugins/jetpack/modules/carousel/jetpack-carousel.js
@@ -4,7 +4,12 @@ jQuery(document).ready(function($) {
// gallery faded layer and container elements
var overlay, comments, gallery, container, nextButton, previousButton, info, title,
caption, resizeTimeout, mouseTimeout, photo_info, close_hint, commentInterval, buttons,
- screenPadding = 110, originalOverflow = $('body').css('overflow'), proportion = 85;
+ screenPadding = 110, originalOverflow = $('body').css('overflow'), originalHOverflow = $('html').css('overflow'), proportion = 85, isMobile;
+
+ isMobile = /Android|iPhone|iPod/i.test(navigator.userAgent);
+
+ if (isMobile)
+ screenPadding = 0;
var keyListener = function(e){
switch(e.which){
@@ -64,7 +69,7 @@ jQuery(document).ready(function($) {
buttons = '<a class="jp-carousel-commentlink" href="#">' + jetpackCarouselStrings.comment + '</a>';
buttons = $('<div class="jp-carousel-buttons">' + buttons + '</div>');
-
+
caption = $('<h2></h2>');
photo_info = $('<div class="jp-carousel-photo-info"></div>').append(caption);
@@ -127,7 +132,7 @@ jQuery(document).ready(function($) {
'bottom' : '10px',
'margin-top' : '20px'
});
-
+
leftWidth = ( $(window).width() - ( screenPadding * 2 ) ) - (imageMeta.width() + 40);
if ( $.browser.mozilla )
leftWidth -= 55;
@@ -135,6 +140,9 @@ jQuery(document).ready(function($) {
leftWidth -= 20;
leftWidth += 'px';
+ if (isMobile)
+ leftWidth = '100%';
+
leftColWrapper = $('<div></div>')
.addClass('jp-carousel-left-column-wrapper')
.css({
@@ -147,7 +155,7 @@ jQuery(document).ready(function($) {
fadeaway = $('<div></div>')
.addClass('jp-carousel-fadeaway');
-
+
info = $('<div></div>')
.addClass('jp-carousel-info')
.css({
@@ -159,6 +167,11 @@ jQuery(document).ready(function($) {
.append(imageMeta)
.append(leftColWrapper);
+ if (isMobile)
+ info.prepend(leftColWrapper);
+ else
+ info.append(leftColWrapper);
+
targetBottomPos = ( $(window).height() - parseInt( info.css('top'), 10 ) ) + 'px';
nextButton = $("<div><span></span></div>")
@@ -166,7 +179,7 @@ jQuery(document).ready(function($) {
.css({
'position' : 'fixed',
'top' : 0,
- 'right' : 0,
+ 'right' : '15px',
'bottom' : 0,
'width' : screenPadding
});
@@ -175,7 +188,7 @@ jQuery(document).ready(function($) {
'top' : '40px',
'bottom' : targetBottomPos
});
-
+
previousButton = $("<div><span></span></div>")
.addClass('jp-carousel-previous-button')
.css({
@@ -190,7 +203,7 @@ jQuery(document).ready(function($) {
'top' : '40px',
'bottom' : targetBottomPos
});
-
+
gallery = $('<div></div>')
.addClass('jp-carousel')
.css({
@@ -205,20 +218,20 @@ jQuery(document).ready(function($) {
.css({
position : 'fixed'
});
-
+
container = $("<div></div>")
.addClass('jp-carousel-wrap');
-
+
if ( 'white' == jetpackCarouselStrings.background_color )
container.addClass('jp-carousel-light');
-
+
container.css({
'position' : 'fixed',
'top' : 0,
'right' : 0,
'bottom' : 0,
'left' : 0,
- 'z-index' : 999999,
+ 'z-index' : 2147483647,
'overflow-x' : 'hidden',
'overflow-y' : 'auto',
'direction' : 'ltr'
@@ -315,7 +328,7 @@ jQuery(document).ready(function($) {
return;
}
}
-
+
$.ajax({
type: 'POST',
url: jetpackCarouselStrings.ajaxurl,
@@ -349,6 +362,7 @@ jQuery(document).ready(function($) {
.bind('jp_carousel.afterOpen', function(){
$(window).bind('keydown', keyListener);
$(window).bind('resize', resizeListener);
+ gallery.opened = true;
})
.bind('jp_carousel.beforeClose', function(){
var scroll = $(window).scrollTop();
@@ -357,6 +371,15 @@ jQuery(document).ready(function($) {
$(window).unbind('resize', resizeListener);
document.location.hash = '';
$(window).scrollTop(scroll);
+ gallery.opened = false;
+ });
+
+ $('.jp-carousel').touchwipe({
+ wipeLeft: function() { gallery.jp_carousel('next'); },
+ wipeRight: function() { gallery.jp_carousel('previous'); },
+ min_move_x: 20,
+ min_move_y: 20,
+ preventDefaultEvents: true
});
nextButton.add(previousButton).click(function(e){
@@ -372,9 +395,22 @@ jQuery(document).ready(function($) {
};
var methods = {
+ testForData: function(gallery) {
+ gallery = $( gallery ); // make sure we have it as a jQuery object.
+ if ( ! gallery.length || undefined == gallery.data( 'carousel-extra' ) )
+ return false;
+ return true;
+ },
+
+ testIfOpened: function() {
+ if ( 'undefined' != typeof(gallery) && 'undefined' != typeof(gallery.opened) && true == gallery.opened )
+ return true;
+ return false;
+ },
+
open: function(options) {
var settings = {
- 'items_selector' : ".gallery-item [data-attachment-id]",
+ 'items_selector' : ".gallery-item [data-attachment-id], .tiled-gallery-item [data-attachment-id]",
'start_index': 0
},
data = $(this).data('carousel-extra');
@@ -382,12 +418,19 @@ jQuery(document).ready(function($) {
if ( !data )
return; // don't run if the default gallery functions weren't used
+ prepareGallery();
+
+ if ( gallery.jp_carousel( 'testIfOpened' ) )
+ return; // don't open if already opened
+
// make sure to stop the page from scrolling behind the carousel overlay, so we don't trigger
// infiniscroll for it when enabled (Reader, theme infiniscroll, etc).
originalOverflow = $('body').css('overflow');
$('body').css('overflow', 'hidden');
-
- prepareGallery();
+ // prevent html from overflowing on some of the new themes.
+ originalHOverflow = $('html').css('overflow');
+ $('html').css('overflow', 'hidden');
+
container.data('carousel-extra', data);
return this.each(function() {
@@ -415,7 +458,7 @@ jQuery(document).ready(function($) {
if ( 0 === selected.length )
selected = slides.eq(0);
-
+
gallery.jp_carousel('selectSlide', selected, false);
return this;
},
@@ -423,6 +466,7 @@ jQuery(document).ready(function($) {
close : function(){
// make sure to let the page scroll again
$('body').css('overflow', originalOverflow);
+ $('html').css('overflow', originalHOverflow);
return container
.trigger('jp_carousel.beforeClose')
.fadeOut('fast', function(){
@@ -473,29 +517,21 @@ jQuery(document).ready(function($) {
gallery.jp_carousel('selectedSlide').removeClass('selected').css({'position': 'fixed'});
if (reverse !== true ) {
last = slides.last();
- slides.first().nextAll().not(last).css({'left':gallery.width()+slides.first().width()}).hide();
- last.css({
- 'left' : -last.width()
- });
- last.prev().css({
- 'left' : -last.width() - last.prev().width()
- });
- slides.first().css({'left':gallery.width()});
+ slides.first().nextAll().not(last).jp_carousel('setSlidePosition', gallery.width()+slides.first().width()).hide();
+ last.jp_carousel('setSlidePosition', -last.width());
+ last.prev().jp_carousel('setSlidePosition', -last.width() - last.prev().width());
+ slides.first().jp_carousel('setSlidePosition', gallery.width());
setTimeout(function(){
gallery.jp_carousel('selectSlide', slides.show().first());
}, 400);
} else {
first = slides.first();
- first.css({
- 'left':gallery.width()
- });
- first.next().css({
- 'left':gallery.width() + first.width()
- });
- first.next().nextAll().hide().css({'left':-slides.last().width()});
- slides.last().css({'left':-slides.last().width()});
- slides.last().prevAll().not(first, first.next()).hide().css({'left':-slides.last().width()-slides.last().prev().width()});
+ first.jp_carousel('setSlidePosition', gallery.width());
+ first.next().jp_carousel('setSlidePosition', gallery.width() + first.width());
+ first.next().nextAll().hide().jp_carousel('setSlidePosition', -slides.last().width());
+ slides.last().jp_carousel('setSlidePosition', -slides.last().width());
+ slides.last().prevAll().not(first, first.next()).hide().jp_carousel('setSlidePosition', -slides.last().width()-slides.last().prev().width());
setTimeout(function(){
gallery.jp_carousel('selectSlide', slides.show().last());
}, 400);
@@ -507,6 +543,16 @@ jQuery(document).ready(function($) {
return this.find('.selected');
},
+ setSlidePosition : function(x) {
+ return this.css({
+ '-webkit-transform':'translate3d(' + x + 'px,0,0)',
+ '-moz-transform':'translate3d(' + x + 'px,0,0)',
+ '-ms-transform':'translate(' + x + 'px,0)',
+ '-o-transform':'translate(' + x + 'px,0)',
+ 'transform':'translate3d(' + x + 'px,0,0)'
+ });
+ },
+
selectSlide : function(slide, animate){
var last = this.find('.selected').removeClass('selected'),
slides = gallery.jp_carousel('slides').css({'position': 'fixed'}),
@@ -521,7 +567,7 @@ jQuery(document).ready(function($) {
animated,
info_min;
// center the main image
-
+
caption.hide();
method = 'css';
@@ -534,7 +580,7 @@ jQuery(document).ready(function($) {
// slide the whole view to the x we want
slides.not(animated).hide();
- current[method]({left:left}).show();
+ current.jp_carousel('setSlidePosition', left).show();
// minimum width
gallery.jp_carousel('fitInfo', animate);
@@ -542,24 +588,24 @@ jQuery(document).ready(function($) {
// prep the slides
var direction = last.is(current.prevAll()) ? 1 : -1;
if ( 1 == direction ) {
- next_next.css({'left':gallery.width() + next.width()}).show();
- next.hide().css({'left':gallery.width() + current.width()}).show();
- previous_previous.css({'left':-previous_previous.width() - current.width()});
+ next_next.jp_carousel('setSlidePosition', gallery.width() + next.width()).show();
+ next.hide().jp_carousel('setSlidePosition', gallery.width() + current.width()).show();
+ previous_previous.jp_carousel('setSlidePosition', -previous_previous.width() - current.width()).show();
} else {
- previous.css({'left':-previous.width() - current.width()});
- next_next.css({'left':gallery.width() + current.width()});
+ previous.jp_carousel('setSlidePosition', -previous.width() - current.width()).show();
+ next_next.jp_carousel('setSlidePosition', gallery.width() + current.width()).show();
}
-
- // if advancing prepare the slide that will enter the screen
- previous[method]({left:-previous.width() + (screenPadding * 0.75) }).show();
- next[method]({left:gallery.width() - (screenPadding * 0.75) }).show();
+ // if advancing prepare the slide that will enter the screen
+ previous.jp_carousel('setSlidePosition', -previous.width() + (screenPadding * 0.75)).show();
+ next.jp_carousel('setSlidePosition', gallery.width() - (screenPadding * 0.75)).show();
+ next.css({'position': ''});
document.location.href = document.location.href.replace(/#.*/, '') + '#jp-carousel-' + current.data('attachment-id');
gallery.jp_carousel('resetButtons', current);
container.trigger('jp_carousel.selectSlide', [current]);
$( 'div.jp-carousel-image-meta', 'div.jp-carousel-wrap' ).html('');
-
+
gallery.jp_carousel('getTitleDesc', { title: current.data('title'), desc: current.data('desc') } );
gallery.jp_carousel('getMeta', current.data('image-meta'));
gallery.jp_carousel('getFullSizeLink', current);
@@ -568,7 +614,7 @@ jQuery(document).ready(function($) {
gallery.jp_carousel('getComments', {'attachment_id': current.data('attachment-id'), 'offset': 0, 'clear': true});
$('#jp-carousel-comment-post-results').slideUp();
-
+
// $('<div />').html(sometext).text() is a trick to go to HTML to plain text (including HTML emntities decode, etc)
if ( current.data('caption') ) {
if ( $('<div />').html(current.data('caption')).text() == $('<div />').html(current.data('title')).text() )
@@ -593,7 +639,7 @@ jQuery(document).ready(function($) {
};
},
- loadSlide : function(){
+ loadSlide : function() {
return this.each(function(){
var slide = $(this);
slide.find('img')
@@ -642,13 +688,19 @@ jQuery(document).ready(function($) {
'left' : (info.width() - size.width) * 0.5,
'width' : size.width
});
+
+ if (isMobile){
+ photo_info.css('left', '0px');
+ photo_info.css('top', '-20px');
+ }
+
return this;
},
fitMeta : function(animated){
var newInfoTop = { top: ( $(window).height() / 100 * proportion + 5 ) + 'px' };
var newLeftWidth = { width: ( info.width() - (imageMeta.width() + 80) ) + 'px' };
-
+
if (animated) {
info.animate(newInfoTop);
leftColWrapper.animate(newLeftWidth);
@@ -666,27 +718,14 @@ jQuery(document).ready(function($) {
method = 'css',
max = gallery.jp_carousel('slideDimensions');
- if ( 0 === selected.length ) {
- dimensions.left = $(window).width();
- } else if ($this.is(selected)) {
- dimensions.left = ($(window).width() - dimensions.width) * 0.5;
- } else if ($this.is(selected.next())) {
- dimensions.left = gallery.width() - ( screenPadding * 0.75 );
- } else if ($this.is(selected.prev())) {
- dimensions.left = -dimensions.width + screenPadding * 0.75;
- } else {
- if ($this.is(selected.nextAll())) {
- dimensions.left = $(window).width();
- } else {
- dimensions.left = -dimensions.width;
- }
- }
+ dimensions.left = 0;
dimensions.top = ( (max.height - dimensions.height) * 0.5 ) + 40;
$this[method](dimensions);
});
},
texturize : function(text) {
+ text = new String(text); // make sure we get a string. Title "1" came in as int 1, for example, which did not support .replace().
text = text.replace(/'/g, '&#8217;').replace(/&#039;/g, '&#8217;').replace(/[\u2019]/g, '&#8217;');
text = text.replace(/"/g, '&#8221;').replace(/&#034;/g, '&#8221;').replace(/&quot;/g, '&#8221;').replace(/[\u201D]/g, '&#8221;');
text = text.replace(/([\w]+)=&#[\d]+;(.+?)&#[\d]+;/g, '$1="$2"'); // untexturize allowed HTML tags params double-quotes
@@ -700,7 +739,7 @@ jQuery(document).ready(function($) {
// Calculate the new src.
items.each(function(i){
var src_item = $(this),
- orig_size = src_item.data('orig-size') || 0,
+ orig_size = src_item.data('orig-size') || '',
max = gallery.jp_carousel('slideDimensions'),
parts = orig_size.split(',');
orig_size = {width: parseInt(parts[0], 10), height: parseInt(parts[1], 10)},
@@ -708,7 +747,7 @@ jQuery(document).ready(function($) {
large_file = src_item.data('large-file') || '';
src = src_item.data('orig-file');
-
+
src = gallery.jp_carousel('selectBestImageSize', {
orig_file : src,
orig_width : orig_size.width,
@@ -718,7 +757,7 @@ jQuery(document).ready(function($) {
medium_file : medium_file,
large_file : large_file
});
-
+
// Set the final src
$(this).data( 'gallery-src', src );
});
@@ -733,45 +772,49 @@ jQuery(document).ready(function($) {
attachment_id = src_item.data('attachment-id') || 0,
comments_opened = src_item.data('comments-opened') || 0,
image_meta = src_item.data('image-meta') || {},
- orig_size = src_item.data('orig-size') || 0,
- title = src_item.attr('title') || '',
+ orig_size = src_item.data('orig-size') || '',
+ title = src_item.data('image-title') || '',
description = src_item.data('image-description') || '',
caption = src_item.parents('dl').find('dd.gallery-caption').html() || '',
- src = src_item.data('gallery-src') || '',
+ src = src_item.data('gallery-src') || '',
medium_file = src_item.data('medium-file') || '',
- large_file = src_item.data('large-file') || '';
-
- if ( !attachment_id || !orig_size )
- return false; // break the loop if we are missing the data-* attributes
-
- title = gallery.jp_carousel('texturize', title);
- description = gallery.jp_carousel('texturize', description);
- caption = gallery.jp_carousel('texturize', caption);
-
- var slide = $('<div class="jp-carousel-slide"></div>')
- .hide()
- .css({
- 'position' : 'fixed',
- 'left' : i < start_index ? -1000 : gallery.width()
- })
- .append($('<img>'))
- .appendTo(gallery)
- .data('src', src )
- .data('title', title)
- .data('desc', description)
- .data('caption', caption)
- .data('attachment-id', attachment_id)
- .data('permalink', src_item.parents('a').attr('href'))
- .data('orig-size', orig_size)
- .data('comments-opened', comments_opened)
- .data('image-meta', image_meta)
- .data('medium-file', medium_file)
- .data('large-file', large_file)
- .jp_carousel('fitSlide', false);
-
-
- // Preloading all images
- slide.find('img').first().attr('src', src );
+ large_file = src_item.data('large-file') || '',
+ orig_file = src_item.data('orig-file') || '';
+
+ var tiledCaption = src_item.parents('div.tiled-gallery-item').find('div.tiled-gallery-caption').html();
+ if ( tiledCaption )
+ caption = tiledCaption;
+
+ if ( attachment_id && orig_size.length ) {
+ title = gallery.jp_carousel('texturize', title);
+ description = gallery.jp_carousel('texturize', description);
+ caption = gallery.jp_carousel('texturize', caption);
+
+ var slide = $('<div class="jp-carousel-slide"></div>')
+ .hide()
+ .css({
+ //'position' : 'fixed',
+ 'left' : i < start_index ? -1000 : gallery.width()
+ })
+ .append($('<img>'))
+ .appendTo(gallery)
+ .data('src', src )
+ .data('title', title)
+ .data('desc', description)
+ .data('caption', caption)
+ .data('attachment-id', attachment_id)
+ .data('permalink', src_item.parents('a').attr('href'))
+ .data('orig-size', orig_size)
+ .data('comments-opened', comments_opened)
+ .data('image-meta', image_meta)
+ .data('medium-file', medium_file)
+ .data('large-file', large_file)
+ .data('orig-file', orig_file)
+ .jp_carousel('fitSlide', false);
+
+ // Preloading all images
+ slide.find('img').first().attr('src', src );
+ }
});
return this;
},
@@ -779,13 +822,13 @@ jQuery(document).ready(function($) {
selectBestImageSize: function(args) {
if ( 'object' != typeof args )
args = {};
-
+
if ( 'undefined' == typeof args.orig_file )
return '';
-
+
if ( 'undefined' == typeof args.orig_width || 'undefined' == typeof args.max_width )
return args.orig_file;
-
+
if ( 'undefined' == typeof args.medium_file || 'undefined' == typeof args.large_file )
return args.orig_file;
@@ -797,19 +840,19 @@ jQuery(document).ready(function($) {
large_size_parts = (large_size != args.large_file) ? large_size.split('x') : [args.orig_width, 0],
large_width = parseInt( large_size_parts[0], 10 ),
large_height = parseInt( large_size_parts[1], 10 );
-
+
// Give devices with a higher devicePixelRatio higher-res images (Retina display = 2, Android phones = 1.5, etc)
if ('undefined' != typeof window.devicePixelRatio && window.devicePixelRatio > 1) {
args.max_width = args.max_width * window.devicePixelRatio;
args.max_height = args.max_height * window.devicePixelRatio;
}
- if ( medium_width >= args.max_width || medium_height >= args.max_height )
- return args.medium_file;
-
if ( large_width >= args.max_width || large_height >= args.max_height )
return args.large_file;
+ if ( medium_width >= args.max_width || medium_height >= args.max_height )
+ return args.medium_file;
+
return args.orig_file;
},
@@ -826,14 +869,14 @@ jQuery(document).ready(function($) {
return;
if ( ! args.replacements || 'undefined' == typeof args.replacements )
return args.text;
- return args.text.replace(/{(\d+)}/g, function(match, number) {
+ return args.text.replace(/{(\d+)}/g, function(match, number) {
return typeof args.replacements[number] != 'undefined' ? args.replacements[number] : match;
});
},
shutterSpeed: function(d) {
if (d >= 1)
- Math.round(d) + 's';
+ return Math.round(d) + 's';
var df = 1, top = 1, bot = 1;
var limit = 1e5; //Increase for greater precision.
while (df != d && limit-- > 0) {
@@ -887,16 +930,16 @@ jQuery(document).ready(function($) {
});
return value;
},
-
+
getTitleDesc: function( data ) {
var title ='', desc = '', markup = '', target, commentWrappere;
-
+
target = $( 'div.jp-carousel-titleanddesc', 'div.jp-carousel-wrap' );
target.hide();
-
+
title = gallery.jp_carousel('parseTitleDesc', data.title) || '';
desc = gallery.jp_carousel('parseTitleDesc', data.desc) || '';
-
+
if ( title.length || desc.length ) {
// $('<div />').html(sometext).text() is a trick to go to HTML to plain text (including HTML emntities decode, etc)
if ( $('<div />').html(title).text() == $('<div />').html(desc).text() )
@@ -911,16 +954,16 @@ jQuery(document).ready(function($) {
$( 'div#jp-carousel-comment-form-container' ).css('margin-top', '20px');
$( 'div#jp-carousel-comments-loading' ).css('margin-top', '20px');
},
-
+
getMeta: function( meta ) {
if ( !meta || 1 != jetpackCarouselStrings.display_exif )
return false;
-
+
var $ul = $( '<ul></ul>' );
$.each( meta, function( key, val ) {
if ( 0 === parseFloat(val) || !val.length || -1 === $.inArray( key, [ 'camera', 'aperture', 'shutter_speed', 'focal_length' ] ) )
return;
-
+
switch( key ) {
case 'focal_length':
val = val + 'mm';
@@ -935,7 +978,7 @@ jQuery(document).ready(function($) {
// making jslint happy
break;
}
-
+
$ul.append( '<li><h5>' + jetpackCarouselStrings[key] + '</h5>' + val + '</li>' );
});
@@ -949,23 +992,23 @@ jQuery(document).ready(function($) {
getFullSizeLink: function(current) {
if(!current || !current.data)
return false;
- var original = current.data('src').replace(/\?.+$/, ''),
+ var original = current.data('orig-file').replace(/\?.+$/, ''),
origSize = current.data('orig-size').split(','),
permalink = $( '<a>'+gallery.jp_carousel('format', {'text': jetpackCarouselStrings.download_original, 'replacements': origSize})+'</a>' )
.addClass( 'jp-carousel-image-download' )
.attr( 'href', original )
.attr( 'target', '_blank' );
-
+
$( 'div.jp-carousel-image-meta', 'div.jp-carousel-wrap' )
.append( permalink );
},
-
+
getMap: function( meta ) {
if ( !meta.latitude || !meta.longitude || 1 != jetpackCarouselStrings.display_geo )
return;
-
- var latitude = meta.latitude,
- longitude = meta.longitude,
+
+ var latitude = meta.latitude,
+ longitude = meta.longitude,
$metabox = $( 'div.jp-carousel-image-meta', 'div.jp-carousel-wrap' ),
$mapbox = $( '<div></div>' ),
style = '&scale=2&style=feature:all|element:all|invert_lightness:true|hue:0x0077FF|saturation:-50|lightness:-5|gamma:0.91';
@@ -1003,23 +1046,23 @@ jQuery(document).ready(function($) {
getComments: function( args ) {
if ( 'object' != typeof args )
args = {};
-
+
if ( ! args.attachment_id || 'undefined' == typeof args.attachment_id )
return;
-
+
if ( ! args.offset || 'undefined' == typeof args.offset || args.offset < 1 )
args.offset = 0;
-
+
var comments = $('.jp-carousel-comments'),
commentsLoading = $('#jp-carousel-comments-loading');
-
+
commentsLoading.show();
-
+
if ( args.clear ) {
comments.hide();
comments.empty();
}
-
+
$.ajax({
type: 'GET',
url: jetpackCarouselStrings.ajaxurl,
@@ -1056,7 +1099,7 @@ jQuery(document).ready(function($) {
+ '</div>'
);
comments.append(comment);
-
+
// Set the interval to check for a new page of comments.
clearInterval( commentInterval );
commentInterval = setInterval( function() {
@@ -1066,7 +1109,7 @@ jQuery(document).ready(function($) {
}
}, 150 );
});
-
+
// Verify (late) that the user didn't repeatldy click the arrows really fast, in which case the requested
// attachment id might no longer match the current attachment id by the time we get the data back or a now
// registered infiniscroll event kicks in, so we don't ever display comments for the wrong image by mistake.
@@ -1079,7 +1122,7 @@ jQuery(document).ready(function($) {
// Increase the height of the background, semi-transparent overlay to match the new length of the comments list.
$('.jp-carousel-overlay').height( $(window).height() + titleAndDescription.height() + commentForm.height() + ( (comments.height() > 0) ? comments.height() : imageMeta.height() ) + 200 );
-
+
comments.show();
commentsLoading.hide();
},
@@ -1130,18 +1173,28 @@ jQuery(document).ready(function($) {
};
- // register the event listener for staring the gallery
- $( document.body ).on( 'click', 'div.gallery', function(e) {
+ // register the event listener for starting the gallery
+ $( document.body ).on( 'click', 'div.gallery,div.tiled-gallery', function(e) {
+ if ( ! $(this).jp_carousel( 'testForData', e.currentTarget ) )
+ return;
if ( $(e.target).parent().hasClass('gallery-caption') )
return;
e.preventDefault();
- $(this).jp_carousel('open', {start_index: $(this).find('.gallery-item').index($(e.target).parents('.gallery-item'))});
+ $(this).jp_carousel('open', {start_index: $(this).find('.gallery-item, .tiled-gallery-item').index($(e.target).parents('.gallery-item, .tiled-gallery-item'))});
});
- // start on page load if hash exists
- if ( document.location.hash && document.location.hash.match(/jp-carousel-(\d+)/) ) {
- $(document).ready(function(){
- var gallery = $('div.gallery'), index = -1, n = document.location.hash.match(/jp-carousel-(\d+)/);
+ // Set an interval on page load to load the carousel if hash exists and not already opened.
+ // Makes carousel work on page load and when back button leads to same URL with carousel hash (ie: no actual document.ready trigger)
+ $(document).ready(function(){
+ var jp_carousel_open_interval = window.setInterval(function(){
+ // We should have a URL hash by now.
+ if ( ! document.location.hash || ! document.location.hash.match(/jp-carousel-(\d+)/) )
+ return;
+
+ var gallery = $('div.gallery, div.tiled-gallery'), index = -1, n = document.location.hash.match(/jp-carousel-(\d+)/);
+
+ if ( ! $(this).jp_carousel( 'testForData', gallery ) )
+ return;
n = parseInt(n[1], 10);
@@ -1153,7 +1206,10 @@ jQuery(document).ready(function($) {
});
if ( index != -1 )
- gallery.jp_carousel('open', {start_index: index});
- });
- }
+ gallery.jp_carousel('open', {start_index: index}); // open method checks if already opened
+ }, 1000);
+ });
});
+
+// Swipe gesture detection
+(function($){$.fn.touchwipe=function(settings){var config={min_move_x:20,min_move_y:20,wipeLeft:function(){},wipeRight:function(){},wipeUp:function(){},wipeDown:function(){},preventDefaultEvents:true};if(settings)$.extend(config,settings);this.each(function(){var startX;var startY;var isMoving=false;function cancelTouch(){this.removeEventListener('touchmove',onTouchMove);startX=null;isMoving=false}function onTouchMove(e){if(config.preventDefaultEvents){e.preventDefault()}if(isMoving){var x=e.touches[0].pageX;var y=e.touches[0].pageY;var dx=startX-x;var dy=startY-y;if(Math.abs(dx)>=config.min_move_x){cancelTouch();if(dx>0){config.wipeLeft()}else{config.wipeRight()}}else if(Math.abs(dy)>=config.min_move_y){cancelTouch();if(dy>0){config.wipeDown()}else{config.wipeUp()}}}}function onTouchStart(e){if(e.touches.length==1){startX=e.touches[0].pageX;startY=e.touches[0].pageY;isMoving=true;this.addEventListener('touchmove',onTouchMove,false)}}if('ontouchstart'in document.documentElement){this.addEventListener('touchstart',onTouchStart,false)}});return this}})(jQuery);
diff --git a/plugins/jetpack/modules/carousel/jetpack-carousel.php b/plugins/jetpack/modules/carousel/jetpack-carousel.php
index 3d48681b..314dd7b2 100644
--- a/plugins/jetpack/modules/carousel/jetpack-carousel.php
+++ b/plugins/jetpack/modules/carousel/jetpack-carousel.php
@@ -76,7 +76,7 @@ class Jetpack_Carousel {
}
function enqueue_assets( $output ) {
- if ( ! empty( $output ) ) {
+ if ( ! empty( $output ) && ! apply_filters( 'jp_carousel_force_enable', false ) ) {
// Bail because someone is overriding the [gallery] shortcode.
remove_filter( 'gallery_style', array( $this, 'add_data_to_container' ) );
remove_filter( 'wp_get_attachment_link', array( $this, 'add_data_to_images' ) );
@@ -86,12 +86,7 @@ class Jetpack_Carousel {
do_action( 'jp_carousel_thumbnails_shown' );
if ( $this->first_run ) {
- if ( ! has_action( 'wp_enqueue_scripts', 'register_spin_scripts' ) ) {
- wp_enqueue_script( 'spin', plugins_url( 'spin.js', __FILE__ ), false, '1.2.4' );
- wp_enqueue_script( 'jquery.spin', plugins_url( 'jquery.spin.js', __FILE__ ) , array( 'jquery', 'spin' ) );
- }
-
- wp_enqueue_script( 'jetpack-carousel', plugins_url( 'jetpack-carousel.js', __FILE__ ), array( 'jquery' ), $this->asset_version( '20120629' ), true );
+ wp_enqueue_script( 'jetpack-carousel', plugins_url( 'jetpack-carousel.js', __FILE__ ), array( 'jquery.spin' ), $this->asset_version( '20130109' ), true );
// Note: using home_url() instead of admin_url() for ajaxurl to be sure to get same domain on wpcom when using mapped domains (also works on self-hosted)
// Also: not hardcoding path since there is no guarantee site is running on site root in self-hosted context.
@@ -140,7 +135,14 @@ class Jetpack_Carousel {
$localize_strings = apply_filters( 'jp_carousel_localize_strings', $localize_strings );
wp_localize_script( 'jetpack-carousel', 'jetpackCarouselStrings', $localize_strings );
wp_enqueue_style( 'jetpack-carousel', plugins_url( 'jetpack-carousel.css', __FILE__ ), array(), $this->asset_version( '20120629' ) );
-
+ global $is_IE;
+ if( $is_IE )
+ {
+ $msie = strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE' ) + 4;
+ $version = (float) substr( $_SERVER['HTTP_USER_AGENT'], $msie, strpos( $_SERVER['HTTP_USER_AGENT'], ';', $msie ) - $msie );
+ if( $version < 9 )
+ wp_enqueue_style( 'jetpack-carousel-ie8fix', plugins_url( 'jetpack-carousel-ie8fix.css', __FILE__ ), array(), $this->asset_version( '20121024' ) );
+ }
do_action( 'jp_carousel_enqueue_assets', $this->first_run, $localize_strings );
$this->first_run = false;
@@ -154,10 +156,11 @@ class Jetpack_Carousel {
return $html;
$attachment_id = intval( $attachment_id );
- $orig_file = wp_get_attachment_url( $attachment_id );
+ $orig_file = wp_get_attachment_image_src( $attachment_id, 'full' );
+ $orig_file = isset( $orig_file[0] ) ? $orig_file[0] : wp_get_attachment_url( $attachment_id );
$meta = wp_get_attachment_metadata( $attachment_id );
$size = isset( $meta['width'] ) ? intval( $meta['width'] ) . ',' . intval( $meta['height'] ) : '';
- $img_meta = $meta['image_meta'];
+ $img_meta = ( ! empty( $meta['image_meta'] ) ) ? (array) $meta['image_meta'] : array();
$comments_opened = intval( comments_open( $attachment_id ) );
/*
@@ -167,10 +170,10 @@ class Jetpack_Carousel {
* $content_width has no filter we could temporarily de-register, run wp_get_attachment_image_src(), then
* re-register. So using returned file URL instead, which we can define the sizes from through filename
* parsing in the JS, as this is a failsafe file reference.
- *
+ *
* EG with Twenty Eleven activated:
* array(4) { [0]=> string(82) "http://vanillawpinstall.blah/wp-content/uploads/2012/06/IMG_3534-1024x764.jpg" [1]=> int(584) [2]=> int(435) [3]=> bool(true) }
- *
+ *
* EG with Twenty Ten activated:
* array(4) { [0]=> string(82) "http://vanillawpinstall.blah/wp-content/uploads/2012/06/IMG_3534-1024x764.jpg" [1]=> int(640) [2]=> int(477) [3]=> bool(true) }
*/
@@ -178,11 +181,12 @@ class Jetpack_Carousel {
$medium_file_info = wp_get_attachment_image_src( $attachment_id, 'medium' );
$medium_file = isset( $medium_file_info[0] ) ? $medium_file_info[0] : '';
- $large_file_info = wp_get_attachment_image_src( $attachment_id, 'large' );
- $large_file = isset( $large_file_info[0] ) ? $large_file_info[0] : '';
+ $large_file_info = wp_get_attachment_image_src( $attachment_id, 'large' );
+ $large_file = isset( $large_file_info[0] ) ? $large_file_info[0] : '';
- $attachment = get_post( $attachment_id );
- $attachment_desc = wpautop( wptexturize( $attachment->post_content ) );
+ $attachment = get_post( $attachment_id );
+ $attachment_title = wptexturize( $attachment->post_title );
+ $attachment_desc = wpautop( wptexturize( $attachment->post_content ) );
// Not yet providing geo-data, need to "fuzzify" for privacy
if ( ! empty( $img_meta ) ) {
@@ -192,17 +196,18 @@ class Jetpack_Carousel {
}
}
- $img_meta = json_encode( $img_meta );
+ $img_meta = json_encode( array_map( 'strval', $img_meta ) );
$html = str_replace(
'<img ',
sprintf(
- '<img data-attachment-id="%1$d" data-orig-file="%2$s" data-orig-size="%3$s" data-comments-opened="%4$s" data-image-meta="%5$s" data-image-description="%6$s" data-medium-file="%7$s" data-large-file="%8$s" ',
+ '<img data-attachment-id="%1$d" data-orig-file="%2$s" data-orig-size="%3$s" data-comments-opened="%4$s" data-image-meta="%5$s" data-image-title="%6$s" data-image-description="%7$s" data-medium-file="%8$s" data-large-file="%9$s" ',
$attachment_id,
esc_attr( $orig_file ),
$size,
$comments_opened,
esc_attr( $img_meta ),
+ esc_attr( $attachment_title ),
esc_attr( $attachment_desc ),
esc_attr( $medium_file ),
esc_attr( $large_file )
@@ -230,24 +235,24 @@ class Jetpack_Carousel {
return $html;
}
-
+
function get_attachment_comments() {
if ( ! headers_sent() )
header('Content-type: text/javascript');
-
+
do_action('jp_carousel_check_blog_user_privileges');
-
+
$attachment_id = ( isset( $_REQUEST['id'] ) ) ? (int) $_REQUEST['id'] : 0;
$offset = ( isset( $_REQUEST['offset'] ) ) ? (int) $_REQUEST['offset'] : 0;
-
+
if ( ! $attachment_id ) {
echo json_encode( __( 'Missing attachment ID.', 'jetpack' ) );
die();
}
-
+
if ( $offset < 1 )
$offset = 0;
-
+
$comments = get_comments( array(
'status' => 'approve',
'order' => ( 'asc' == get_option('comment_order') ) ? 'ASC' : 'DESC',
@@ -255,9 +260,9 @@ class Jetpack_Carousel {
'offset' => $offset,
'post_id' => $attachment_id,
) );
-
+
$out = array();
-
+
// Can't just send the results, they contain the commenter's email address.
foreach ( $comments as $comment ) {
$author_markup = '<a href="' . esc_url( $comment->comment_author_url ) . '">' . esc_html( $comment->comment_author ) . '</a>';
@@ -270,42 +275,42 @@ class Jetpack_Carousel {
'content' => wpautop($comment->comment_content),
);
}
-
+
die( json_encode( $out ) );
}
function post_attachment_comment() {
if ( ! headers_sent() )
header('Content-type: text/javascript');
-
+
if ( empty( $_POST['nonce'] ) || ! wp_verify_nonce($_POST['nonce'], 'carousel_nonce') )
die( json_encode( array( 'error' => __( 'Nonce verification failed.', 'jetpack' ) ) ) );
-
+
$_blog_id = (int) $_POST['blog_id'];
$_post_id = (int) $_POST['id'];
$comment = $_POST['comment'];
-
+
if ( empty( $_blog_id ) )
die( json_encode( array( 'error' => __( 'Missing target blog ID.', 'jetpack' ) ) ) );
-
+
if ( empty( $_post_id ) )
die( json_encode( array( 'error' => __( 'Missing target post ID.', 'jetpack' ) ) ) );
-
+
if ( empty( $comment ) )
die( json_encode( array( 'error' => __( 'No comment text was submitted.', 'jetpack' ) ) ) );
// Used in context like NewDash
$switched = false;
- if ( $_blog_id != get_current_blog_id() ) {
+ if ( is_multisite() && $_blog_id != get_current_blog_id() ) {
switch_to_blog( $_blog_id );
$switched = true;
}
-
+
do_action('jp_carousel_check_blog_user_privileges');
if ( ! comments_open( $_post_id ) )
die( json_encode( array( 'error' => __( 'Comments on this post are closed.', 'jetpack' ) ) ) );
-
+
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$user_id = $user->ID;
@@ -353,10 +358,10 @@ class Jetpack_Carousel {
die( json_encode( array( 'comment_id' => $comment_id, 'comment_status' => $comment_status ) ) );
}
-
+
function register_settings() {
add_settings_section('carousel_section', __( 'Image Gallery Carousel', 'jetpack' ), array( $this, 'carousel_section_callback' ), 'media');
-
+
if ( ! $this->in_jetpack ) {
add_settings_field('carousel_enable_it', __( 'Enable carousel', 'jetpack' ), array( $this, 'carousel_enable_it_callback' ), 'media', 'carousel_section' );
register_setting( 'media', 'carousel_enable_it', array( $this, 'carousel_enable_it_sanitize' ) );
@@ -364,7 +369,7 @@ class Jetpack_Carousel {
add_settings_field('carousel_background_color', __( 'Background color', 'jetpack' ), array( $this, 'carousel_background_color_callback' ), 'media', 'carousel_section' );
register_setting( 'media', 'carousel_background_color', array( $this, 'carousel_background_color_sanitize' ) );
-
+
add_settings_field('carousel_display_exif', __( 'Metadata', 'jetpack'), array( $this, 'carousel_display_exif_callback' ), 'media', 'carousel_section' );
register_setting( 'media', 'carousel_display_exif', array( $this, 'carousel_display_exif_sanitize' ) );
@@ -386,7 +391,7 @@ class Jetpack_Carousel {
}
return ( 1 == $value ) ? 1 : 0;
}
-
+
function sanitize_1or0_option( $value ) {
return ( 1 == $value ) ? 1 : 0;
}
@@ -435,7 +440,7 @@ class Jetpack_Carousel {
function carousel_display_geo_sanitize( $value ) {
return $this->sanitize_1or0_option( $value );
- }
+ }
function carousel_background_color_callback() {
$this->settings_select( 'carousel_background_color', array( 'black' => __( 'Black', 'jetpack' ), 'white' => __( 'White', 'jetpack', 'jetpack' ) ) );
diff --git a/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css b/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css
new file mode 100644
index 00000000..0d010eb5
--- /dev/null
+++ b/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css
@@ -0,0 +1,1106 @@
+/* This file was automatically generated on Jan 29 2013 22:51:19 */
+
+* {
+ line-height:inherit; /* prevent declarations of line-height in the universal selector */
+}
+
+.jp-carousel-overlay {
+ background: #000;
+}
+
+div.jp-carousel-fadeaway {
+ background: -moz-linear-gradient(bottom, rgba(0,0,0,0.5), rgba(0,0,0,0));
+ background: -webkit-gradient(linear, right bottom, right top, from(rgba(0,0,0,0.5)), to(rgba(0,0,0,0)));
+ position: fixed;
+ bottom: 0;
+ z-index: 2147483647;
+ width: 100%;
+ height: 15px;
+}
+
+.jp-carousel-next-button span,
+.jp-carousel-previous-button span {
+ background: url(.././images/arrows.png) no-repeat center center;
+ background-size: 200px 126px;
+}
+
+@media
+only screen and (-webkit-min-device-pixel-ratio: 1.5),
+only screen and (-o-min-device-pixel-ratio: 3/2),
+only screen and (min--moz-device-pixel-ratio: 1.5),
+only screen and (min-device-pixel-ratio: 1.5) {
+ .jp-carousel-next-button span,
+ .jp-carousel-previous-button span {
+ background-image: url(.././images/arrows-2x.png);
+ }
+}
+
+.jp-carousel-wrap {
+ font-family: "Helvetica Neue", sans-serif !important;
+}
+
+.jp-carousel-info {
+ position: absolute;
+ bottom: 0;
+ text-align: right !important;
+ -webkit-font-smoothing: subpixel-antialiased !important;
+}
+
+.jp-carousel-info ::selection {
+ background: #68c9e8; /* Safari */
+ color: #fff;
+ }
+
+.jp-carousel-info ::-moz-selection {
+ background: #68c9e8; /* Firefox */
+ color: #fff;
+}
+
+.jp-carousel-photo-info {
+ position: relative;
+ -webkit-transition: 400ms ease-out;
+ -moz-transition: 400ms ease-out;
+ -o-transition: 400ms ease-out;
+ transition: 400ms ease-out;
+ right: 25%;
+ width: 50%;
+}
+
+.jp-carousel-info h2 {
+ background: none !important;
+ border: none !important;
+ color: #999;
+ display: block !important;
+ font: normal 13px/1.25em "Helvetica Neue", sans-serif !important;
+ letter-spacing: 0 !important;
+ margin: 7px 0 0 0 !important;
+ padding: 10px 0 0 !important;
+ overflow: hidden;
+ text-align: right;
+ text-shadow: none !important;
+ text-transform: none !important;
+ -webkit-font-smoothing: subpixel-antialiased;
+}
+
+.jp-carousel-next-button,
+.jp-carousel-previous-button {
+ text-indent: -9999px;
+ overflow: hidden;
+ cursor: pointer;
+}
+
+.jp-carousel-next-button span,
+.jp-carousel-previous-button span {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 82px;
+ zoom: 1;
+ filter: alpha(opacity=20);
+ opacity: 0.2;
+ -webkit-transition: 500ms opacity ease-out;
+ -moz-transition: 500ms opacity ease-out;
+ -o-transition: 500ms opacity ease-out;
+ transition: 500ms opacity ease-out;
+}
+
+.jp-carousel-next-button:hover span,
+.jp-carousel-previous-button:hover span {
+ filter: alpha(opacity=60);
+ opacity: 0.6;
+}
+.jp-carousel-next-button span {
+ background-position: -110px center;
+ left: 0;
+}
+
+.jp-carousel-previous-button span {
+ background-position: -10px center;
+ right:0;
+}
+
+.jp-carousel-buttons {
+ margin:-18px -20px 15px;
+ padding:8px 10px;
+ border-bottom:1px solid #222;
+ background: #222;
+ text-align: center;
+}
+
+div.jp-carousel-buttons a {
+ border: none !important;
+ color: #999;
+ font: normal 11px/1.2em "Helvetica Neue", sans-serif !important;
+ letter-spacing: 0 !important;
+ padding: 5px 0 5px 2px;
+ text-decoration: none !important;
+ text-shadow: none !important;
+ vertical-align: baseline !important;
+ -webkit-font-smoothing: subpixel-antialiased;
+}
+
+div.jp-carousel-buttons a:hover {
+ color: #68c9e8;
+ border: none !important;
+ -webkit-transition: none !important;
+ -moz-transition: none !important;
+ -o-transition: none !important;
+ transition: none !important;
+}
+
+.jp-carousel-slide, .jp-carousel-slide img, .jp-carousel-next-button,
+.jp-carousel-previous-button {
+ -webkit-transform:translate3d(0, 0, 0);
+ -moz-transform:translate3d(0, 0, 0);
+ -o-transform:translate3d(0, 0, 0);
+ -ms-transform:translate3d(0, 0, 0);
+}
+
+.jp-carousel-slide {
+ position:absolute;
+ width:0;
+ bottom:0;
+ background-color:#000;
+ border-radius:2px;
+ -webkit-border-radius:2px;
+ -moz-border-radius:2px;
+ -ms-border-radius:2px;
+ -o-border-radius:2px;
+ -webkit-transition: 400ms ease-out;
+ -moz-transition: 400ms ease-out;
+ -o-transition: 400ms ease-out;
+ transition: 400ms ease-out;
+}
+
+.jp-carousel-slide img {
+ display: block;
+ width: 100% !important;
+ height: 100% !important;
+ max-width: 100% !important;
+ max-height: 100% !important;
+ background: none !important;
+ border: none !important;
+ padding: 0 !important;
+ -webkit-box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+ -moz-box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+ zoom: 1;
+ filter: alpha(opacity=25);
+ opacity: 0.25;
+ -webkit-transition: opacity 400ms linear;
+ -moz-transition: opacity 400ms linear;
+ -o-transition: opacity 400ms linear;
+ transition: opacity 400ms linear;
+}
+
+.jp-carousel-slide.selected img {
+ filter: alpha(opacity=100);
+ opacity: 1;
+}
+
+.jp-carousel-close-hint {
+ color: #999;
+ cursor: default;
+ letter-spacing: 0 !important;
+ padding:0.35em 0 0;
+ position: absolute;
+ text-align: right;
+ width: 90%;
+ -webkit-transition: color 200ms linear;
+ -moz-transition: color 200ms linear;
+ -o-transition: color 200ms linear;
+ transition: color 200ms linear;
+}
+
+.jp-carousel-close-hint span {
+ cursor: pointer;
+ background-color: black;
+ background-color: rgba(0,0,0,0.8);
+ display: block;
+ height: 22px;
+ font: 400 24px/1 "Helvetica Neue", sans-serif !important;
+ line-height: 22px;
+ margin: 0 0.4em 0 0;
+ text-align: center;
+ vertical-align: middle;
+ width: 22px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-transition: border-color 200ms linear;
+ -moz-transition: border-color 200ms linear;
+ -o-transition: border-color 200ms linear;
+ transition: border-color 200ms linear;
+}
+
+.jp-carousel-close-hint:hover {
+ cursor: default;
+ color: #fff;
+}
+
+.jp-carousel-close-hint:hover span {
+ border-color: #fff;
+}
+
+div.jp-carousel-buttons a.jp-carousel-like,
+div.jp-carousel-buttons a.jp-carousel-reblog,
+div.jp-carousel-buttons a.jp-carousel-commentlink,
+a.jp-carousel-image-download {
+ background: url(.././images/carousel-sprite.png?4) no-repeat;
+ background-size: 16px 160px;
+}
+
+div.jp-carousel-buttons a.jp-carousel-reblog,
+div.jp-carousel-buttons a.jp-carousel-commentlink {
+ margin:0 0 0 14px !important;
+}
+
+div.jp-carousel-buttons a.jp-carousel-reblog.reblogged,
+div.jp-carousel-buttons a.jp-carousel-like.liked {
+ background-color: #303030;
+ padding-left: 8px !important;
+ border-radius: 2px;
+ border-radius:2px;
+ -webkit-border-radius:2px;
+ -moz-border-radius:2px;
+ -ms-border-radius:2px;
+ -o-border-radius:2px;
+}
+
+div.jp-carousel-buttons a.jp-carousel-reblog.reblogged {
+ margin:0 -12px 0 2px !important;
+}
+
+
+div.jp-carousel-buttons a.jp-carousel-reblog,
+div.jp-carousel-buttons a.jp-carousel-reblog.reblogged:hover {
+ background-position: 6px -36px;
+ padding-right: 26px !important;
+ color: #999;
+}
+
+div.jp-carousel-buttons a.jp-carousel-commentlink {
+ background-position: 0px -116px;
+ padding-right: 19px !important;
+}
+
+div.jp-carousel-buttons a.jp-carousel-reblog.reblogged:hover {
+ cursor: default;
+}
+
+div.jp-carousel-buttons a.jp-carousel-reblog:hover {
+ background-position: 6px -56px;
+ color: #68c9e8;
+}
+
+div.jp-carousel-buttons a.jp-carousel-like {
+ background-position: 5px 5px;
+ padding-right: 24px !important;
+}
+
+div.jp-carousel-buttons a.jp-carousel-like:hover {
+ background-position: 5px -15px;
+}
+
+@media
+only screen and (-webkit-min-device-pixel-ratio: 1.5),
+only screen and (-o-min-device-pixel-ratio: 3/2),
+only screen and (min--moz-device-pixel-ratio: 1.5),
+only screen and (min-device-pixel-ratio: 1.5) {
+ div.jp-carousel-buttons a.jp-carousel-like,
+ div.jp-carousel-buttons a.jp-carousel-reblog,
+ div.jp-carousel-buttons a.jp-carousel-commentlink,
+ a.jp-carousel-image-download {
+ background-image: url(.././images/carousel-sprite-2x.png?4);
+ }
+}
+
+/* reblog */
+div#carousel-reblog-box {
+ background: #222;
+ background: -moz-linear-gradient(bottom, #222, #333);
+ background: -webkit-gradient(linear, right bottom, right top, from(#222), to(#333));
+ padding: 3px 0 0;
+ display: none;
+ margin: 5px auto 0;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+ -webkit-box-shadow: 0 0 20px rgba(0,0,0,0.9);
+ -moz-box-shadow: 0 0 20px rgba(0,0,0,0.9);
+ box-shadow: 0 0 20px rgba(0,0,0,0.9);
+ height: 74px;
+ width: 565px;
+}
+
+#carousel-reblog-box textarea {
+ background: #999;
+ font: 13px/1.4 "Helvetica Neue", sans-serif !important;
+ color: #444;
+ padding: 3px 6px;
+ width: 370px;
+ height: 48px;
+ float: right;
+ margin: 6px 9px 0 9px;
+ border: 1px solid #666;
+ -webkit-box-shadow: inset 2px 2px 2px rgba(0,0,0,0.2);
+ box-shadow: inset 2px 2px 2px rgba(0,0,0,0.2);
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+}
+
+#carousel-reblog-box textarea:focus {
+ background: #ccc;
+ color: #222;
+}
+
+#carousel-reblog-box label {
+ color: #aaa;
+ font-size: 11px;
+ padding-left: 2px;
+ padding-right: 2px;
+ display: inline;
+ font-weight: normal;
+}
+
+#carousel-reblog-box select {
+ width: 110px;
+ padding: 0;
+ font-size: 12px;
+ font-family: "Helvetica Neue", sans-serif !important;
+ background: #333;
+ color: #eee;
+ border: 1px solid #444;
+ margin-top:5px;
+}
+
+#carousel-reblog-box .submit,
+#wrapper #carousel-reblog-box p.response {
+ float: right;
+ width: 154px;
+ padding-top: 0;
+ padding-right: 1px;
+ overflow: hidden;
+ height: 34px;
+ margin:3px 2px 0 0 !important;
+}
+
+#wrapper #carousel-reblog-box p.response {
+ font-size: 13px;
+ clear: none;
+ padding-right: 2px;
+ height: 34px;
+ color: #aaa;
+}
+
+#carousel-reblog-box input#carousel-reblog-submit, #jp-carousel-comment-form-button-submit {
+ font: 13px/24px "Helvetica Neue", sans-serif !important;
+ margin-top: 8px;
+ padding: 0 10px !important;
+ border-radius: 1em;
+ height: 24px;
+ color: #333;
+ cursor:pointer;
+ font-weight: normal;
+ background: #aaa;
+ background: -moz-linear-gradient(bottom, #aaa, #ccc);
+ background: -webkit-gradient(linear, right bottom, right top, from(#aaa), to(#ccc));
+ border: 1px solid #444;
+}
+
+#carousel-reblog-box input#carousel-reblog-submit:hover, #jp-carousel-comment-form-button-submit:hover {
+ background: #ccc;
+ background: -moz-linear-gradient(bottom, #ccc, #eee);
+ background: -webkit-gradient(linear, right bottom, right top, from(#ccc), to(#eee));
+}
+
+#carousel-reblog-box .canceltext {
+ color: #aaa;
+ font-size: 11px;
+ line-height: 24px;
+}
+
+#carousel-reblog-box .canceltext a {
+ color: #fff;
+}
+/* reblog end */
+
+
+/** Title and Desc Start **/
+.jp-carousel-titleanddesc {
+ border-top: 1px solid #222;
+ color: #999;
+ font-size: 15px;
+ padding-top: 24px;
+ margin-bottom: 20px;
+ font-weight:400;
+}
+.jp-carousel-titleanddesc-title {
+ font: 300 1.5em/1.1 "Helvetica Neue", sans-serif !important;
+ text-transform: none !important; /* prevents uppercase from leaking through */
+ color: #fff;
+ margin: 0 0 15px;
+ padding:0;
+}
+
+.jp-carousel-titleanddesc-desc p {
+ color: #999;
+ line-height:1.4;
+ margin-bottom: 0.75em;
+}
+
+.jp-carousel-titleanddesc p a,
+.jp-carousel-comments p a,
+.jp-carousel-info h2 a {
+ color: #fff !important;
+ border: none !important;
+ text-decoration: underline !important;
+ font-weight: normal !important;
+ font-style: normal !important;
+}
+
+.jp-carousel-titleanddesc p strong,
+.jp-carousel-titleanddesc p b {
+ font-weight: bold;
+ color: #999;
+}
+
+.jp-carousel-titleanddesc p em,
+.jp-carousel-titleanddesc p i {
+ font-style: italic;
+ color: #999;
+}
+
+
+.jp-carousel-titleanddesc p a:hover,
+.jp-carousel-comments p a:hover,
+.jp-carousel-info h2 a:hover {
+ color: #68c9e8 !important;
+}
+
+.jp-carousel-titleanddesc p:empty {
+ display: none;
+}
+
+.jp-carousel-photo-info h1:before,
+.jp-carousel-photo-info h1:after,
+.jp-carousel-left-column-wrapper h1:before,
+.jp-carousel-left-column-wrapper h1:after {
+ content:none !important;
+}
+/** Title and Desc End **/
+
+/** Meta Box Start **/
+.jp-carousel-image-meta {
+ background: #111;
+ border: 1px solid #222;
+ color: #fff;
+ font-size: 13px;
+ font: 12px/1.4 "Helvetica Neue", sans-serif !important;
+ overflow: hidden;
+ padding: 18px 20px;
+ width: 209px !important;
+}
+
+.jp-carousel-image-meta li,
+.jp-carousel-image-meta h5 {
+ font-family: "Helvetica Neue", sans-serif !important;
+ position: inherit !important;
+ top: auto !important;
+ left: auto !important;
+ right: auto !important;
+ bottom: auto !important;
+ background: none !important;
+ border: none !important;
+ font-weight: 400 !important;
+ line-height: 1.3em !important;
+}
+
+.jp-carousel-image-meta ul {
+ margin: 0 !important;
+ padding: 0 !important;
+ list-style: none !important;
+}
+
+.jp-carousel-image-meta li {
+ width: 48% !important;
+ float: right !important;
+ margin: 0 0 15px 2% !important;
+ color: #fff !important;
+ font-size:13px !important;
+}
+
+.jp-carousel-image-meta h5 {
+ color: #999 !important;
+ text-transform: uppercase !important;
+ font-size:10px !important;
+ margin:0 0 2px !important;
+ letter-spacing: 0.1em !important;
+}
+
+a.jp-carousel-image-download {
+ padding-right: 23px;
+ display: inline-block;
+ clear: both;
+ color: #999;
+ line-height: 1;
+ font-weight: 400;
+ font-size: 13px;
+ text-decoration: none;
+ background-position: 0 -82px;
+}
+
+a.jp-carousel-image-download span.photo-size {
+ font-size: 11px;
+ border-radius: 1em;
+ margin-right: 2px;
+ display: inline-block;
+}
+
+a.jp-carousel-image-download span.photo-size-times {
+ padding: 0 2px 0 1px;
+}
+
+a.jp-carousel-image-download:hover {
+ background-position: 0 -102px;
+ color: #68c9e8;
+ border: none !important;
+}
+
+/** Meta Box End **/
+
+/** GPS Map Start **/
+.jp-carousel-image-map {
+ position: relative;
+ margin: -20px -20px 20px;
+ border-bottom: 1px solid rgba( 255, 255, 255, 0.17 );
+ height: 154px;
+}
+
+.jp-carousel-image-map img.gmap-main {
+ -moz-border-radius-topleft: 6px;
+ border-top-right-radius: 6px;
+ border-left: 1px solid rgba( 255, 255, 255, 0.17 );
+}
+.jp-carousel-image-map div.gmap-topright {
+ width: 94px;
+ height: 154px;
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+.jp-carousel-image-map div.imgclip {
+ overflow: hidden;
+ -moz-border-radius-topright: 6px;
+ border-top-left-radius: 6px;
+}
+.jp-carousel-image-map div.gmap-topright img {
+ margin-right: -40px;
+}
+.jp-carousel-image-map img.gmap-bottomright {
+ position: absolute;
+ top: 96px;
+ left: 0;
+}
+
+/** Comments Start **/
+.jp-carousel-comments {
+ font: 15px/1.7 "Helvetica Neue", sans-serif !important;
+ font-weight: 400;
+ background:none transparent;
+}
+
+.jp-carousel-comments p a:hover, .jp-carousel-comments p a:focus, .jp-carousel-comments p a:active {
+ color: #68c9e8 !important;
+}
+
+.jp-carousel-comment {
+ background:none transparent;
+ color: #999;
+ margin-bottom: 20px;
+ clear:right;
+ overflow: auto;
+ width: 100%
+}
+
+.jp-carousel-comment p {
+ color: #999 !important;
+}
+
+.jp-carousel-comment .comment-author {
+ font-size: 13px;
+ font-weight:400;
+ padding:0;
+ width:auto;
+ display: inline;
+ float:none;
+ border:none;
+ margin:0;
+}
+
+.jp-carousel-comment .comment-author a {
+ color: #fff;
+}
+
+.jp-carousel-comment .comment-gravatar {
+ float:right;
+}
+
+.jp-carousel-comment .comment-content {
+ border:none;
+ margin-right:85px;
+ padding: 0;
+}
+
+.jp-carousel-comment .avatar {
+ margin:0 0 0 20px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ border: none !important;
+ padding: 0 !important;
+ background-color: transparent !important;
+}
+
+.jp-carousel-comment .comment-date {
+ color:#999;
+ margin-top: 4px;
+ font-size:11px;
+ display: inline;
+ float: left;
+ /*clear: right;*/
+}
+
+#jp-carousel-comment-form {
+ margin:0 0 10px !important;
+ float: right;
+ width: 100%;
+}
+
+textarea#jp-carousel-comment-form-comment-field {
+ background: rgba(34,34,34,0.9);
+ border: 1px solid #3a3a3a;
+ color: #aaa;
+ font: 15px/1.4 "Helvetica Neue", sans-serif !important;
+ width: 100%;
+ padding: 10px 10px 5px;
+ margin: 0;
+ float: none;
+ height: 147px;
+ -webkit-box-shadow: inset 2px 2px 2px rgba(0,0,0,0.2);
+ box-shadow: inset 2px 2px 2px rgba(0,0,0,0.2);
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ overflow: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+textarea#jp-carousel-comment-form-comment-field::-webkit-input-placeholder {
+ color: #555;
+}
+
+textarea#jp-carousel-comment-form-comment-field:focus {
+ background: #ccc;
+ color: #222;
+}
+
+textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder {
+ color: #aaa;
+}
+
+#jp-carousel-comment-form-spinner {
+ color: #fff;
+ margin:22px 10px 0 0;
+ display: block;
+ width: 20px;
+ height: 20px;
+ float: right;
+}
+
+#jp-carousel-comment-form-submit-and-info-wrapper {
+ display: none;
+ /*margin-bottom:15px;*/
+ overflow: hidden;
+ width: 100%
+}
+
+#jp-carousel-comment-form-commenting-as {
+}
+
+#jp-carousel-comment-form-commenting-as input {
+ background: rgba(34,34,34,0.9);
+ border: 1px solid #3a3a3a;
+ color: #aaa;
+ font: 13px/1.4 "Helvetica Neue", sans-serif !important;
+ padding: 3px 6px;
+ float: right;
+ -webkit-box-shadow: inset 2px 2px 2px rgba(0,0,0,0.2);
+ box-shadow: inset 2px 2px 2px rgba(0,0,0,0.2);
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+ width:285px;
+}
+
+#jp-carousel-comment-form-commenting-as input:focus {
+ background: #ccc;
+ color: #222;
+}
+
+#jp-carousel-comment-form-commenting-as p {
+ font: 400 13px/1.7 "Helvetica Neue", sans-serif !important;
+ margin:22px 0 0;
+ float: right;
+}
+
+#jp-carousel-comment-form-commenting-as fieldset {
+ float:right;
+ border:none;
+ margin:20px 0 0 0;
+ padding:0;
+}
+
+#jp-carousel-comment-form-commenting-as fieldset {
+ clear: both;
+}
+
+#jp-carousel-comment-form-commenting-as label {
+ font: 400 13px/1.7 "Helvetica Neue", sans-serif !important;
+ margin:0 0 3px 20px;
+ float:right;
+ width:100px;
+}
+
+#jp-carousel-comment-form-button-submit {
+ margin-top: 20px;
+ float:left;
+}
+
+#js-carousel-comment-form-container {
+ margin-bottom:15px;
+ overflow: auto;
+ width: 100%;
+}
+
+#jp-carousel-comment-form-container {
+ margin-bottom:15px;
+ overflow: auto;
+ width: 100%;
+}
+
+#jp-carousel-comment-post-results {
+ display: none;
+ overflow:auto;
+ width:100%;
+}
+
+#jp-carousel-comment-post-results span {
+ display:block;
+ text-align: center;
+ margin-top:20px;
+ width: 100%;
+ overflow: auto;
+ padding: 1em 0;
+ box-sizing: border-box;
+ background: rgba( 0, 0, 0, 0.7 );
+ border-radius: 2px;
+ font: 13px/1.4 "Helvetica Neue", sans-serif !important;
+ border: 1px solid rgba( 255, 255, 255, 0.17 );
+ -webkit-box-shadow: inset 0px 5px 5px 0px rgba(0, 0, 0, 1);
+ box-shadow: inset 0px 5px 5px 0px rgba(0, 0, 0, 1);
+}
+
+.jp-carousel-comment-post-error {
+ color:#DF4926;
+}
+
+.jp-carousel-comment-post-success {
+ /*color:#21759B;*/
+}
+
+#jp-carousel-comments-closed {
+ display: none;
+ color: #999;
+}
+
+#jp-carousel-comments-loading {
+ font: 444 15px/1.7 "Helvetica Neue", sans-serif !important;
+ display: none;
+ color: #999;
+ text-align: right;
+ margin-bottom: 20px;
+}
+
+
+/* ----- Light variant ----- */
+
+.jp-carousel-light .jp-carousel-overlay {
+ background: #fff;
+}
+
+.jp-carousel-light .jp-carousel-next-button:hover span,
+.jp-carousel-light .jp-carousel-previous-button:hover span {
+ opacity: 0.8;
+}
+
+.jp-carousel-light .jp-carousel-close-hint:hover,
+.jp-carousel-light .jp-carousel-titleanddesc div {
+ color: #000 !important;
+}
+
+.jp-carousel-light .jp-carousel-comments p a,
+.jp-carousel-light .jp-carousel-comment .comment-author a,
+.jp-carousel-light .jp-carousel-titleanddesc p a,
+.jp-carousel-light .jp-carousel-titleanddesc p a,
+.jp-carousel-light .jp-carousel-comments p a,
+.jp-carousel-light .jp-carousel-info h2 a {
+ color: #1e8cbe !important;
+}
+
+.jp-carousel-light .jp-carousel-comments p a:hover,
+.jp-carousel-light .jp-carousel-comment .comment-author a:hover,
+.jp-carousel-light .jp-carousel-titleanddesc p a:hover,
+.jp-carousel-light .jp-carousel-titleanddesc p a:hover,
+.jp-carousel-light .jp-carousel-comments p a:hover,
+.jp-carousel-light .jp-carousel-info h2 a:hover {
+ color: #f1831e !important;
+}
+
+.jp-carousel-light .jp-carousel-info h2,
+.jp-carousel-light .jp-carousel-titleanddesc,
+.jp-carousel-light .jp-carousel-titleanddesc p,
+.jp-carousel-light .jp-carousel-comment,
+.jp-carousel-light .jp-carousel-comment p,
+.jp-carousel-light div.jp-carousel-buttons a,
+.jp-carousel-light .jp-carousel-titleanddesc p strong,
+.jp-carousel-light .jp-carousel-titleanddesc p b,
+.jp-carousel-light .jp-carousel-titleanddesc p em,
+.jp-carousel-light .jp-carousel-titleanddesc p i {
+ color: #666;
+}
+
+.jp-carousel-light .jp-carousel-buttons {
+ border-bottom-color: #f0f0f0;
+ background: #f5f5f5;
+}
+
+.jp-carousel-light div.jp-carousel-buttons a:hover {
+ text-decoration: none;
+ color: #f1831e;
+}
+
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-reblog,
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-reblog:hover {
+ background-position: 4px -56px;
+ padding-right: 24px !important;
+}
+
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-reblog.reblogged,
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-like.liked {
+ background-color: #2ea2cc;
+ color: #fff;
+}
+
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-commentlink {
+ background-position: 0px -136px;
+}
+
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-like,
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-like:hover {
+ background-position: 5px -15px;
+ padding-right: 23px !important;
+}
+
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-reblog.reblogged {
+ background-position: 5px -36px;
+}
+
+.jp-carousel-light div.jp-carousel-buttons a.jp-carousel-like.liked {
+ background-position: 5px 5px;
+}
+
+.jp-carousel-light div#carousel-reblog-box {
+ background: #eee;
+ background: -moz-linear-gradient(bottom, #ececec, #f7f7f7);
+ background: -webkit-gradient(linear, right bottom, right top, from(#ececec), to(#f7f7f7));
+ -webkit-box-shadow: 0 2px 6px rgba(0,0,0,0.1);
+ -moz-box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+ border:1px solid #ddd;
+}
+
+.jp-carousel-light #carousel-reblog-box textarea {
+ border: 1px inset #ccc;
+ color: #666;
+ border: 1px solid #cfcfcf;
+ background: #fff;
+}
+
+.jp-carousel-light #carousel-reblog-box .canceltext {
+ color: #888;
+}
+
+.jp-carousel-light #carousel-reblog-box .canceltext a {
+ color: #666;
+}
+
+.jp-carousel-light #carousel-reblog-box select {
+ background: #eee;
+ color: #333;
+ border: 1px solid #aaa;
+}
+
+.jp-carousel-light #carousel-reblog-box input#carousel-reblog-submit, #jp-carousel-comment-form-button-submit {
+ color: #333;
+ background: #fff;
+ background: -moz-linear-gradient(bottom, #ddd, #fff);
+ background: -webkit-gradient(linear, right bottom, right top, from(#ddd), to(#fff));
+ border: 1px solid #aaa;
+}
+
+.jp-carousel-light .jp-carousel-image-meta {
+ background: #fafafa;
+ border: 1px solid #eee;
+ border-top-color: #f5f5f5;
+ border-right-color: #f5f5f5;
+ color: #333;
+}
+
+.jp-carousel-light .jp-carousel-image-meta li {
+ color: #000 !important;
+}
+
+.jp-carousel-light .jp-carousel-close-hint {
+ color: #ccc;
+}
+
+.jp-carousel-light .jp-carousel-close-hint span {
+ background-color: white;
+ border-color: #ccc;
+}
+
+.jp-carousel-light #jp-carousel-comment-form-comment-field::-webkit-input-placeholder {
+ color: #aaa;
+}
+
+.jp-carousel-light #jp-carousel-comment-form-comment-field:focus {
+ color: #333;
+}
+
+.jp-carousel-light #jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder {
+ color: #ddd;
+}
+
+.jp-carousel-light a.jp-carousel-image-download {
+ background-position: 0 -102px;
+}
+
+.jp-carousel-light a.jp-carousel-image-download:hover {
+ background-position: 0 -102px;
+ color: #f1831e;
+}
+
+.jp-carousel-light textarea#jp-carousel-comment-form-comment-field {
+ background: #fbfbfb;
+ color: #333;
+ border: 1px solid #dfdfdf;
+ -webkit-box-shadow: inset 2px 2px 2px rgba(0,0,0,0.1);
+ box-shadow: inset 2px 2px 2px rgba(0,0,0,0.1);
+}
+
+.jp-carousel-light #jp-carousel-comment-form-commenting-as input {
+ background: #fbfbfb;
+ border: 1px solid #dfdfdf;
+ color: #333;
+ -webkit-box-shadow: inset 2px 2px 2px rgba(0,0,0,0.1);
+ box-shadow: inset 2px 2px 2px rgba(0,0,0,0.1);
+}
+
+.jp-carousel-light #jp-carousel-comment-form-commenting-as input:focus {
+ background: #fbfbfb;
+ color: #333;
+}
+
+.jp-carousel-light #jp-carousel-comment-post-results span {
+ background: #f7f7f7;
+ border:1px solid #dfdfdf;
+ -webkit-box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.05);
+}
+
+.jp-carousel-light .jp-carousel-slide {
+ background-color:#fff;
+}
+
+.jp-carousel-light .jp-carousel-titleanddesc {
+ border-top: 1px solid #eee;
+}
+
+.jp-carousel-light .jp-carousel-fadeaway {
+ background: -moz-linear-gradient(bottom, rgba(255,255,255,0.75), rgba(255,255,255,0));
+ background: -webkit-gradient(linear, right bottom, right top, from(rgba(255,255,255,0.75)), to(rgba(255,255,255,0)));
+}
+
+/* Small screens */
+@media only screen and (max-width: 760px) {
+
+ .jp-carousel-info {
+ margin: 0 10px !important;
+ }
+
+ .jp-carousel-next-button, .jp-carousel-previous-button {
+ display: none !important;
+ }
+
+ .jp-carousel-buttons {
+ display: none !important;
+ }
+
+ .jp-carousel-image-meta {
+ float: none !important;
+ width: 100% !important;
+ -moz-box-sizing:border-box;
+ -webkit-box-sizing:border-box;
+ box-sizing: border-box;
+ }
+
+ .jp-carousel-close-hint {
+ font-weight: 800 !important;
+ font-size: 26px !important;
+ position: fixed !important;
+ top: -10px;
+ }
+
+ .jp-carousel-slide img {
+ filter: alpha(opacity=100);
+ opacity: 1;
+ }
+
+ .jp-carousel-wrap {
+ background-color: #000;
+ }
+
+ .jp-carousel-fadeaway {
+ display: none;
+ }
+
+ #jp-carousel-comment-form-container {
+ display: none !important;
+ }
+
+ .jp-carousel-titleanddesc {
+ padding-top: 0 !important;
+ border: none !important;
+ }
+ .jp-carousel-titleanddesc-title {
+ font-size: 1em !important;
+ }
+
+ .jp-carousel-left-column-wrapper {
+ padding: 0;
+ }
+}
diff --git a/plugins/jetpack/modules/comments.php b/plugins/jetpack/modules/comments.php
index b30ccd73..d5d4da4d 100644
--- a/plugins/jetpack/modules/comments.php
+++ b/plugins/jetpack/modules/comments.php
@@ -13,6 +13,15 @@ if ( is_admin() ) {
require dirname( __FILE__ ) . '/comments/admin.php';
}
+Jetpack_Sync::sync_options( __FILE__,
+ 'comment_registration',
+ 'require_name_email',
+ 'show_avatars',
+ 'avatar_default',
+ 'highlander_comment_form_prompt',
+ 'jetpack_comment_form_color_scheme'
+);
+
function jetpack_comments_load() {
Jetpack::enable_module_configurable( __FILE__ );
Jetpack::module_configuration_load( __FILE__, 'jetpack_comments_configuration_load' );
diff --git a/plugins/jetpack/modules/comments/base.php b/plugins/jetpack/modules/comments/base.php
index 2835313f..f1b5440e 100644
--- a/plugins/jetpack/modules/comments/base.php
+++ b/plugins/jetpack/modules/comments/base.php
@@ -35,7 +35,6 @@ class Highlander_Comments_Base {
protected function setup_filters() {
add_filter( 'comments_array', array( $this, 'comments_array' ) );
add_filter( 'preprocess_comment', array( $this, 'allow_logged_in_user_to_comment_as_guest' ), 0 );
- add_filter( 'get_avatar', array( $this, 'get_avatar' ), 10, 4 );
}
/**
@@ -273,56 +272,16 @@ class Highlander_Comments_Base {
}
/**
- * Get the comment avatar from Gravatar, Twitter, or Facebook
- *
- * @since JetpackComments (1.4)
- * @param string $avatar Current avatar URL
- * @param string $comment Comment for the avatar
- * @param int $size Size of the avatar
- * @param string $default Not used
- * @return string New avatar
- */
- public function get_avatar( $avatar, $comment, $size, $default ) {
- if ( ! isset( $comment->comment_post_ID ) || ! isset( $comment->comment_ID ) ) {
- // it's not a comment - bail
- return $avatar;
- }
-
- if ( false === strpos( $comment->comment_author_url, '/www.facebook.com/' ) && false === strpos( $comment->comment_author_url, '/twitter.com/' ) ) {
- // It's neither FB nor Twitter - bail
- return $avatar;
- }
-
- // It's a FB or Twitter avatar
- $foreign_avatar = get_comment_meta( $comment->comment_ID, 'hc_avatar', true );
- if ( empty( $foreign_avatar ) ) {
- // Can't find the avatar details - bail
- return $avatar;
- }
-
- // Return the FB or Twitter avatar
- return preg_replace( '#src=([\'"])[^\'"]+\\1#', 'src=\\1' . esc_url( $this->imgpress_avatar( $foreign_avatar, $size ) ) . '\\1', $avatar );
- }
-
- /**
- * Get an avatar from Imgpress
+ * Get an avatar from Photon
*
* @since JetpackComments (1.4)
* @param string $url
* @param int $size
* @return string
*/
- protected function imgpress_avatar( $url, $size ) {
+ protected function photon_avatar( $url, $size ) {
$size = (int) $size;
- $args = urlencode_deep( array(
- 'url' => $url,
- 'resize' => "$size,$size",
- ) );
-
- $url = apply_filters( 'jetpack_static_url', ( is_ssl() ? 'https://s-ssl.wordpress.com' : 'http://s.wordpress.com' ) . '/imgpress' );
- $url = add_query_arg( $args, $url );
-
- return $url;
+ return jetpack_photon_url( $url, array( 'resize' => "$size,$size" ) );
}
}
diff --git a/plugins/jetpack/modules/comments/comments.php b/plugins/jetpack/modules/comments/comments.php
index d33ad240..8dae39b7 100644
--- a/plugins/jetpack/modules/comments/comments.php
+++ b/plugins/jetpack/modules/comments/comments.php
@@ -115,6 +115,49 @@ class Jetpack_Comments extends Highlander_Comments_Base {
add_action( 'comment_post', array( $this, 'add_comment_meta' ) );
}
+ /**
+ * Setup filters for methods in this class
+ * @since 1.6.2
+ */
+ protected function setup_filters() {
+ parent::setup_filters();
+
+ add_filter( 'comment_post_redirect', array( $this, 'capture_comment_post_redirect_to_reload_parent_frame' ), 100 );
+ add_filter( 'get_avatar', array( $this, 'get_avatar' ), 10, 4 );
+ }
+
+ /**
+ * Get the comment avatar from Gravatar, Twitter, or Facebook
+ *
+ * @since JetpackComments (1.4)
+ * @param string $avatar Current avatar URL
+ * @param string $comment Comment for the avatar
+ * @param int $size Size of the avatar
+ * @param string $default Not used
+ * @return string New avatar
+ */
+ public function get_avatar( $avatar, $comment, $size, $default ) {
+ if ( ! isset( $comment->comment_post_ID ) || ! isset( $comment->comment_ID ) ) {
+ // it's not a comment - bail
+ return $avatar;
+ }
+
+ if ( false === strpos( $comment->comment_author_url, '/www.facebook.com/' ) && false === strpos( $comment->comment_author_url, '/twitter.com/' ) ) {
+ // It's neither FB nor Twitter - bail
+ return $avatar;
+ }
+
+ // It's a FB or Twitter avatar
+ $foreign_avatar = get_comment_meta( $comment->comment_ID, 'hc_avatar', true );
+ if ( empty( $foreign_avatar ) ) {
+ // Can't find the avatar details - bail
+ return $avatar;
+ }
+
+ // Return the FB or Twitter avatar
+ return preg_replace( '#src=([\'"])[^\'"]+\\1#', 'src=\\1' . esc_url( $this->photon_avatar( $foreign_avatar, $size ) ) . '\\1', $avatar );
+ }
+
/** Output Methods ********************************************************/
/**
@@ -168,6 +211,7 @@ class Jetpack_Comments extends Highlander_Comments_Base {
'greeting' => get_option( 'highlander_comment_form_prompt', __( 'Leave a Reply', 'jetpack' ) ),
'color_scheme' => get_option( 'jetpack_comment_form_color_scheme', $this->default_color_scheme ),
'lang' => get_bloginfo( 'language' ),
+ 'jetpack_version' => JETPACK__VERSION,
);
// Extra parameters for logged in user
@@ -223,6 +267,14 @@ class Jetpack_Comments extends Highlander_Comments_Base {
$url_origin = ( is_ssl() ? 'https' : 'http' ) . '://jetpack.wordpress.com';
?>
+ <!--[if IE]>
+ <script type="text/javascript">
+ if ( 0 === window.location.hash.indexOf( '#comment-' ) ) {
+ // window.location.reload() doesn't respect the Hash in IE
+ window.location.hash = window.location.hash;
+ }
+ </script>
+ <![endif]-->
<script type="text/javascript">
var comm_par_el = document.getElementById( 'comment_parent' ),
comm_par = (comm_par_el && comm_par_el.value) ? comm_par_el.value : '',
@@ -361,6 +413,7 @@ class Jetpack_Comments extends Highlander_Comments_Base {
$comment_meta['hc_post_as'] = 'wordpress';
$comment_meta['hc_avatar'] = stripslashes( $_POST['hc_avatar'] );
$comment_meta['hc_foreign_user_id'] = stripslashes( $_POST['hc_userid'] );
+ $comment_meta['hc_wpcom_id_sig'] = stripslashes( $_POST['hc_wpcom_id_sig'] ); //since 1.9
break;
case 'jetpack' :
@@ -379,6 +432,87 @@ class Jetpack_Comments extends Highlander_Comments_Base {
foreach ( $comment_meta as $key => $value )
add_comment_meta( $comment_id, $key, $value, true );
}
+ function capture_comment_post_redirect_to_reload_parent_frame( $url ) {
+ if ( !isset( $_GET['for'] ) || 'jetpack' != $_GET['for'] ) {
+ return $url;
+ }
+?>
+<!DOCTYPE html>
+<html <?php language_attributes(); ?>>
+<!--<![endif]-->
+<head>
+<meta charset="<?php bloginfo( 'charset' ); ?>" />
+<title><?php printf( __( 'Submitting Comment%s', 'jetpack' ), '&hellip;' ); ?></title>
+<style type="text/css">
+body {
+ display: table;
+ width: 100%;
+ height: 60%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ overflow: hidden;
+ color: #333;
+}
+
+h1 {
+ text-align: center;
+ margin: 0;
+ padding: 0;
+ display: table-cell;
+ vertical-align: middle;
+ font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", sans-serif;
+ font-weight: normal;
+}
+
+.hidden {
+ opacity: 0;
+}
+
+h1 span {
+ -moz-transition-property: opacity;
+ -moz-transition-duration: 1s;
+ -moz-transition-timing-function: ease-in-out;
+
+ -webkit-transition-property: opacity;
+ -webkit-transition-duration: 1s;
+ -webbit-transition-timing-function: ease-in-out;
+
+ -o-transition-property: opacity;
+ -o-transition-duration: 1s;
+ -o-transition-timing-function: ease-in-out;
+
+ -ms-transition-property: opacity;
+ -ms-transition-duration: 1s;
+ -ms-transition-timing-function: ease-in-out;
+
+ transition-property: opacity;
+ transition-duration: 1s;
+ transition-timing-function: ease-in-out;
+}
+</style>
+</head>
+<body>
+ <h1><?php printf( __( 'Submitting Comment%s', 'jetpack' ), '<span id="ellipsis" class="hidden">&hellip;</span>' ); ?></h1>
+<script type="text/javascript">
+try {
+ window.parent.location = <?php echo json_encode( $url ); ?>;
+ window.parent.location.reload( true );
+} catch ( e ) {
+ window.location = <?php echo json_encode( $url ); ?>;
+ window.location.reload( true );
+}
+ellipsis = document.getElementById( 'ellipsis' );
+function toggleEllipsis() {
+ ellipsis.className = ellipsis.className ? '' : 'hidden';
+}
+setInterval( toggleEllipsis, 1200 );
+</script>
+</body>
+</html>
+<?php
+ exit;
+ }
}
Jetpack_Comments::init();
diff --git a/plugins/jetpack/modules/contact-form/admin.php b/plugins/jetpack/modules/contact-form/admin.php
index b5fcadd9..d3efefa0 100644
--- a/plugins/jetpack/modules/contact-form/admin.php
+++ b/plugins/jetpack/modules/contact-form/admin.php
@@ -1,5 +1,43 @@
<?php
+function menu_alter() {
+ echo '
+ <style>
+ #menu-posts-feedback .wp-menu-image img { display: none; }
+ #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; }
+ #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; }
+ .grunion-menu-button { background: url("' . GRUNION_PLUGIN_URL . 'images/grunion-form.png") no-repeat; width: 13px; height: 13px; display: inline-block; vertical-align: middle; ) }
+ @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) {
+ #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; }
+ #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; }
+ .grunion-menu-button { background-image: url("' . GRUNION_PLUGIN_URL . 'images/grunion-form-2x.png"); background-size: 13px 12px !important; vertical-align: bottom; }
+ }
+ </style>';
+}
+
+add_action('admin_head', 'menu_alter');
+
+/**
+ * Add a contact form button to the post composition screen
+ */
+add_action( 'media_buttons', 'grunion_media_button', 999 );
+function grunion_media_button( ) {
+ global $post_ID, $temp_ID;
+ $iframe_post_id = (int) (0 == $post_ID ? $temp_ID : $post_ID);
+ $title = esc_attr( __( 'Add a custom form', 'jetpack' ) );
+ $plugin_url = esc_url( GRUNION_PLUGIN_URL );
+ $site_url = esc_url( admin_url( "/admin-ajax.php?post_id={$iframe_post_id}&action=grunion_form_builder&TB_iframe=true&width=768" ) );
+
+ echo '<a href="' . $site_url . '&id=add_form" class="thickbox" title="' . $title . '"><div class="grunion-menu-button" alt="' . $title . '"></div></a>';
+}
+
+add_action( 'wp_ajax_grunion_form_builder', 'display_form_view' );
+
+function display_form_view() {
+ require_once GRUNION_PLUGIN_DIR . 'grunion-form-view.php';
+ exit;
+}
+
// feedback specific css items
add_action( 'admin_print_styles', 'grunion_admin_css' );
function grunion_admin_css() {
@@ -40,17 +78,91 @@ function grunion_admin_css() {
color: #D98500;
}
-#icon-edit { background-position: -432px -5px; }
-
-#icon-edit, #icon-post { background: url("<?php echo GRUNION_PLUGIN_URL; ?>images/grunion-menu-big.png") no-repeat !important; }
+#icon-edit.icon32-posts-feedback, #icon-post.icon32-posts-feedback { background: url("<?php echo GRUNION_PLUGIN_URL; ?>images/grunion-menu-big.png") no-repeat !important; }
@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) {
- #icon-edit, #icon-post { background: url("<?php echo GRUNION_PLUGIN_URL; ?>images/grunion-menu-big-2x.png") no-repeat !important; background-size: 30px 31px !important; }
+ #icon-edit.icon32-posts-feedback, #icon-post.icon32-posts-feedback { background: url("<?php echo GRUNION_PLUGIN_URL; ?>images/grunion-menu-big-2x.png") no-repeat !important; background-size: 30px 31px !important; }
}
+
+#icon-edit.icon32-posts-feedback { background-position: 2px 2px !important; }
+
</style>
<?php
}
+/**
+ * Hack a 'Bulk Spam' option for bulk edit
+ * There isn't a better way to do this until
+ * http://core.trac.wordpress.org/changeset/17297 is resolved
+ */
+add_action( 'admin_head', 'grunion_add_bulk_edit_option' );
+function grunion_add_bulk_edit_option() {
+
+ $screen = get_current_screen();
+
+ if ( 'edit-feedback' != $screen->id
+ || ( ! empty( $_GET['post_status'] ) && 'spam' == $_GET['post_status'] ) )
+ return;
+
+ $spam_text = __( 'Mark Spam', 'jetpack' );
+ ?>
+ <script type="text/javascript">
+ jQuery(document).ready(function($) {
+ $('#posts-filter .actions select[name=action] option:first-child').after('<option value="spam"><?php echo esc_attr( $spam_text ); ?></option>' );
+ })
+ </script>
+ <?php
+}
+
+/**
+ * Handle a bulk spam report
+ */
+add_action( 'admin_init', 'grunion_handle_bulk_spam' );
+function grunion_handle_bulk_spam() {
+ global $pagenow;
+
+ if ( 'edit.php' != $pagenow
+ || ( empty( $_REQUEST['post_type'] ) || 'feedback' != $_REQUEST['post_type'] ) )
+ return;
+
+ // Slip in a success message
+ if ( ! empty( $_REQUEST['message'] ) && 'marked-spam' == $_REQUEST['message'] )
+ add_action( 'admin_notices', 'grunion_message_bulk_spam' );
+
+ if ( empty( $_REQUEST['action'] ) || 'spam' != $_REQUEST['action'] )
+ return;
+
+ check_admin_referer('bulk-posts');
+
+ if ( empty( $_REQUEST['post'] ) ) {
+ wp_safe_redirect( wp_get_referer() );
+ exit;
+ }
+
+ $post_ids = array_map( 'intval', $_REQUEST['post'] );
+
+ foreach( $post_ids as $post_id ) {
+ if ( ! current_user_can( "edit_page", $post_id ) )
+ wp_die( __( 'You are not allowed to manage this item.', 'jetpack' ) );
+
+ $post = array(
+ 'ID' => $post_id,
+ 'post_status' => 'spam',
+ );
+ $akismet_values = get_post_meta( $post_id, '_feedback_akismet_values', true );
+ wp_update_post( $post );
+ do_action( 'contact_form_akismet', 'spam', $akismet_values );
+ }
+
+ $redirect_url = add_query_arg( 'message', 'marked-spam', wp_get_referer() );
+ wp_safe_redirect( $redirect_url );
+ exit;
+}
+
+function grunion_message_bulk_spam() {
+ echo '<div class="updated"><p>' . __( 'Feedback(s) marked as spam', 'jetpack' ) . '</p></div>';
+}
+
// remove admin UI parts that we don't support in feedback management
add_action( 'admin_menu', 'grunion_admin_menu' );
function grunion_admin_menu() {
@@ -320,48 +432,41 @@ function grunion_sort_objects( $a, $b ) {
// returns both the shortcode form, and HTML markup representing a preview of the form
function grunion_ajax_shortcode() {
check_ajax_referer( 'grunion_shortcode' );
-
- $atts = '';
- if ( trim( $_POST['subject'] ) )
- $atts .= ' subject="'.grunion_esc_attr($_POST['subject']).'"';
- if ( trim( $_POST['to'] ) )
- $atts .= ' to="'.grunion_esc_attr($_POST['to']).'"';
-
- $shortcode = '[contact-form'.$atts.']';
- $shortcode .= "\n";
+
+ $attributes = array();
+
+ foreach ( array( 'subject', 'to' ) as $attribute ) {
+ if ( isset( $_POST[$attribute] ) && strlen( $_POST[$attribute] ) ) {
+ $attributes[$attribute] = stripslashes( $_POST[$attribute] );
+ }
+ }
+
if ( is_array( $_POST['fields'] ) ) {
- usort( $_POST['fields'], 'grunion_sort_objects' );
- foreach ( $_POST['fields'] as $field ) {
- $req = $opts = '';
- if ( $field['required'] == 'true' )
- $req = ' required="true"';
- if ( isset( $field['options'] ) && $field['options'] ) {
- $opts = ' options="';
- foreach ( $field['options'] as $option ) {
- $option = wp_kses( $option, array() );
- $option = grunion_esc_attr( $option );
-
- # we need to be very specific about how we
- # encode these values
- $option = str_replace( ',', '&#x002c;', $option );
- $option = str_replace( '"', '&#x0022;', $option );
- $option = str_replace( "'", '&#x0027;', $option );
- $option = str_replace( '&', '&#x0026;', $option );
-
- $opts .= $option . ',';
- }
- $opts = rtrim( $opts, ',' ) . '"';
+ $fields = stripslashes_deep( $_POST['fields'] );
+ usort( $fields, 'grunion_sort_objects' );
+
+ $field_shortcodes = array();
+
+ foreach ( $fields as $field ) {
+ $field_attributes = array();
+
+ if ( isset( $field['required'] ) && 'true' === $field['required'] ) {
+ $field_attributes['required'] = 'true';
}
- $field['label'] = wp_kses( $field['label'], array() );
- $field['label'] = str_replace( '"', '&#x0022;', $field['label'] );
+ foreach ( array( 'options', 'label', 'type' ) as $attribute ) {
+ if ( isset( $field[$attribute] ) ) {
+ $field_attributes[$attribute] = $field[$attribute];
+ }
+ }
- $shortcode .= '[contact-field label="'. $field['label'] .'" type="'.grunion_esc_attr($field['type']).'"' . $req . $opts .' /]'."\n";
+ $field_shortcodes[] = new Grunion_Contact_Form_Field( $field_attributes );
}
}
- $shortcode .= '[/contact-form]';
-
- die( "\n$shortcode\n" );
+
+ $grunion = new Grunion_Contact_Form( $attributes, $field_shortcodes );
+
+ die( "\n$grunion\n" );
}
// takes a post_id, extracts the contact-form shortcode from that post (if there is one), parses it,
@@ -370,33 +475,45 @@ function grunion_ajax_shortcode_to_json() {
global $post, $grunion_form;
check_ajax_referer( 'grunion_shortcode_to_json' );
- if ( isset( $_POST['content'] ) && is_numeric( $_POST['post_id'] ) ) {
- $content = stripslashes( $_POST['content'] );
- $post = get_post( $_POST['post_id'] );
- // does it look like a post with a [contact-form] already?
- if ( strpos( $content, '[contact-form' ) !== false ) {
- $out = do_shortcode($content);
- global $contact_form_fields;
- if ( is_array($contact_form_fields) && !empty($contact_form_fields) ) {
- foreach ( $contact_form_fields as $field_id => $field ) {
- # need to dig deeper on select field options
- if ( preg_match( "|^(.*)\-select$|", $field_id ) ) {
- foreach ( (array) $field['options'] as $opt_i => $opt ) {
- $contact_form_fields[$field_id]['options'][$opt_i] = html_entity_decode( $opt );
- }
- }
- $contact_form_fields[$field_id]['label'] = html_entity_decode( $contact_form_fields[$field_id]['label'] );
- $contact_form_fields[$field_id]['label'] = wp_kses( $contact_form_fields[$field_id]['label'], array() );
- }
- $out = array( 'fields' => $contact_form_fields, 'to' => $grunion_form->to, 'subject' => $grunion_form->subject );
- die( json_encode( $out ) );
- }
- }
+ if ( !isset( $_POST['content'] ) || !is_numeric( $_POST['post_id'] ) ) {
+ die( '-1' );
+ }
+
+ $content = stripslashes( $_POST['content'] );
+
+ // doesn't look like a post with a [contact-form] already.
+ if ( false === strpos( $content, '[contact-form' ) ) {
die( '' );
}
-
- die( -1 );
+
+ $post = get_post( $_POST['post_id'] );
+
+ do_shortcode( $content );
+
+ $grunion = Grunion_Contact_Form::$last;
+
+ $out = array(
+ 'to' => '',
+ 'subject' => '',
+ 'fields' => array(),
+ );
+
+ foreach ( $grunion->fields as $field ) {
+ $out['fields'][$field->get_attribute( 'id' )] = $field->attributes;
+ }
+
+ $to = $grunion->get_attribute( 'to' );
+ $subject = $grunion->get_attribute( 'subject' );
+ foreach ( array( 'to', 'subject' ) as $attribute ) {
+ $value = $grunion->get_attribute( $attribute );
+ if ( isset( $grunion->defaults[$attribute] ) && $value == $grunion->defaults[$attribute] ) {
+ $value = '';
+ }
+ $out[$attribute] = $value;
+ }
+
+ die( json_encode( $out ) );
}
diff --git a/plugins/jetpack/modules/contact-form/css/grunion.css b/plugins/jetpack/modules/contact-form/css/grunion.css
index a8f1651d..00035180 100644
--- a/plugins/jetpack/modules/contact-form/css/grunion.css
+++ b/plugins/jetpack/modules/contact-form/css/grunion.css
@@ -1,9 +1,10 @@
-.textwidget input[type='text'], .textwidget textarea { width: 100% !important; }
.contact-form .clear-form { clear: both; }
-.contact-form input[type='text'] { width: 300px; margin-bottom: 13px; }
+.contact-form input[type='text'], .contact-form input[type='email'] { width: 300px; margin-bottom: 13px; }
.contact-form select { margin-bottom: 13px; }
.contact-form textarea { height: 200px; width: 80%; float: none; margin-bottom: 13px; }
.contact-form input[type='radio'], .contact-form input[type='checkbox'] { float: none; margin-bottom: 13px; }
.contact-form label { margin-bottom: 3px; float: none; font-weight: bold; display: block; }
.contact-form label.checkbox, .contact-form label.radio { margin-bottom: 3px; float: none; font-weight: bold; display: inline-block; }
-.contact-form label span { color: #AAA; margin-left: 4px; font-weight: normal; } \ No newline at end of file
+.contact-form label span { color: #AAA; margin-left: 4px; font-weight: normal; }
+.form-errors .form-error-message { color: red; }
+.textwidget input[type='text'], .textwidget input[type='email'], .textwidget textarea { width: 250px; }
diff --git a/plugins/jetpack/modules/contact-form/grunion-contact-form.php b/plugins/jetpack/modules/contact-form/grunion-contact-form.php
index bbf2ba54..5600febb 100644
--- a/plugins/jetpack/modules/contact-form/grunion-contact-form.php
+++ b/plugins/jetpack/modules/contact-form/grunion-contact-form.php
@@ -6,7 +6,7 @@ Description: Add a contact form to any post, page or text widget. Emails will b
Plugin URI: http://automattic.com/#
AUthor: Automattic, Inc.
Author URI: http://automattic.com/
-Version: 2.3
+Version: 2.4
License: GPLv2 or later
*/
@@ -16,782 +16,1338 @@ define( 'GRUNION_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
if ( is_admin() )
require_once GRUNION_PLUGIN_DIR . '/admin.php';
-// take the content of a contact-form shortcode and parse it into a list of field types
-function contact_form_parse( $content ) {
- // first parse all the contact-field shortcodes into an array
- global $contact_form_fields, $grunion_form;
- $contact_form_fields = array();
+/**
+ * Sets up various actions, filters, post types, post statuses, shortcodes.
+ */
+class Grunion_Contact_Form_Plugin {
+ /**
+ * @var string The Widget ID of the widget currently being processed. Used to build the unique contact-form ID for forms embedded in widgets.
+ */
+ var $current_widget_id;
- if ( empty( $_REQUEST['action'] ) || $_REQUEST['action'] != 'grunion_shortcode_to_json' ) {
- wp_print_styles( 'grunion.css' );
- }
-
- $out = do_shortcode( $content );
-
- if ( empty($contact_form_fields) || !is_array($contact_form_fields) ) {
- // default form: same as the original Grunion form
- $default_form = '
- [contact-field label="'.__( 'Name', 'jetpack' ).'" type="name" required="true" /]
- [contact-field label="'.__( 'Email', 'jetpack' ).'" type="email" required="true" /]
- [contact-field label="'.__( 'Website', 'jetpack' ).'" type="url" /]';
- if ( 'yes' == strtolower($grunion_form->show_subject) ) {
- $default_form .= '
- [contact-field label="'.__( 'Subject', 'jetpack' ).'" type="subject" /]';
+ static function init() {
+ static $instance = false;
+
+ if ( !$instance ) {
+ $instance = new Grunion_Contact_Form_Plugin;
}
- $default_form .= '
- [contact-field label="'.__( 'Message', 'jetpack' ).'" type="textarea" /]';
- $out = do_shortcode( $default_form );
+ return $instance;
}
- return $out;
-}
-
-function contact_form_render_field( $field ) {
- global $contact_form_last_id, $contact_form_errors, $contact_form_fields, $current_user, $user_identity;
-
- $r = '';
-
- $field_id = $field['id'];
- if ( isset($_POST[ $field_id ]) ) {
- $field_value = stripslashes( $_POST[ $field_id ] );
- } elseif ( is_user_logged_in() ) {
- // Special defaults for logged-in users
- if ( $field['type'] == 'email' )
- $field_value = $current_user->data->user_email;
- elseif ( $field['type'] == 'name' )
- $field_value = $user_identity;
- elseif ( $field['type'] == 'url' )
- $field_value = $current_user->data->user_url;
- else
- $field_value = $field['default'];
- } else {
- $field_value = $field['default'];
+ /**
+ * Strips HTML tags from input. Output is NOT HTML safe.
+ *
+ * @param string $string
+ * @return string
+ */
+ static function strip_tags( $string ) {
+ $string = wp_kses( $string, array() );
+ return str_replace( '&amp;', '&', $string ); // undo damage done by wp_kses_normalize_entities()
}
-
- $field_value = wp_kses($field_value, array());
-
- $field['label'] = html_entity_decode( $field['label'] );
- $field['label'] = wp_kses( $field['label'], array() );
-
- if ( $field['type'] == 'email' ) {
- $r .= "\n<div>\n";
- $r .= "\t\t<label for='".esc_attr($field_id)."' class='grunion-field-label ".esc_attr($field['type']) . ( contact_form_is_error($field_id) ? ' form-error' : '' ) . "'>" . htmlspecialchars( $field['label'] ) . ( $field['required'] ? '<span>'. __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
- $r .= "\t\t<input type='text' name='".esc_attr($field_id)."' id='".esc_attr($field_id)."' value='".esc_attr($field_value)."' class='".esc_attr($field['type'])."'/>\n";
- $r .= "\t</div>\n";
- } elseif ( $field['type'] == 'textarea' ) {
- $r .= "\n<div>\n";
- $r .= "\t\t<label class='".esc_attr($field['type']) . ( contact_form_is_error($field_id) ? ' form-error' : '' ) . "' for='contact-form-comment-" . esc_attr( $field_id ) . "'>" . htmlspecialchars( $field['label'] ) . ( $field['required'] ? '<span>'. __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
- $r .= "\t\t<textarea name='".esc_attr($field_id)."' id='contact-form-comment-".esc_attr($field_id)."' rows='20'>".htmlspecialchars($field_value)."</textarea>\n";
- $r .= "\t</div>\n";
- } elseif ( $field['type'] == 'radio' ) {
- $r .= "\t<div><label class='". ( contact_form_is_error($field_id) ? ' form-error' : '' ) . "'>" . htmlspecialchars( $field['label'] ) . ( $field['required'] ? '<span>'. __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
- foreach ( $field['options'] as $option ) {
- $r .= "\t\t<label class='" . esc_attr( $field['type'] ) . ( contact_form_is_error( $field_id ) ? ' form-error' : '' ) . "'>";
- $r .= "<input type='radio' name='".esc_attr($field_id)."' value='".esc_attr($option)."' class='".esc_attr($field['type'])."' ".( $option == $field_value ? "checked='checked' " : "")." /> ";
- $r .= htmlspecialchars( $option ) . "</label>\n";
- $r .= "\t\t<div class='clear-form'></div>\n";
+
+ function __construct() {
+ $this->add_shortcode();
+
+ // While generating the output of a text widget with a contact-form shortcode, we need to know its widget ID.
+ add_action( 'dynamic_sidebar', array( $this, 'track_current_widget' ) );
+
+ // Add a "widget" shortcode attribute to all contact-form shortcodes embedded in widgets
+ add_filter( 'widget_text', array( $this, 'widget_atts' ), 0 );
+
+ // If Text Widgets don't get shortcode processed, hack ours into place.
+ if ( !has_filter( 'widget_text', 'do_shortcode' ) )
+ add_filter( 'widget_text', array( $this, 'widget_shortcode_hack' ), 5 );
+
+ // Akismet to the rescue
+ if ( function_exists( 'akismet_http_post' ) ) {
+ add_filter( 'contact_form_is_spam', array( $this, 'is_spam_akismet' ), 10 );
+ add_action( 'contact_form_akismet', array( $this, 'akismet_submit' ), 10, 2 );
}
- $r .= "\t\t</div>\n";
- } elseif ( $field['type'] == 'checkbox' ) {
- $r .= "\t<div>\n";
- $r .= "\t\t<label class='".esc_attr($field['type']) . ( contact_form_is_error($field_id) ? ' form-error' : '' ) . "'>\n";
- $r .= "\t\t<input type='checkbox' name='".esc_attr($field_id)."' value='".__( 'Yes', 'jetpack' )."' class='".esc_attr($field['type'])."' ".( $field_value ? "checked='checked' " : "")." /> \n";
- $r .= "\t\t". htmlspecialchars( $field['label'] ) . ( $field['required'] ? '<span>'. __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
- $r .= "\t\t<div class='clear-form'></div>\n";
- $r .= "\t</div>\n";
- } elseif ( $field['type'] == 'select' ) {
- $r .= "\n<div>\n";
- $r .= "\t\t<label for='".esc_attr($field_id)."' class='".esc_attr($field['type']) . ( contact_form_is_error($field_id) ? ' form-error' : '' ) . "'>" . htmlspecialchars( $field['label'] ) . ( $field['required'] ? '<span>'. __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
- $r .= "\t<select name='".esc_attr($field_id)."' id='".esc_attr($field_id)."' value='".esc_attr($field_value)."' class='".esc_attr($field['type'])."'/>\n";
- foreach ( $field['options'] as $option ) {
- $option = html_entity_decode( $option );
- $option = wp_kses( $option, array() );
- $r .= "\t\t<option".( $option == $field_value ? " selected='selected'" : "").">". esc_html( $option ) ."</option>\n";
- }
- $r .= "\t</select>\n";
- $r .= "\t</div>\n";
- } else {
- // default: text field
- // note that any unknown types will produce a text input, so we can use arbitrary type names to handle
- // input fields like name, email, url that require special validation or handling at POST
- $r .= "\n<div>\n";
- $r .= "\t\t<label for='".esc_attr($field_id)."' class='".esc_attr($field['type']) . ( contact_form_is_error($field_id) ? ' form-error' : '' ) . "'>" . htmlspecialchars( $field['label'] ) . ( $field['required'] ? '<span>'. __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
- $r .= "\t\t<input type='text' name='".esc_attr($field_id)."' id='".esc_attr($field_id)."' value='".esc_attr($field_value)."' class='".esc_attr($field['type'])."'/>\n";
- $r .= "\t</div>\n";
+
+ add_action( 'loop_start', array( 'Grunion_Contact_Form', '_style_on' ) );
+
+ // custom post type we'll use to keep copies of the feedback items
+ register_post_type( 'feedback', array(
+ 'labels' => array(
+ 'name' => __( 'Feedbacks', 'jetpack' ),
+ 'singular_name' => __( 'Feedback', 'jetpack' ),
+ 'search_items' => __( 'Search Feedback', 'jetpack' ),
+ 'not_found' => __( 'No feedback found', 'jetpack' ),
+ 'not_found_in_trash' => __( 'No feedback found', 'jetpack' )
+ ),
+ 'menu_icon' => GRUNION_PLUGIN_URL . '/images/grunion-menu.png',
+ 'show_ui' => TRUE,
+ 'show_in_admin_bar' => FALSE,
+ 'public' => FALSE,
+ 'rewrite' => FALSE,
+ 'query_var' => FALSE,
+ 'capability_type' => 'page'
+ ) );
+
+ // Add "spam" as a post status
+ register_post_status( 'spam', array(
+ 'label' => 'Spam',
+ 'public' => FALSE,
+ 'exclude_from_search' => TRUE,
+ 'show_in_admin_all_list' => FALSE,
+ 'label_count' => _n_noop( 'Spam <span class="count">(%s)</span>', 'Spam <span class="count">(%s)</span>', 'jetpack' ),
+ 'protected' => TRUE,
+ '_builtin' => FALSE
+ ) );
+
+ // POST handler
+ if (
+ 'POST' == strtoupper( $_SERVER['REQUEST_METHOD'] )
+ &&
+ isset( $_POST['action'] ) && 'grunion-contact-form' == $_POST['action']
+ &&
+ isset( $_POST['contact-form-id'] )
+ ) {
+ add_action( 'template_redirect', array( $this, 'process_form_submission' ) );
+ }
+
+ /* Can be dequeued by placing the following in wp-content/themes/yourtheme/functions.php
+ *
+ * function remove_grunion_style() {
+ * wp_deregister_style('grunion.css');
+ * }
+ * add_action('wp_print_styles', 'remove_grunion_style');
+ */
+
+ wp_register_style( 'grunion.css', GRUNION_PLUGIN_URL . 'css/grunion.css', array(), JETPACK__VERSION );
}
-
- return $r;
-}
-function contact_form_validate_field( $field ) {
- global $contact_form_last_id, $contact_form_errors, $contact_form_values;
+ /**
+ * Handles all contact-form POST submissions
+ *
+ * Conditionally attached to `template_redirect`
+ */
+ function process_form_submission() {
+ $id = stripslashes( $_POST['contact-form-id'] );
+
+ check_admin_referer( "contact-form_{$id}" );
+
+ $is_widget = 0 === strpos( $id, 'widget-' );
+
+ $form = false;
- $field_id = $field['id'];
- $field_value = isset($_POST[ $field_id ]) ? stripslashes($_POST[ $field_id ]) : '';
+ if ( $is_widget ) {
+ // It's a form embedded in a text widget
- # pay special attention to required email fields
- if ( $field['required'] && $field['type'] == 'email' ) {
- if ( !is_email( $field_value ) ) {
- if ( !is_wp_error( $contact_form_errors ) ) {
- $contact_form_errors = new WP_Error();
+ $this->current_widget_id = substr( $id, 7 ); // remove "widget-"
+
+ // Is the widget active?
+ $sidebar = is_active_widget( false, $this->current_widget_id, 'text' );
+
+ // This is lame - no core API for getting a widget by ID
+ $widget = isset( $GLOBALS['wp_registered_widgets'][$this->current_widget_id] ) ? $GLOBALS['wp_registered_widgets'][$this->current_widget_id] : false;
+
+ if ( $sidebar && $widget && isset( $widget['callback'] ) ) {
+ // This is lamer - no API for outputting a given widget by ID
+ ob_start();
+ // Process the widget to populate Grunion_Contact_Form::$last
+ call_user_func( $widget['callback'], array(), $widget['params'][0] );
+ ob_end_clean();
}
+ } else {
+ // It's a form embedded in a post
+
+ $post = get_post( $id );
- $contact_form_errors->add( $field_id, sprintf( __( '%s requires a valid email address', 'jetpack' ), $field['label'] ) );
+ // Process the content to populate Grunion_Contact_Form::$last
+ apply_filters( 'the_content', $post->post_content );
}
- } elseif ( $field['required'] && !trim($field_value) ) {
- if ( !is_wp_error($contact_form_errors) ) {
- $contact_form_errors = new WP_Error();
+
+ $form = Grunion_Contact_Form::$last;
+
+ if ( !$form || ( is_wp_error( $form->errors ) && $form->errors->get_error_codes() ) ) {
+ return;
}
- $contact_form_errors->add( $field_id, sprintf( __( '%s is required', 'jetpack' ), $field['label'] ) );
+ // Process the form
+ $form->process_submission();
}
-
- $contact_form_values[ $field_id ] = $field_value;
-}
-function contact_form_is_error( $field_id ) {
- global $contact_form_errors;
-
- return ( is_wp_error( $contact_form_errors ) && $contact_form_errors->get_error_message( $field_id ) );
-}
+ /**
+ * Ensure the post author is always zero for contact-form feedbacks
+ * Attached to `wp_insert_post_data`
+ *
+ * @see Grunion_Contact_Form::process_submission()
+ *
+ * @param array $data the data to insert
+ * @param array $postarr the data sent to wp_insert_post()
+ * @return array The filtered $data to insert
+ */
+ function insert_feedback_filter( $data, $postarr ) {
+ if ( $data['post_type'] == 'feedback' && $postarr['post_type'] == 'feedback' ) {
+ $data['post_author'] = 0;
+ }
-// generic shortcode that handles all of the major input types
-// this parses the field attributes into an array that is used by other functions for rendering, validation etc
-function contact_form_field( $atts, $content, $tag ) {
- global $contact_form_fields, $contact_form_last_id, $grunion_form;
-
- $field = shortcode_atts( array(
- 'label' => null,
- 'type' => 'text',
- 'required' => false,
- 'options' => array(),
- 'id' => null,
- 'default' => null,
- ), $atts);
-
- // special default for subject field
- if ( $field['type'] == 'subject' && is_null($field['default']) )
- $field['default'] = $grunion_form->subject;
-
- // allow required=1 or required=true
- if ( $field['required'] == '1' || strtolower($field['required']) == 'true' )
- $field['required'] = true;
- else
- $field['required'] = false;
-
- // parse out comma-separated options list
- if ( !empty($field['options']) && is_string($field['options']) )
- $field['options'] = array_map('trim', explode(',', $field['options']));
-
- // make a unique field ID based on the label, with an incrementing number if needed to avoid clashes
- $id = $field['id'];
- if ( empty($id) ) {
- $id = sanitize_title_with_dashes( $contact_form_last_id . '-' . $field['label'] );
- $i = 0;
- $max_tries = 12;
- while ( isset( $contact_form_fields[ $id ] ) ) {
- $i++;
- $id = sanitize_title_with_dashes( $contact_form_last_id . '-' . $field['label'] . '-' . $i );
-
- if ( $i > $max_tries ) {
- break;
- }
+ return $data;
+ }
+
+ /*
+ * Adds our contact-form shortcode
+ * The "child" contact-field shortcode is added as needed by the contact-form shortcode handler
+ */
+ function add_shortcode() {
+ add_shortcode( 'contact-form', array( 'Grunion_Contact_Form', 'parse' ) );
+ }
+
+ /**
+ * Tracks the widget currently being processed.
+ * Attached to `dynamic_sidebar`
+ *
+ * @see $current_widget_id
+ *
+ * @param array $widget The widget data
+ */
+ function track_current_widget( $widget ) {
+ $this->current_widget_id = $widget['id'];
+ }
+
+ /**
+ * Adds a "widget" attribute to every contact-form embedded in a text widget.
+ * Used to tell the difference between post-embedded contact-forms and widget-embedded contact-forms
+ * Attached to `widget_text`
+ *
+ * @param string $text The widget text
+ * @return string The filtered widget text
+ */
+ function widget_atts( $text ) {
+ Grunion_Contact_Form::style( true );
+
+ return preg_replace( '/\[contact-form([^a-zA-Z_-])/', '[contact-form widget="' . $this->current_widget_id . '"\\1', $text );
+ }
+
+ /**
+ * For sites where text widgets are not processed for shortcodes, we add this hack to process just our shortcode
+ * Attached to `widget_text`
+ *
+ * @param string $text The widget text
+ * @return string The contact-form filtered widget text
+ */
+ function widget_shortcode_hack( $text ) {
+ if ( !preg_match( '/\[contact-form([^a-zA-Z_-])/', $text ) ) {
+ return $text;
}
- $field['id'] = $id;
+
+ $old = $GLOBALS['shortcode_tags'];
+ remove_all_shortcodes();
+ $this->add_shortcode();
+
+ $text = do_shortcode( $text );
+
+ $GLOBALS['shortcode_tags'] = $old;
+
+ return $text;
}
+
+ /**
+ * Populate an array with all values necessary to submit a NEW contact-form feedback to Akismet.
+ * Note that this includes the current user_ip etc, so this should only be called when accepting a new item via $_POST
+ *
+ * @param array $form Contact form feedback array
+ * @return array feedback array with additional data ready for submission to Akismet
+ */
+ function prepare_for_akismet( $form ) {
+ $form['comment_type'] = 'contact_form';
+ $form['user_ip'] = preg_replace( '/[^0-9., ]/', '', $_SERVER['REMOTE_ADDR'] );
+ $form['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
+ $form['referrer'] = $_SERVER['HTTP_REFERER'];
+ $form['blog'] = get_option( 'home' );
+
+ $ignore = array( 'HTTP_COOKIE' );
+
+ foreach ( $_SERVER as $k => $value )
+ if ( !in_array( $k, $ignore ) && is_string( $value ) )
+ $form["$k"] = $value;
+
+ return $form;
+ }
+
+ /**
+ * Submit contact-form data to Akismet to check for spam.
+ * If you're accepting a new item via $_POST, run it Grunion_Contact_Form_Plugin::prepare_for_akismet() first
+ * Attached to `contact_form_is_spam`
+ *
+ * @param array $form
+ * @return bool|WP_Error TRUE => spam, FALSE => not spam, WP_Error => stop processing entirely
+ */
+ function is_spam_akismet( $form ) {
+ global $akismet_api_host, $akismet_api_port;
- $contact_form_fields[ $id ] = $field;
-
- if ( isset( $_POST['contact-form-id'] ) && $_POST['contact-form-id'] == $contact_form_last_id )
- contact_form_validate_field( $field );
-
- return contact_form_render_field( $field );
+ if ( !function_exists( 'akismet_http_post' ) )
+ return false;
+
+ $query_string = http_build_query( $form );
+
+ $response = akismet_http_post( $query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port );
+ $result = false;
+ if ( 'true' == trim( $response[1] ) ) // 'true' is spam
+ $result = true;
+ return apply_filters( 'contact_form_is_spam_akismet', $result, $form );
+ }
+
+ /**
+ * Submit a feedback as either spam or ham
+ *
+ * @param string $as Either 'spam' or 'ham'.
+ * @param array $form the contact-form data
+ */
+ function akismet_submit( $as, $form ) {
+ global $akismet_api_host, $akismet_api_port;
+
+ if ( !in_array( $as, array( 'ham', 'spam' ) ) )
+ return false;
+
+ $query_string = http_build_query( $form );
+
+ $response = akismet_http_post( $query_string, $akismet_api_host, "/1.1/submit-{$as}", $akismet_api_port );
+ return trim( $response[1] );
+ }
}
-add_shortcode('contact-field', 'contact_form_field');
+/**
+ * Generic shortcode class.
+ * Does nothing other than store structured data and output the shortcode as a string
+ *
+ * Not very general - specific to Grunion.
+ */
+class Crunion_Contact_Form_Shortcode {
+ /**
+ * @var string the name of the shortcode: [$shortcode_name /]
+ */
+ var $shortcode_name;
+
+ /**
+ * @var array key => value pairs for the shortcode's attributes: [$shortcode_name key="value" ... /]
+ */
+ var $attributes;
+
+ /**
+ * @var array key => value pair for attribute defaults
+ */
+ var $defaults = array();
+
+ /**
+ * @var null|string Null for selfclosing shortcodes. Hhe inner content of otherwise: [$shortcode_name]$content[/$shortcode_name]
+ */
+ var $content;
+
+ /**
+ * @var array Associative array of inner "child" shortcodes equivalent to the $content: [$shortcode_name][child 1/][child 2/][/$shortcode_name]
+ */
+ var $fields;
+
+ /**
+ * @var null|string The HTML of the parsed inner "child" shortcodes". Null for selfclosing shortcodes.
+ */
+ var $body;
+
+ /**
+ * @param array $attributes An associative array of shortcode attributes. @see shortcode_atts()
+ * @param null|string $content Null for selfclosing shortcodes. The inner content otherwise.
+ */
+ function __construct( $attributes, $content = null ) {
+ $this->attributes = $this->unesc_attr( $attributes );
+ if ( is_array( $content ) ) {
+ $string_content = '';
+ foreach ( $content as $field ) {
+ $string_content .= (string) $field;
+ }
+
+ $this->content = $string_content;
+ } else {
+ $this->content = $content;
+ }
+ $this->parse_content( $content );
+ }
-function contact_form_shortcode( $atts, $content ) {
- global $post;
+ /**
+ * Processes the shortcode's inner content for "child" shortcodes
+ *
+ * @param string $content The shortcode's inner content: [shortcode]$content[/shortcode]
+ */
+ function parse_content( $content ) {
+ if ( is_null( $content ) ) {
+ $this->body = null;
+ }
- $default_to = get_option( 'admin_email' );
- $default_subject = "[" . get_option( 'blogname' ) . "]";
+ $this->body = do_shortcode( $content );
+ }
- if ( !empty( $atts['widget'] ) && $atts['widget'] ) {
- $default_subject .= " Sidebar";
- } elseif ( $post->ID ) {
- $default_subject .= " ". wp_kses( $post->post_title, array() );
- $post_author = get_userdata( $post->post_author );
- $default_to = $post_author->user_email;
+ /**
+ * Returns the value of the requested attribute.
+ *
+ * @param string $key The attribute to retrieve
+ * @return mixed
+ */
+ function get_attribute( $key ) {
+ return isset( $this->attributes[$key] ) ? $this->attributes[$key] : null;
}
- extract( shortcode_atts( array(
- 'to' => $default_to,
- 'subject' => $default_subject,
- 'show_subject' => 'no', // only used in back-compat mode
- 'widget' => 0 //This is not exposed to the user. Works with contact_form_widget_atts
- ), $atts ) );
+ function esc_attr( $value ) {
+ if ( is_array( $value ) ) {
+ return array_map( array( $this, 'esc_attr' ), $value );
+ }
- $widget = esc_attr( $widget );
+ $value = Grunion_Contact_Form_Plugin::strip_tags( $value );
+ $value = _wp_specialchars( $value, ENT_QUOTES, false, true );
- if ( ( function_exists( 'faux_faux' ) && faux_faux() ) || is_feed() )
- return '[contact-form]';
+ // Shortcode attributes can't contain "]"
+ $value = str_replace( ']', '', $value );
+ $value = str_replace( ',', '&#x002c;', $value ); // store commas encoded
+ $value = strtr( $value, array( '%' => '%25', '&' => '%26' ) );
- global $wp_query, $grunion_form, $contact_form_errors, $contact_form_values, $user_identity, $contact_form_last_id, $contact_form_message;
-
- // used to store attributes, configuration etc for access by contact-field shortcodes
- $grunion_form = new stdClass();
- $grunion_form->to = $to;
- $grunion_form->subject = $subject;
- $grunion_form->show_subject = $show_subject;
-
- if ( $widget )
- $id = 'widget-' . $widget;
- elseif ( is_singular() )
- $id = $wp_query->get_queried_object_id();
- else
- $id = $GLOBALS['post']->ID;
- if ( !$id ) // something terrible has happened
- return '[contact-form]';
-
- if ( $id == $contact_form_last_id )
- return;
- else
- $contact_form_last_id = $id;
-
- ob_start();
- wp_nonce_field( 'contact-form_' . $id );
- $nonce = ob_get_contents();
- ob_end_clean();
-
-
- $body = contact_form_parse( $content );
-
- $r = "<div id='contact-form-$id'>\n";
-
- $errors = array();
- if ( is_wp_error( $contact_form_errors ) && $errors = (array) $contact_form_errors->get_error_codes() ) {
- $r .= "<div class='form-error'>\n<h3>" . __( 'Error!', 'jetpack' ) . "</h3>\n<ul class='form-errors'>\n";
- foreach ( $contact_form_errors->get_error_messages() as $message )
- $r .= "\t<li class='form-error-message' style='color: red;'>$message</li>\n";
- $r .= "</ul>\n</div>\n\n";
+ // shortcode_parse_atts() does stripcslashes()
+ $value = addslashes( $value );
+ return $value;
}
-
- $action = apply_filters( 'grunion_contact_form_form_action', get_permalink( $post->ID ) . "#contact-form-$id", $post, $id );
- $r .= "<form action='" . esc_url( $action ) . "' method='post' class='contact-form commentsblock'>\n";
- $r .= $body;
- $r .= "\t<p class='contact-submit'>\n";
- $r .= "\t\t<input type='submit' value='" . __( "Submit &#187;", 'jetpack' ) . "' class='pushbutton-wide'/>\n";
- $r .= "\t\t$nonce\n";
- $r .= "\t\t<input type='hidden' name='contact-form-id' value='$id' />\n";
- $r .= "\t</p>\n";
- $r .= "</form>\n</div>";
-
- if ( !isset( $_POST['contact-form-id'] ) || $_POST['contact-form-id'] != $contact_form_last_id )
- return $r;
+ function unesc_attr( $value ) {
+ if ( is_array( $value ) ) {
+ return array_map( array( $this, 'unesc_attr' ), $value );
+ }
- if ( is_wp_error($contact_form_errors) )
- return $r;
+ // For back-compat with old Grunion encoding
+ // Also, unencode commas
+ $value = strtr( $value, array( '%26' => '&', '%25' => '%' ) );
+ $value = preg_replace( array( '/&#x0*22;/i', '/&#x0*27;/i', '/&#x0*26;/i', '/&#x0*2c;/i' ), array( '"', "'", '&', ',' ), $value );
+ $value = htmlspecialchars_decode( $value, ENT_QUOTES );
+ $value = Grunion_Contact_Form_Plugin::strip_tags( $value );
-
- $emails = str_replace( ' ', '', $to );
- $emails = explode( ',', $emails );
- foreach ( (array) $emails as $email ) {
- if ( is_email( $email ) && ( !function_exists( 'is_email_address_unsafe' ) || !is_email_address_unsafe( $email ) ) )
- $valid_emails[] = $email;
+ return $value;
}
- $to = ( $valid_emails ) ? $valid_emails : $default_to;
+ /**
+ * Generates the shortcode
+ */
+ function __toString() {
+ $r = "[{$this->shortcode_name} ";
- $message_sent = contact_form_send_message( $to, $subject, $widget );
+ foreach ( $this->attributes as $key => $value ) {
+ if ( !$value ) {
+ continue;
+ }
- if ( is_array( $contact_form_values ) )
- extract( $contact_form_values );
+ if ( isset( $this->defaults[$key] ) && $this->defaults[$key] == $value ) {
+ continue;
+ }
- if ( !isset( $comment_content ) )
- $comment_content = '';
- else
- $comment_content = wp_kses( $comment_content, array() );
+ if ( 'id' == $key ) {
+ continue;
+ }
+ $value = $this->esc_attr( $value );
- $r = "<div id='contact-form-$id'>\n";
+ if ( is_array( $value ) ) {
+ $value = join( ',', $value );
+ }
- $errors = array();
- if ( is_wp_error( $contact_form_errors ) && $errors = (array) $contact_form_errors->get_error_codes() ) :
- $r .= "<div class='form-error'>\n<h3>" . __( 'Error!', 'jetpack' ) . "</h3>\n<p>\n";
- foreach ( $contact_form_errors->get_error_messages() as $message )
- $r .= "\t$message<br />\n";
- $r .= "</p>\n</div>\n\n";
- else :
- $r_success_message = "<h3>" . __( 'Message Sent', 'jetpack' ) . "</h3>\n\n";
- $r_success_message .= wp_kses($contact_form_message, array('br' => array(), 'blockquote' => array()));
+ if ( false === strpos( $value, "'" ) ) {
+ $value = "'$value'";
+ } elseif ( false === strpos( $value, '"' ) ) {
+ $value = '"' . $value . '"';
+ } else {
+ // Shortcodes can't contain both '"' and "'". Strip one.
+ $value = str_replace( "'", '', $value );
+ $value = "'$value'";
+ }
- $r .= apply_filters( 'grunion_contact_form_success_message', $r_success_message );
+ $r .= "{$key}={$value} ";
+ }
- $r .= "</div>";
-
- // Reset for multiple contact forms. Hacky
- $contact_form_values['comment_content'] = '';
+ $r = rtrim( $r );
- return $r;
- endif;
+ if ( $this->fields ) {
+ $r .= ']';
- return $r;
-}
-add_shortcode( 'contact-form', 'contact_form_shortcode' );
+ foreach ( $this->fields as $field ) {
+ $r .= (string) $field;
+ }
-function contact_form_send_message( $to, $subject, $widget ) {
- global $post;
-
- if ( !isset( $_POST['contact-form-id'] ) )
- return;
-
- if ( ( $widget && 'widget-' . $widget != $_POST['contact-form-id'] ) || ( !$widget && $post->ID != $_POST['contact-form-id'] ) )
- return;
-
- if ( $widget )
- check_admin_referer( 'contact-form_widget-' . $widget );
- else
- check_admin_referer( 'contact-form_' . $post->ID );
-
- global $contact_form_values, $contact_form_errors, $current_user, $user_identity;
- global $contact_form_fields, $contact_form_message;
-
- // compact the fields and values into an array of Label => Value pairs
- // also find values for comment_author_email and other significant fields
- $all_values = $extra_values = array();
-
- foreach ( $contact_form_fields as $id => $field ) {
- if ( $field['type'] == 'email' && !isset( $comment_author_email ) ) {
- $comment_author_email = $contact_form_values[ $id ];
- $comment_author_email_label = $field['label'];
- } elseif ( $field['type'] == 'name' && !isset( $comment_author ) ) {
- $comment_author = $contact_form_values[ $id ];
- $comment_author_label = $field['label'];
- } elseif ( $field['type'] == 'url' && !isset( $comment_author_url ) ) {
- $comment_author_url = $contact_form_values[ $id ];
- $comment_author_url_label = $field['label'];
- } elseif ( $field['type'] == 'subject' && !isset( $contact_form_subject ) ) {
- $contact_form_subject = $contact_form_values[$id];
- $contact_form_subject_label = $field['label'];
- } elseif ( $field['type'] == 'textarea' && !isset( $comment_content ) ) {
- $comment_content = $contact_form_values[ $id ];
- $comment_content_label = $field['label'];
+ $r .= "[/{$this->shortcode_name}]";
} else {
- $extra_values[ $field['label'] ] = $contact_form_values[ $id ];
+ $r .= '/]';
}
-
- $all_values[ $field['label'] ] = $contact_form_values[ $id ];
+
+ return $r;
}
+}
-/*
- $contact_form_values = array();
- $contact_form_errors = new WP_Error();
+/**
+ * Class for the contact-form shortcode.
+ * Parses shortcode to output the contact form as HTML
+ * Sends email and stores the contact form response (a.k.a. "feedback")
+ */
+class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
+ var $shortcode_name = 'contact-form';
- list($comment_author, $comment_author_email, $comment_author_url) = is_user_logged_in() ?
- add_magic_quotes( array( $user_identity, $current_user->data->user_email, $current_user->data->user_url ) ) :
- array( $_POST['comment_author'], $_POST['comment_author_email'], $_POST['comment_author_url'] );
-*/
+ /**
+ * @var WP_Error stores form submission errors
+ */
+ var $errors;
- $comment_author = stripslashes( apply_filters( 'pre_comment_author_name', $comment_author ) );
+ /**
+ * @var Grunion_Contact_Form The most recent (inclusive) contact-form shortcode processed
+ */
+ static $last;
- if ( !empty( $comment_author_email ) ) {
- $comment_author_email = stripslashes( apply_filters( 'pre_comment_author_email', $comment_author_email ) );
- } else {
- $comment_author_email = '';
- $comment_author_email_label = '';
- }
+ /**
+ * @var bool Whether to print the grunion.css style when processing the contact-form shortcode
+ */
+ static $style = false;
+
+ function __construct( $attributes, $content = null ) {
+ global $post;
+
+ // Set up the default subject and recipient for this form
+ $default_to = get_option( 'admin_email' );
+ $default_subject = "[" . get_option( 'blogname' ) . "]";
- if ( !empty( $comment_author_url ) ) {
- $comment_author_url = stripslashes( apply_filters( 'pre_comment_author_url', $comment_author_url ) );
- if ( 'http://' == $comment_author_url ) {
- $comment_author_url = '';
+ if ( !empty( $attributes['widget'] ) && $attributes['widget'] ) {
+ $attributes['id'] = 'widget-' . $attributes['widget'];
+
+ $default_subject = sprintf( _x( '%1$s Sidebar', '%1$s = blog name', 'jetpack' ), $default_subject );
+ } else if ( $post ) {
+ $attributes['id'] = $post->ID;
+ $default_subject = sprintf( _x( '%1$s %2$s', '%1$s = blog name, %2$s = post title', 'jetpack' ), $default_subject, Grunion_Contact_Form_Plugin::strip_tags( $post->post_title ) );
+ $post_author = get_userdata( $post->post_author );
+ $default_to = $post_author->user_email;
}
- } else {
- $comment_author_url = '';
- $comment_author_url_label = '';
- }
- $comment_content = stripslashes( $comment_content );
- $comment_content = trim( wp_kses( $comment_content, array() ) );
+ $this->defaults = array(
+ 'to' => $default_to,
+ 'subject' => $default_subject,
+ 'show_subject' => 'no', // only used in back-compat mode
+ 'widget' => 0, // Not exposed to the user. Works with Grunion_Contact_Form_Plugin::widget_atts()
+ 'id' => null, // Not exposed to the user. Set above.
+ );
+
+ $attributes = shortcode_atts( $this->defaults, $attributes );
- if ( empty( $contact_form_subject ) )
- $contact_form_subject = trim( wp_kses( $subject, array() ) );
- else
- $contact_form_subject = trim( wp_kses( $contact_form_subject, array() ) );
-
- $comment_author_IP = $_SERVER['REMOTE_ADDR'];
+ // We only add the contact-field shortcode temporarily while processing the contact-form shortcode
+ add_shortcode( 'contact-field', array( $this, 'parse_contact_field' ) );
- $vars = array( 'comment_author', 'comment_author_email', 'comment_author_url', 'contact_form_subject', 'comment_author_IP' );
- foreach ( $vars as $var )
- $$var = str_replace( array("\n", "\r" ), '', $$var ); // I don't know if it's possible to inject this
- $vars[] = 'comment_content';
+ parent::__construct( $attributes, $content );
- $contact_form_values = compact( $vars );
+ // There were no fields in the contact form. The form was probably just [contact-form /]. Build a default form.
+ if ( empty( $this->fields ) ) {
+ // same as the original Grunion v1 form
+ $default_form = '
+ [contact-field label="' . __( 'Name', 'jetpack' ) . '" type="name" required="true" /]
+ [contact-field label="' . __( 'Email', 'jetpack' ) . '" type="email" required="true" /]
+ [contact-field label="' . __( 'Website', 'jetpack' ) . '" type="url" /]';
- $spam = '';
- $akismet_values = contact_form_prepare_for_akismet( $contact_form_values );
- $is_spam = apply_filters( 'contact_form_is_spam', $akismet_values );
- if ( is_wp_error( $is_spam ) )
- return; // abort
- else if ( $is_spam === TRUE )
- $spam = '***SPAM*** ';
+ if ( 'yes' == strtolower( $this->get_attribute( 'show_subject' ) ) ) {
+ $default_form .= '
+ [contact-field label="' . __( 'Subject', 'jetpack' ) . '" type="subject" /]';
+ }
- if ( !$comment_author )
- $comment_author = $comment_author_email;
+ $default_form .= '
+ [contact-field label="' . __( 'Message', 'jetpack' ) . '" type="textarea" /]';
- $to = apply_filters( 'contact_form_to', $to );
- foreach ( (array) $to as $to_key => $to_value ) {
- $to[$to_key] = wp_kses( $to_value, array() );
+ $this->parse_content( $default_form );
+ }
+
+ // $this->body and $this->fields have been setup. We no longer need the contact-field shortcode.
+ remove_shortcode( 'contact-field' );
+ }
+
+ /**
+ * Toggle for printing the grunion.css stylesheet
+ *
+ * @param bool $style
+ */
+ static function style( $style ) {
+ $previous_style = self::$style;
+ self::$style = (bool) $style;
+ return $previous_style;
}
- $from_email_addr = $to[0];
- if ( !empty( $comment_author_email ) ) {
- $from_email_addr = $comment_author_email;
+ /**
+ * Turn on printing of grunion.css stylesheet
+ * @see ::style()
+ * @internal
+ * @param bool $style
+ */
+ static function _style_on() {
+ return self::style( true );
}
- $headers = 'From: ' . wp_kses( $comment_author, array() ) .
- ' <' . wp_kses( $from_email_addr, array() ) . ">\r\n" .
- 'Reply-To: ' . wp_kses( $from_email_addr, array() ) . "\r\n" .
- "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"";
- $subject = apply_filters( 'contact_form_subject', $contact_form_subject );
- $subject = wp_kses( $subject, array() );
+ /**
+ * The contact-form shortcode processor
+ *
+ * @param array $attributes Key => Value pairs as parsed by shortcode_parse_atts()
+ * @param string|null $content The shortcode's inner content: [contact-form]$content[/contact-form]
+ * @return string HTML for the concat form.
+ */
+ static function parse( $attributes, $content ) {
+ // Create a new Grunion_Contact_Form object (this class)
+ $form = new Grunion_Contact_Form( $attributes, $content );
+
+ $id = $form->get_attribute( 'id' );
- $time = date_i18n( __( 'l F j, Y \a\t g:i a', 'jetpack' ), current_time( 'timestamp' ) );
-
- $extra_content = '';
- $extra_content_br = '';
+ if ( !$id ) { // something terrible has happened
+ return '[contact-form]';
+ }
+
+ if ( apply_filters( 'jetpack_bail_on_shortcode', false, 'contact-form' ) || is_feed() ) {
+ return '[contact-form]';
+ }
+
+ // Only allow one contact form per post/widget
+ if ( self::$last && $id == self::$last->get_attribute( 'id' ) ) {
+ // We're processing the same post
+
+ if ( self::$last->attributes != $form->attributes || self::$last->content != $form->content ) {
+ // And we're processing a different shortcode;
+ return '';
+ } // else, we're processing the same shortcode - probably a separate run of do_shortcode() - let it through
+
+ } else {
+ self::$last = $form;
+ }
+
+ // Enqueue the grunion.css stylesheet if self::$style allows it
+ if ( self::$style && ( empty( $_REQUEST['action'] ) || $_REQUEST['action'] != 'grunion_shortcode_to_json' ) ) {
+ // Enqueue the style here instead of printing it, because if some other plugin has run the_post()+rewind_posts(),
+ // (like VideoPress does), the style tag gets "printed" the first time and discarded, leaving the contact form unstyled.
+ // when WordPress does the real loop.
+ wp_enqueue_style( 'grunion.css' );
+ }
+
+ $r = '';
+ $r .= "<div id='contact-form-$id'>\n";
- foreach ( $extra_values as $label => $value ) {
- $extra_content .= $label . ': ' . trim($value) . "\n";
- $extra_content_br .= wp_kses( $label, array() ) . ': ' . wp_kses( trim($value), array() ) . "<br />";
- }
-
- $message = "$comment_author_label: $comment_author\n";
- if ( !empty( $comment_author_email ) ) {
- $message .= "$comment_author_email_label: $comment_author_email\n";
- }
- if ( !empty( $comment_author_url ) ) {
- $message .= "$comment_author_url_label: $comment_author_url\n";
- }
- $message .= "$comment_content_label: $comment_content\n";
- $message .= $extra_content . "\n";
-
- $message .= __( "Time:", 'jetpack' ) . " " . $time . "\n";
- $message .= __( "IP Address:", 'jetpack' ) . " " . $comment_author_IP . "\n";
- $message .= __( "Contact Form URL:", 'jetpack' ) . " " . get_permalink( $post->ID ) . "\n";
-
-
- // Construct message that is returned to user
- $contact_form_message = "<blockquote>";
- if (isset($comment_author_label))
- $contact_form_message .= wp_kses( $comment_author_label, array() ) . ": " . wp_kses( $comment_author, array() ) . "<br />";
- if ( !empty( $comment_author_email ) )
- $contact_form_message .= wp_kses( $comment_author_email_label, array() ) . ": " . wp_kses( $comment_author_email, array() ) . "<br />";
- if ( !empty( $comment_author_url ) )
- $contact_form_message .= wp_kses( $comment_author_url_label, array() ) . ": " . wp_kses( $comment_author_url, array() ) . "<br />";
- if ( !empty( $contact_form_subject_label ) ) {
- $contact_form_message .= wp_kses( $contact_form_subject_label, array() ) . ": " . wp_kses( $contact_form_subject, array() ) . "<br />";
- }
- if (isset($comment_content_label))
- $contact_form_message .= wp_kses( $comment_content_label, array() ) . ": " . wp_kses( $comment_content, array() ) . "<br />";
- if (isset($extra_content_br))
- $contact_form_message .= $extra_content_br;
- $contact_form_message .= "</blockquote><br /><br />";
-
- if ( is_user_logged_in() ) {
- $message .= "\n";
- $message .= sprintf(
- __( 'Sent by a verified %s user.', 'jetpack' ),
- isset( $GLOBALS['current_site']->site_name ) && $GLOBALS['current_site']->site_name ? $GLOBALS['current_site']->site_name : '"' . get_option( 'blogname' ) . '"'
- );
- } else {
- $message .= __( "Sent by an unverified visitor to your site.", 'jetpack' );
- }
+ if ( is_wp_error( $form->errors ) && $form->errors->get_error_codes() ) {
+ // There are errors. Display them
+ $r .= "<div class='form-error'>\n<h3>" . __( 'Error!', 'jetpack' ) . "</h3>\n<ul class='form-errors'>\n";
+ foreach ( $form->errors->get_error_messages() as $message )
+ $r .= "\t<li class='form-error-message'>" . esc_html( $message ) . "</li>\n";
+ $r .= "</ul>\n</div>\n\n";
+ }
+
+ if ( isset( $_GET['contact-form-id'] ) && $_GET['contact-form-id'] == self::$last->get_attribute( 'id' ) && isset( $_GET['contact-form-sent'] ) ) {
+ // The contact form was submitted. Show the success message/results
+
+ $feedback_id = (int) $_GET['contact-form-sent'];
+
+ $back_url = remove_query_arg( array( 'contact-form-id', 'contact-form-sent', '_wpnonce' ) );
+
+ $r_success_message =
+ "<h3>" . __( 'Message Sent', 'jetpack' ) .
+ ' (<a href="' . esc_url( $back_url ) . '">' . esc_html__( 'go back', 'jetpack' ) . '</a>)' .
+ "</h3>\n\n";
+
+ // Don't show the feedback details unless the nonce matches
+ if ( $feedback_id && wp_verify_nonce( stripslashes( $_GET['_wpnonce'] ), "contact-form-sent-{$feedback_id}" ) ) {
+ $feedback = get_post( $feedback_id );
+
+ $field_ids = $form->get_field_ids();
+
+ // Maps field_ids to post_meta keys
+ $field_value_map = array(
+ 'name' => 'author',
+ 'email' => 'author_email',
+ 'url' => 'author_url',
+ 'subject' => 'subject',
+ 'textarea' => false, // not a post_meta key. This is stored in post_content
+ );
+
+ $contact_form_message = "<blockquote>\n";
+
+ // "Standard" field whitelist
+ foreach ( $field_value_map as $type => $meta_key ) {
+ if ( isset( $field_ids[$type] ) ) {
+ $field = $form->fields[$field_ids[$type]];
+
+ if ( $meta_key ) {
+ $value = get_post_meta( $feedback_id, "_feedback_{$meta_key}", true );
+ } else {
+ // The feedback content is stored as the first "half" of post_content
+ $value = $feedback->post_content;
+ list( $value ) = explode( '<!--more-->', $value );
+ $value = trim( $value );
+ }
+
+ $contact_form_message .= sprintf(
+ _x( '%1$s: %2$s', '%1$s = form field label, %2$s = form field value', 'jetpack' ),
+ wp_kses( $field->get_attribute( 'label' ), array() ),
+ wp_kses( $value, array() )
+ ) . '<br />';
+ }
+ }
+
+ // "Non-standard" fields
+ if ( $field_ids['extra'] ) {
+ // array indexed by field label (not field id)
+ $extra_fields = get_post_meta( $feedback_id, '_feedback_extra_fields', true );
+
+ foreach ( $field_ids['extra'] as $field_id ) {
+ $field = $form->fields[$field_id];
+ $label = $field->get_attribute( 'label' );
+ $contact_form_message .= sprintf(
+ _x( '%1$s: %2$s', '%1$s = form field label, %2$s = form field value', 'jetpack' ),
+ wp_kses( $label, array() ),
+ wp_kses( $extra_fields[$label], array() )
+ ) . '<br />';
+ }
+ }
+
+ $contact_form_message .= "</blockquote><br /><br />";
+
+ $r_success_message .= wp_kses( $contact_form_message, array( 'br' => array(), 'blockquote' => array() ) );
+ }
- $message = apply_filters( 'contact_form_message', $message );
- $message = wp_kses( $message, array() );
+ $r .= apply_filters( 'grunion_contact_form_success_message', $r_success_message );
+ } else {
+ // Nothing special - show the normal contact form
+
+ if ( $form->get_attribute( 'widget' ) ) {
+ // Submit form to the current URL
+ $url = remove_query_arg( array( 'contact-form-id', 'contact-form-sent', 'action', '_wpnonce' ) );
+ } else {
+ // Submit form to the post permalink
+ $url = get_permalink();
+ }
+
+ // May eventually want to send this to admin-post.php...
+ $url = apply_filters( 'grunion_contact_form_form_action', "{$url}#contact-form-{$id}", $GLOBALS['post'], $id );
+
+ $r .= "<form action='" . esc_url( $url ) . "' method='post' class='contact-form commentsblock'>\n";
+ $r .= $form->body;
+ $r .= "\t<p class='contact-submit'>\n";
+ $r .= "\t\t<input type='submit' value='" . esc_attr__( 'Submit &#187;', 'jetpack' ) . "' class='pushbutton-wide'/>\n";
+ $r .= "\t\t" . wp_nonce_field( 'contact-form_' . $id, '_wpnonce', true, false ) . "\n"; // nonce and referer
+ $r .= "\t\t<input type='hidden' name='contact-form-id' value='$id' />\n";
+ $r .= "\t\t<input type='hidden' name='action' value='grunion-contact-form' />\n";
+ $r .= "\t</p>\n";
+ $r .= "</form>\n";
+ }
- // keep a copy of the feedback as a custom post type
- $feedback_mysql_time = current_time( 'mysql' );
- $feedback_title = "{$comment_author} - {$feedback_mysql_time}";
- $feedback_status = 'publish';
- if ( $is_spam === TRUE )
- $feedback_status = 'spam';
+ $r .= "</div>";
- foreach ( (array) $akismet_values as $av_key => $av_value ) {
- $akismet_values[$av_key] = wp_kses( $av_value, array() );
+ return $r;
}
- foreach ( (array) $all_values as $all_key => $all_value ) {
- $all_values[$all_key] = wp_kses( $all_value, array() );
+ /**
+ * The contact-field shortcode processor
+ * We use an object method here instead of a static Grunion_Contact_Form_Field class method to parse contact-field shortcodes so that we can tie them to the contact-form object.
+ *
+ * @param array $attributes Key => Value pairs as parsed by shortcode_parse_atts()
+ * @param string|null $content The shortcode's inner content: [contact-field]$content[/contact-field]
+ * @return HTML for the contact form field
+ */
+ function parse_contact_field( $attributes, $content ) {
+ $field = new Grunion_Contact_Form_Field( $attributes, $content, $this );
+
+ $field_id = $field->get_attribute( 'id' );
+ if ( $field_id ) {
+ $this->fields[$field_id] = $field;
+ } else {
+ $this->fields[] = $field;
+ }
+
+ if (
+ isset( $_POST['action'] ) && 'grunion-contact-form' === $_POST['action']
+ &&
+ isset( $_POST['contact-form-id'] ) && $this->get_attribute( 'id' ) == $_POST['contact-form-id']
+ ) {
+ // If we're processing a POST submission for this contact form, validate the field value so we can show errors as necessary.
+ $field->validate();
+ }
+
+ // Output HTML
+ return $field->render();
}
- foreach ( (array) $extra_values as $ev_key => $ev_value ) {
- $ev_values[$ev_key] = wp_kses( $ev_value, array() );
+ /**
+ * Loops through $this->fields to generate a (structured) list of field IDs
+ * @return array
+ */
+ function get_field_ids() {
+ $field_ids = array(
+ 'all' => array(), // array of all field_ids
+ 'extra' => array(), // array of all non-whitelisted field IDs
+
+ // Whitelisted "standard" field IDs:
+ // 'email' => field_id,
+ // 'name' => field_id,
+ // 'url' => field_id,
+ // 'subject' => field_id,
+ // 'textarea' => field_id,
+ );
+
+ foreach ( $this->fields as $id => $field ) {
+ $field_ids['all'][] = $id;
+
+ $type = $field->get_attribute( 'type' );
+ if ( isset( $field_ids[$type] ) ) {
+ // This type of field is already present in our whitelist of "standard" fields for this form
+ // Put it in extra
+ $field_ids['extra'][] = $id;
+ continue;
+ }
+
+ switch ( $type ) {
+ case 'email' :
+ case 'name' :
+ case 'url' :
+ case 'subject' :
+ case 'textarea' :
+ $field_ids[$type] = $id;
+ break;
+ default :
+ // Put everything else in extra
+ $field_ids['extra'][] = $id;
+ }
+ }
+
+ return $field_ids;
}
- # We need to make sure that the post author is always zero for contact
- # form submissions. This prevents export/import from trying to create
- # new users based on form submissions from people who were logged in
- # at the time.
- #
- # Unfortunately wp_insert_post() tries very hard to make sure the post
- # author gets the currently logged in user id. That is how we ended up
- # with this work around.
- global $do_grunion_insert;
- $do_grunion_insert = TRUE;
- add_filter( 'wp_insert_post_data', 'grunion_insert_filter', 10, 2 );
+ /**
+ * Process the contact form's POST submission
+ * Stores feedback. Sends email.
+ */
+ function process_submission() {
+ global $post;
- $post_id = wp_insert_post( array(
- 'post_date' => $feedback_mysql_time,
- 'post_type' => 'feedback',
- 'post_status' => $feedback_status,
- 'post_parent' => $post->ID,
- 'post_title' => wp_kses( $feedback_title, array() ),
- 'post_content' => wp_kses($comment_content . "\n<!--more-->\n" . "AUTHOR: {$comment_author}\nAUTHOR EMAIL: {$comment_author_email}\nAUTHOR URL: {$comment_author_url}\nSUBJECT: {$contact_form_subject}\nIP: {$comment_author_IP}\n" . print_r( $all_values, TRUE ), array()), // so that search will pick up this data
- 'post_name' => md5( $feedback_title )
- ) );
+ $plugin = Grunion_Contact_Form_Plugin::init();
- # once insert has finished we don't need this filter any more
- remove_filter( 'wp_insert_post_data', 'grunion_insert_filter' );
- $do_grunion_insert = FALSE;
+ $id = $this->get_attribute( 'id' );
+ $to = $this->get_attribute( 'to' );
+ $widget = $this->get_attribute( 'widget' );
- update_post_meta( $post_id, '_feedback_author', wp_kses( $comment_author, array() ) );
- update_post_meta( $post_id, '_feedback_author_email', wp_kses( $comment_author_email, array() ) );
- update_post_meta( $post_id, '_feedback_author_url', wp_kses( $comment_author_url, array() ) );
- update_post_meta( $post_id, '_feedback_subject', wp_kses( $contact_form_subject, array() ) );
- update_post_meta( $post_id, '_feedback_ip', wp_kses( $comment_author_IP, array() ) );
- update_post_meta( $post_id, '_feedback_contact_form_url', wp_kses( get_permalink( $post->ID ), array() ) );
- update_post_meta( $post_id, '_feedback_all_fields', $all_values );
- update_post_meta( $post_id, '_feedback_extra_fields', $extra_values );
- update_post_meta( $post_id, '_feedback_akismet_values', $akismet_values );
- update_post_meta( $post_id, '_feedback_email', array( 'to' => $to, 'subject' => $subject, 'message' => $message, 'headers' => $headers ) );
+ $contact_form_subject = $this->get_attribute( 'subject' );
- do_action( 'grunion_pre_message_sent', $post_id, $all_values, $extra_values );
+ $to = str_replace( ' ', '', $to );
+ $emails = explode( ',', $to );
- # schedule deletes of old spam feedbacks
- if ( !wp_next_scheduled( 'grunion_scheduled_delete' ) ) {
- wp_schedule_event( time() + 250, 'daily', 'grunion_scheduled_delete' );
- }
+ $valid_emails = array();
- if ( $is_spam !== TRUE )
- return wp_mail( $to, "{$spam}{$subject}", $message, $headers );
- elseif ( apply_filters( 'grunion_still_email_spam', FALSE ) == TRUE )
- return wp_mail( $to, "{$spam}{$subject}", $message, $headers );
+ foreach ( (array) $emails as $email ) {
+ if ( !is_email( $email ) ) {
+ continue;
+ }
-}
+ if ( function_exists( 'is_email_address_unsafe' ) && is_email_address_unsafe( $email ) ) {
+ continue;
+ }
-// populate an array with all values necessary to submit a NEW comment to Akismet
-// note that this includes the current user_ip etc, so this should only be called when accepting a new item via $_POST
-function contact_form_prepare_for_akismet( $form ) {
+ $valid_emails[] = $email;
+ }
- $form['comment_type'] = 'contact_form';
- $form['user_ip'] = preg_replace( '/[^0-9., ]/', '', $_SERVER['REMOTE_ADDR'] );
- $form['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
- $form['referrer'] = $_SERVER['HTTP_REFERER'];
- $form['blog'] = get_option( 'home' );
+ // No one to send it to :(
+ if ( !$valid_emails ) {
+ return;
+ }
- $ignore = array( 'HTTP_COOKIE' );
+ $to = $valid_emails;
- foreach ( $_SERVER as $k => $value )
- if ( !in_array( $k, $ignore ) && is_string( $value ) )
- $form["$k"] = $value;
-
- return $form;
-}
+ // Make sure we're processing the form we think we're processing... probably a redundant check.
+ if ( $widget ) {
+ if ( 'widget-' . $widget != $_POST['contact-form-id'] ) {
+ return;
+ }
+ } else {
+ if ( $post->ID != $_POST['contact-form-id'] ) {
+ return;
+ }
+ }
-// submit an array to Akismet. If you're accepting a new item via $_POST, run it through contact_form_prepare_for_akismet() first
-function contact_form_is_spam_akismet( $form ) {
- if ( !function_exists( 'akismet_http_post' ) )
- return false;
-
- global $akismet_api_host, $akismet_api_port;
-
- $query_string = '';
- foreach ( array_keys( $form ) as $k )
- $query_string .= $k . '=' . urlencode( $form[$k] ) . '&';
-
- $response = akismet_http_post( $query_string, $akismet_api_host, '/1.1/comment-check', $akismet_api_port );
- $result = false;
- if ( 'true' == trim( $response[1] ) ) // 'true' is spam
- $result = true;
- return apply_filters( 'contact_form_is_spam_akismet', $result, $form );
-}
+ $field_ids = $this->get_field_ids();
-// submit a comment as either spam or ham
-// $as should be a string (either 'spam' or 'ham'), $form should be the comment array
-function contact_form_akismet_submit( $as, $form ) {
- global $akismet_api_host, $akismet_api_port;
-
- if ( !in_array( $as, array( 'ham', 'spam' ) ) )
- return false;
+ // Initialize all these "standard" fields to null
+ $comment_author_email = $comment_author_email_label = // v
+ $comment_author = $comment_author_label = // v
+ $comment_author_url = $comment_author_url_label = // v
+ $comment_content = $comment_content_label = null;
- $query_string = '';
- foreach ( array_keys( $form ) as $k )
- $query_string .= $k . '=' . urlencode( $form[$k] ) . '&';
+ // For each of the "standard" fields, grab their field label and value.
- $response = akismet_http_post( $query_string, $akismet_api_host, '/1.1/submit-'.$as, $akismet_api_port );
- return trim( $response[1] );
-}
+ if ( isset( $field_ids['name'] ) ) {
+ $field = $this->fields[$field_ids['name']];
+ $comment_author = Grunion_Contact_Form_Plugin::strip_tags( stripslashes( apply_filters( 'pre_comment_author_name', addslashes( $field->value ) ) ) );
+ $comment_author_label = Grunion_Contact_Form_Plugin::strip_tags( $field->get_attribute( 'label' ) );
+ }
-function contact_form_widget_atts( $text ) {
- static $widget = 0;
-
- $widget++;
+ if ( isset( $field_ids['email'] ) ) {
+ $field = $this->fields[$field_ids['email']];
+ $comment_author_email = Grunion_Contact_Form_Plugin::strip_tags( stripslashes( apply_filters( 'pre_comment_author_email', addslashes( $field->value ) ) ) );
+ $comment_author_email_label = Grunion_Contact_Form_Plugin::strip_tags( $field->get_attribute( 'label' ) );
+ }
- return preg_replace( '/\[contact-form([^a-zA-Z_-])/', '[contact-form widget="' . $widget . '"\\1', $text );
-}
-add_filter( 'widget_text', 'contact_form_widget_atts', 0 );
+ if ( isset( $field_ids['url'] ) ) {
+ $field = $this->fields[$field_ids['url']];
+ $comment_author_url = Grunion_Contact_Form_Plugin::strip_tags( stripslashes( apply_filters( 'pre_comment_author_url', addslashes( $field->value ) ) ) );
+ if ( 'http://' == $comment_author_url ) {
+ $comment_author_url = '';
+ }
+ $comment_author_url_label = Grunion_Contact_Form_Plugin::strip_tags( $field->get_attribute( 'label' ) );
+ }
-function contact_form_widget_shortcode_hack( $text ) {
- if ( !preg_match( '/\[contact-form([^a-zA-Z_-])/', $text ) ) {
- return $text;
- }
+ if ( isset( $field_ids['textarea'] ) ) {
+ $field = $this->fields[$field_ids['textarea']];
+ $comment_content = trim( Grunion_Contact_Form_Plugin::strip_tags( $field->value ) );
+ $comment_content_label = Grunion_Contact_Form_Plugin::strip_tags( $field->get_attribute( 'label' ) );
+ }
- $old = $GLOBALS['shortcode_tags'];
- remove_all_shortcodes();
- add_shortcode( 'contact-form', 'contact_form_shortcode' );
- add_shortcode( 'contact-field', 'contact_form_field' );
- $text = do_shortcode( $text );
- $GLOBALS['shortcode_tags'] = $old;
- return $text;
-}
+ if ( isset( $field_ids['subject'] ) ) {
+ $field = $this->fields[$field_ids['subject']];
+ if ( $field->value ) {
+ $contact_form_subject = Grunion_Contact_Form_Plugin::strip_tags( $field->value );
+ }
+ }
+
+ $all_values = $extra_values = array();
+
+ // For all fields, grab label and value
+ foreach ( $field_ids['all'] as $field_id ) {
+ $field = $this->fields[$field_id];
+ $label = $field->get_attribute( 'label' );
+ $value = $field->value;
+ $all_values[$label] = $value;
+ }
+
+ // For the "non-standard" fields, grab label and value
+ foreach ( $field_ids['extra'] as $field_id ) {
+ $field = $this->fields[$field_id];
+ $label = $field->get_attribute( 'label' );
+ $value = $field->value;
+ $extra_values[$label] = $value;
+ }
+
+ $contact_form_subject = trim( $contact_form_subject );
+
+ $comment_author_IP = Grunion_Contact_Form_Plugin::strip_tags( $_SERVER['REMOTE_ADDR'] );
+
+ $vars = array( 'comment_author', 'comment_author_email', 'comment_author_url', 'contact_form_subject', 'comment_author_IP' );
+ foreach ( $vars as $var )
+ $$var = str_replace( array( "\n", "\r" ), '', $$var );
+ $vars[] = 'comment_content';
+
+ $spam = '';
+ $akismet_values = $plugin->prepare_for_akismet( compact( $vars ) );
+
+ // Is it spam?
+ $is_spam = apply_filters( 'contact_form_is_spam', $akismet_values );
+ if ( is_wp_error( $is_spam ) ) // WP_Error to abort
+ return; // abort
+ else if ( $is_spam === TRUE ) // TRUE to flag a spam
+ $spam = '***SPAM*** ';
+
+ if ( !$comment_author )
+ $comment_author = $comment_author_email;
+
+ $to = (array) apply_filters( 'contact_form_to', $to );
+ foreach ( $to as $to_key => $to_value ) {
+ $to[$to_key] = Grunion_Contact_Form_Plugin::strip_tags( $to_value );
+ }
-function contact_form_init() {
- if ( function_exists( 'akismet_http_post' ) ) {
- add_filter( 'contact_form_is_spam', 'contact_form_is_spam_akismet', 10 );
- add_action( 'contact_form_akismet', 'contact_form_akismet_submit', 10, 2 );
- }
- if ( !has_filter( 'widget_text', 'do_shortcode' ) )
- add_filter( 'widget_text', 'contact_form_widget_shortcode_hack', 5 );
-
- // custom post type we'll use to keep copies of the feedback items
- register_post_type( 'feedback', array(
- 'labels' => array(
- 'name' => __( 'Feedbacks', 'jetpack' ),
- 'singular_name' => __( 'Feedback', 'jetpack' ),
- 'search_items' => __( 'Search Feedback', 'jetpack' ),
- 'not_found' => __( 'No feedback found', 'jetpack' ),
- 'not_found_in_trash' => __( 'No feedback found', 'jetpack' )
- ),
- 'menu_icon' => GRUNION_PLUGIN_URL . 'images/grunion-menu.png',
- 'show_ui' => TRUE,
- 'show_in_admin_bar' => FALSE,
- 'public' => FALSE,
- 'rewrite' => FALSE,
- 'query_var' => FALSE,
- 'capability_type' => 'page'
- ) );
-
- register_post_status( 'spam', array(
- 'label' => 'Spam',
- 'public' => FALSE,
- 'exclude_from_search' => TRUE,
- 'show_in_admin_all_list' => FALSE,
- 'label_count' => _n_noop( 'Spam <span class="count">(%s)</span>', 'Spam <span class="count">(%s)</span>', 'jetpack' ),
- 'protected' => TRUE,
- '_builtin' => FALSE
- ) );
+ $blog_url = parse_url( site_url() );
+ $from_email_addr = 'wordpress@' . $blog_url['host'];
+
+ $reply_to_addr = $to[0];
+ if ( ! empty( $comment_author_email ) ) {
+ $reply_to_addr = $comment_author_email;
+ }
+
+ $headers = 'From: ' . $comment_author .' <' . $from_email_addr . ">\r\n" .
+ 'Reply-To: ' . $comment_author . ' <' . $reply_to_addr . ">\r\n" .
+ "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"";
+
+ $subject = apply_filters( 'contact_form_subject', $contact_form_subject );
+
+ $time = date_i18n( __( 'l F j, Y \a\t g:i a', 'jetpack' ), current_time( 'timestamp' ) );
- /* Can be dequeued by placing the following in wp-content/themes/yourtheme/functions.php
- *
- * function remove_grunion_style() {
- * wp_deregister_style('grunion.css');
- * }
- * add_action('wp_print_styles', 'remove_grunion_style');
- */
+ $extra_content = '';
- wp_register_style('grunion.css', GRUNION_PLUGIN_URL . 'css/grunion.css');
+ foreach ( $extra_values as $label => $value ) {
+ $extra_content .= $label . ': ' . trim( $value ) . "\n";
+ }
+
+ $message = "$comment_author_label: $comment_author\n";
+ if ( !empty( $comment_author_email ) ) {
+ $message .= "$comment_author_email_label: $comment_author_email\n";
+ }
+ if ( !empty( $comment_author_url ) ) {
+ $message .= "$comment_author_url_label: $comment_author_url\n";
+ }
+ if ( !empty( $comment_content_label ) ) {
+ $message .= "$comment_content_label: $comment_content\n";
+ }
+ $message .= $extra_content . "\n";
+
+ $message .= __( 'Time:', 'jetpack' ) . ' ' . $time . "\n";
+ $message .= __( 'IP Address:', 'jetpack' ) . ' ' . $comment_author_IP . "\n";
+
+ if ( $widget ) {
+ $url = home_url( '/' );
+ } else {
+ $url = get_permalink( $post->ID );
+ }
+
+ $message .= __( 'Contact Form URL:', 'jetpack' ) . " $url\n";
+
+ if ( is_user_logged_in() ) {
+ $message .= "\n";
+ $message .= sprintf(
+ __( 'Sent by a verified %s user.', 'jetpack' ),
+ isset( $GLOBALS['current_site']->site_name ) && $GLOBALS['current_site']->site_name ? $GLOBALS['current_site']->site_name : '"' . get_option( 'blogname' ) . '"'
+ );
+ } else {
+ $message .= __( 'Sent by an unverified visitor to your site.', 'jetpack' );
+ }
+
+ $message = apply_filters( 'contact_form_message', $message );
+ $message = Grunion_Contact_Form_Plugin::strip_tags( $message );
+
+ // keep a copy of the feedback as a custom post type
+ $feedback_mysql_time = current_time( 'mysql' );
+ $feedback_title = "{$comment_author} - {$feedback_mysql_time}";
+ $feedback_status = 'publish';
+ if ( $is_spam === TRUE )
+ $feedback_status = 'spam';
+
+ foreach ( (array) $akismet_values as $av_key => $av_value ) {
+ $akismet_values[$av_key] = Grunion_Contact_Form_Plugin::strip_tags( $av_value );
+ }
+
+ foreach ( (array) $all_values as $all_key => $all_value ) {
+ $all_values[$all_key] = Grunion_Contact_Form_Plugin::strip_tags( $all_value );
+ }
+
+ foreach ( (array) $extra_values as $ev_key => $ev_value ) {
+ $extra_values[$ev_key] = Grunion_Contact_Form_Plugin::strip_tags( $ev_value );
+ }
+
+ /* We need to make sure that the post author is always zero for contact
+ * form submissions. This prevents export/import from trying to create
+ * new users based on form submissions from people who were logged in
+ * at the time.
+ *
+ * Unfortunately wp_insert_post() tries very hard to make sure the post
+ * author gets the currently logged in user id. That is how we ended up
+ * with this work around. */
+ add_filter( 'wp_insert_post_data', array( $plugin, 'insert_feedback_filter' ), 10, 2 );
+
+ $post_id = wp_insert_post( array(
+ 'post_date' => addslashes( $feedback_mysql_time ),
+ 'post_type' => 'feedback',
+ 'post_status' => addslashes( $feedback_status ),
+ 'post_parent' => (int) $post->ID,
+ 'post_title' => addslashes( wp_kses( $feedback_title, array() ) ),
+ 'post_content' => addslashes( wp_kses( $comment_content . "\n<!--more-->\n" . "AUTHOR: {$comment_author}\nAUTHOR EMAIL: {$comment_author_email}\nAUTHOR URL: {$comment_author_url}\nSUBJECT: {$contact_form_subject}\nIP: {$comment_author_IP}\n" . print_r( $all_values, TRUE ), array() ) ), // so that search will pick up this data
+ 'post_name' => md5( $feedback_title ),
+ ) );
+
+ // once insert has finished we don't need this filter any more
+ remove_filter( 'wp_insert_post_data', array( $plugin, 'insert_feedback_filter' ), 10, 2 );
+
+ update_post_meta( $post_id, '_feedback_author', addslashes( $comment_author ) );
+ update_post_meta( $post_id, '_feedback_author_email', addslashes( $comment_author_email ) );
+ update_post_meta( $post_id, '_feedback_author_url', addslashes( $comment_author_url ) );
+ update_post_meta( $post_id, '_feedback_subject', addslashes( $contact_form_subject ) );
+ update_post_meta( $post_id, '_feedback_ip', addslashes( $comment_author_IP ) );
+ update_post_meta( $post_id, '_feedback_contact_form_url', addslashes( get_permalink( $post->ID ) ) );
+ update_post_meta( $post_id, '_feedback_all_fields', $this->addslashes_deep( $all_values ) );
+ update_post_meta( $post_id, '_feedback_extra_fields', $this->addslashes_deep( $extra_values ) );
+ update_post_meta( $post_id, '_feedback_akismet_values', $this->addslashes_deep( $akismet_values ) );
+ update_post_meta( $post_id, '_feedback_email', $this->addslashes_deep( array( 'to' => $to, 'subject' => $subject, 'message' => $message, 'headers' => $headers ) ) );
+
+ do_action( 'grunion_pre_message_sent', $post_id, $all_values, $extra_values );
+
+ // schedule deletes of old spam feedbacks
+ if ( !wp_next_scheduled( 'grunion_scheduled_delete' ) ) {
+ wp_schedule_event( time() + 250, 'daily', 'grunion_scheduled_delete' );
+ }
+
+ if ( $is_spam !== TRUE )
+ wp_mail( $to, "{$spam}{$subject}", $message, $headers );
+ elseif ( apply_filters( 'grunion_still_email_spam', FALSE ) == TRUE ) // don't send spam by default. Filterable.
+ wp_mail( $to, "{$spam}{$subject}", $message, $headers );
+
+ $redirect = wp_get_referer();
+ if ( !$redirect ) { // wp_get_referer() returns false if the referer is the same as the current page
+ $redirect = $_SERVER['REQUEST_URI'];
+ }
+
+ $redirect = add_query_arg( urlencode_deep( array(
+ 'contact-form-id' => $id,
+ 'contact-form-sent' => $post_id,
+ '_wpnonce' => wp_create_nonce( "contact-form-sent-{$post_id}" ), // wp_nonce_url HTMLencodes :(
+ ) ), $redirect );
+
+ $redirect = apply_filters( 'grunion_contact_form_redirect_url', $redirect, $id, $post_id );
+
+ wp_safe_redirect( $redirect );
+ exit;
+ }
+
+ function addslashes_deep( $value ) {
+ if ( is_array( $value ) ) {
+ return array_map( array( $this, 'addslashes_deep' ), $value );
+ } elseif ( is_object( $value ) ) {
+ $vars = get_object_vars( $value );
+ foreach ( $vars as $key => $data ) {
+ $value->{$key} = $this->addslashes_deep( $data );
+ }
+ return $value;
+ }
+
+ return addslashes( $value );
+ }
}
-add_action( 'init', 'contact_form_init' );
/**
- * Add a contact form button to the post composition screen
+ * Class for the contact-field shortcode.
+ * Parses shortcode to output the contact form field as HTML.
+ * Validates input.
*/
-add_action( 'media_buttons', 'grunion_media_button', 999 );
-function grunion_media_button( ) {
- global $post_ID, $temp_ID;
- $iframe_post_id = (int) (0 == $post_ID ? $temp_ID : $post_ID);
- $title = esc_attr( __( 'Add a custom form', 'jetpack' ) );
- $plugin_url = esc_url( GRUNION_PLUGIN_URL );
- $site_url = admin_url( "/admin-ajax.php?post_id=$iframe_post_id&amp;grunion=form-builder&amp;action=grunion_form_builder&amp;TB_iframe=true&amp;width=768" );
-
- echo '<a href="' . $site_url . '&id=add_form" class="thickbox" title="' . $title . '"><div class="grunion-menu-button" alt="' . $title . '"></div></a>';
-}
+class Grunion_Contact_Form_Field extends Crunion_Contact_Form_Shortcode {
+ var $shortcode_name = 'contact-field';
+ /**
+ * @var Grunion_Contact_Form parent form
+ */
+ var $form;
-if ( !empty( $_GET['grunion'] ) && $_GET['grunion'] == 'form-builder' ) {
- add_action( 'parse_request', 'parse_wp_request' );
- add_action( 'wp_ajax_grunion_form_builder', 'parse_wp_request' );
-}
+ /**
+ * @var string default or POSTed value
+ */
+ var $value;
-function parse_wp_request( $wp ) {
- display_form_view( );
- exit;
-}
+ /**
+ * @var bool Is the input invalid?
+ */
+ var $error = false;
-function display_form_view( ) {
- require_once GRUNION_PLUGIN_DIR . 'grunion-form-view.php';
-}
+ /**
+ * @param array $attributes An associative array of shortcode attributes. @see shortcode_atts()
+ * @param null|string $content Null for selfclosing shortcodes. The inner content otherwise.
+ * @param Grunion_Contact_Form $form The parent form
+ */
+ function __construct( $attributes, $content = null, $form = null ) {
+ $attributes = shortcode_atts( array(
+ 'label' => null,
+ 'type' => 'text',
+ 'required' => false,
+ 'options' => array(),
+ 'id' => null,
+ 'default' => null,
+ ), $attributes );
+
+ // special default for subject field
+ if ( 'subject' == $attributes['type'] && is_null( $attributes['default'] ) && !is_null( $form ) ) {
+ $attributes['default'] = $form->get_attribute( 'subject' );
+ }
-function menu_alter() {
- echo '
- <style>
- #menu-posts-feedback .wp-menu-image img { display: none; }
- #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 6px 7px;
- }
- #adminmenu .menu-icon-feedback div.wp-menu-image {
- background: url("' . GRUNION_PLUGIN_URL . 'images/grunion-menu.png") no-repeat 6px 7px;
- }
- .grunion-menu-button {
- background: url("' . GRUNION_PLUGIN_URL . 'images/grunion-form.png") no-repeat;
- width: 13px;
- height: 12px;
- display: inline-block;
- }
- @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) {
- #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 6px 7px;
- background-size: 15px 16px;
- }
- #adminmenu .menu-icon-feedback div.wp-menu-image {
- background: url("' . GRUNION_PLUGIN_URL . 'images/grunion-menu-2x.png") no-repeat 6px 7px;
- background-size: 15px 16px;
- }
- .grunion-menu-button {
- background-image: url("' . GRUNION_PLUGIN_URL . 'images/grunion-form-2x.png");
- background-size: 13px 12px;
- vertical-align: bottom;
- }
- }
- </style>';
-}
+ // allow required=1 or required=true
+ if ( '1' == $attributes['required'] || 'true' == strtolower( $attributes['required'] ) )
+ $attributes['required'] = true;
+ else
+ $attributes['required'] = false;
-add_action('admin_head', 'menu_alter');
+ // parse out comma-separated options list (for selects and radios)
+ if ( !empty( $attributes['options'] ) && is_string( $attributes['options'] ) ) {
+ $attributes['options'] = array_map( 'trim', explode( ',', $attributes['options'] ) );
+ }
-function grunion_insert_filter( $data, $postarr ) {
- global $do_grunion_insert;
+ if ( $form ) {
+ // make a unique field ID based on the label, with an incrementing number if needed to avoid clashes
+ $form_id = $form->get_attribute( 'id' );
+ $id = isset( $attributes['id'] ) ? $attributes['id'] : false;
+
+ $unescaped_label = $this->unesc_attr( $attributes['label'] );
+ $unescaped_label = str_replace( '%', '-', $unescaped_label ); // jQuery doesn't like % in IDs?
+ $unescaped_label = preg_replace( '/[^a-zA-Z0-9.-_:]/', '', $unescaped_label );
+
+ if ( empty( $id ) ) {
+ $id = sanitize_title_with_dashes( 'g' + $form_id . '-' . $unescaped_label );
+ $i = 0;
+ $max_tries = 24;
+ while ( isset( $form->fields[$id] ) ) {
+ $i++;
+ $id = sanitize_title_with_dashes( 'g' + $form_id . '-' . $unescaped_label . '-' . $i );
+
+ if ( $i > $max_tries ) {
+ break;
+ }
+ }
+ }
- if ( $do_grunion_insert === TRUE ) {
- if ( $data['post_type'] == 'feedback' ) {
- if ( $postarr['post_type'] == 'feedback' ) {
- $data['post_author'] = 0;
+ $attributes['id'] = $id;
+ }
+
+ parent::__construct( $attributes, $content );
+
+ // Store parent form
+ $this->form = $form;
+ }
+
+ /**
+ * This field's input is invalid. Flag as invalid and add an error to the parent form
+ *
+ * @param string $message The error message to display on the form.
+ */
+ function add_error( $message ) {
+ $this->is_error = true;
+
+ if ( !is_wp_error( $this->form->errors ) ) {
+ $this->form->errors = new WP_Error;
+ }
+
+ $this->form->errors->add( $this->get_attribute( 'id' ), $message );
+ }
+
+ /**
+ * Is the field input invalid?
+ *
+ * @see $error
+ *
+ * @return bool
+ */
+ function is_error() {
+ return $this->error;
+ }
+
+ /**
+ * Validates the form input
+ */
+ function validate() {
+ // If it's not required, there's nothing to validate
+ if ( !$this->get_attribute( 'required' ) ) {
+ return;
+ }
+
+ $field_id = $this->get_attribute( 'id' );
+ $field_type = $this->get_attribute( 'type' );
+ $field_label = $this->get_attribute( 'label' );
+
+ $field_value = isset( $_POST[$field_id] ) ? stripslashes( $_POST[$field_id] ) : '';
+
+ switch ( $field_type ) {
+ case 'email' :
+ // Make sure the email address is valid
+ if ( !is_email( $field_value ) ) {
+ $this->add_error( sprintf( __( '%s requires a valid email address', 'jetpack' ), $field_label ) );
+ }
+ break;
+ default :
+ // Just check for presence of any text
+ if ( !strlen( trim( $field_value ) ) ) {
+ $this->add_error( sprintf( __( '%s is required', 'jetpack' ), $field_label ) );
}
}
}
- return $data;
+ /**
+ * Outputs the HTML for this form field
+ *
+ * @return string HTML
+ */
+ function render() {
+ global $current_user, $user_identity;
+
+ $r = '';
+
+ $field_id = $this->get_attribute( 'id' );
+ $field_type = $this->get_attribute( 'type' );
+ $field_label = $this->get_attribute( 'label' );
+ $field_required = $this->get_attribute( 'required' );
+
+ if ( isset( $_POST[$field_id] ) ) {
+ $this->value = stripslashes( (string) $_POST[$field_id] );
+ } elseif ( is_user_logged_in() ) {
+ // Special defaults for logged-in users
+ switch ( $this->get_attribute( 'type' ) ) {
+ case 'email';
+ $this->value = $current_user->data->user_email;
+ break;
+ case 'name' :
+ $this->value = $user_identity;
+ break;
+ case 'url' :
+ $this->value = $current_user->data->user_url;
+ break;
+ default :
+ $this->value = $this->get_attribute( 'default' );
+ }
+ } else {
+ $this->value = $this->get_attribute( 'default' );
+ }
+
+ $field_value = Grunion_Contact_Form_Plugin::strip_tags( $this->value );
+ $field_label = Grunion_Contact_Form_Plugin::strip_tags( $field_label );
+
+ switch ( $field_type ) {
+ case 'email' :
+ $r .= "\n<div>\n";
+ $r .= "\t\t<label for='" . esc_attr( $field_id ) . "' class='grunion-field-label email" . ( $this->is_error() ? ' form-error' : '' ) . "'>" . esc_html( $field_label ) . ( $field_required ? '<span>' . __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
+ $r .= "\t\t<input type='email' name='" . esc_attr( $field_id ) . "' id='" . esc_attr( $field_id ) . "' value='" . esc_attr( $field_value ) . "' class='email' />\n";
+ $r .= "\t</div>\n";
+ break;
+ case 'textarea' :
+ $r .= "\n<div>\n";
+ $r .= "\t\t<label for='contact-form-comment-" . esc_attr( $field_id ) . "' class='grunion-field-label textarea" . ( $this->is_error() ? ' form-error' : '' ) . "'>" . esc_html( $field_label ) . ( $field_required ? '<span>' . __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
+ $r .= "\t\t<textarea name='" . esc_attr( $field_id ) . "' id='contact-form-comment-" . esc_attr( $field_id ) . "' rows='20'>" . esc_textarea( $field_value ) . "</textarea>\n";
+ $r .= "\t</div>\n";
+ break;
+ case 'radio' :
+ $r .= "\t<div><label class='grunion-field-label" . ( $this->is_error() ? ' form-error' : '' ) . "'>" . esc_html( $field_label ) . ( $field_required ? '<span>' . __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
+ foreach ( $this->get_attribute( 'options' ) as $option ) {
+ $option = Grunion_Contact_Form_Plugin::strip_tags( $option );
+ $r .= "\t\t<label class='grunion-radio-label radio" . ( $this->is_error() ? ' form-error' : '' ) . "'>";
+ $r .= "<input type='radio' name='" . esc_attr( $field_id ) . "' value='" . esc_attr( $option ) . "' class='radio' " . checked( $option, $field_value, false ) . " /> ";
+ $r .= esc_html( $option ) . "</label>\n";
+ $r .= "\t\t<div class='clear-form'></div>\n";
+ }
+ $r .= "\t\t</div>\n";
+ break;
+ case 'checkbox' :
+ $r .= "\t<div>\n";
+ $r .= "\t\t<label class='grunion-field-label checkbox" . ( $this->is_error() ? ' form-error' : '' ) . "'>\n";
+ $r .= "\t\t<input type='checkbox' name='" . esc_attr( $field_id ) . "' value='" . esc_attr__( 'Yes', 'jetpack' ) . "' class='checkbox' " . checked( (bool) $field_value, true, false ) . " /> \n";
+ $r .= "\t\t" . esc_html( $field_label ) . ( $field_required ? '<span>'. __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
+ $r .= "\t\t<div class='clear-form'></div>\n";
+ $r .= "\t</div>\n";
+ break;
+ case 'select' :
+ $r .= "\n<div>\n";
+ $r .= "\t\t<label for='" . esc_attr( $field_id ) . "' class='grunion-field-label select" . ( $this->is_error() ? ' form-error' : '' ) . "'>" . esc_html( $field_label ) . ( $field_required ? '<span>'. __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
+ $r .= "\t<select name='" . esc_attr( $field_id ) . "' id='" . esc_attr( $field_id ) . "' class='select' />\n";
+ foreach ( $this->get_attribute( 'options' ) as $option ) {
+ $option = Grunion_Contact_Form_Plugin::strip_tags( $option );
+ $r .= "\t\t<option" . selected( $option, $field_value, false ) . ">" . esc_html( $option ) . "</option>\n";
+ }
+ $r .= "\t</select>\n";
+ $r .= "\t</div>\n";
+ break;
+ default : // text field
+ // note that any unknown types will produce a text input, so we can use arbitrary type names to handle
+ // input fields like name, email, url that require special validation or handling at POST
+ $r .= "\n<div>\n";
+ $r .= "\t\t<label for='" . esc_attr( $field_id ) . "' class='grunion-field-label " . esc_attr( $field_type ) . ( $this->is_error() ? ' form-error' : '' ) . "'>" . esc_html( $field_label ) . ( $field_required ? '<span>' . __( "(required)", 'jetpack' ) . '</span>' : '' ) . "</label>\n";
+ $r .= "\t\t<input type='text' name='" . esc_attr( $field_id ) . "' id='" . esc_attr( $field_id ) . "' value='" . esc_attr( $field_value ) . "' class='" . esc_attr( $field_type ) . "'/>\n";
+ $r .= "\t</div>\n";
+ }
+
+ return $r;
+ }
}
+add_action( 'init', array( 'Grunion_Contact_Form_Plugin', 'init' ) );
+
add_action( 'grunion_scheduled_delete', 'grunion_delete_old_spam' );
+
+/**
+ * Deletes old spam feedbacks to keep the posts table size under control
+ */
function grunion_delete_old_spam() {
global $wpdb;
diff --git a/plugins/jetpack/modules/contact-form/images/grunion-menu-2x.png b/plugins/jetpack/modules/contact-form/images/grunion-menu-2x.png
index 04fd8be5..7c197441 100644
--- a/plugins/jetpack/modules/contact-form/images/grunion-menu-2x.png
+++ b/plugins/jetpack/modules/contact-form/images/grunion-menu-2x.png
Binary files differ
diff --git a/plugins/jetpack/modules/contact-form/images/grunion-menu-hover-2x.png b/plugins/jetpack/modules/contact-form/images/grunion-menu-hover-2x.png
index f4656a98..21840d17 100644
--- a/plugins/jetpack/modules/contact-form/images/grunion-menu-hover-2x.png
+++ b/plugins/jetpack/modules/contact-form/images/grunion-menu-hover-2x.png
Binary files differ
diff --git a/plugins/jetpack/modules/contact-form/images/grunion-remove-field-2x.png b/plugins/jetpack/modules/contact-form/images/grunion-remove-field-2x.png
index 49553746..244c102c 100644
--- a/plugins/jetpack/modules/contact-form/images/grunion-remove-field-2x.png
+++ b/plugins/jetpack/modules/contact-form/images/grunion-remove-field-2x.png
Binary files differ
diff --git a/plugins/jetpack/modules/contact-form/images/grunion-remove-field-hover-2x.png b/plugins/jetpack/modules/contact-form/images/grunion-remove-field-hover-2x.png
index 561382fa..11fc10ed 100644
--- a/plugins/jetpack/modules/contact-form/images/grunion-remove-field-hover-2x.png
+++ b/plugins/jetpack/modules/contact-form/images/grunion-remove-field-hover-2x.png
Binary files differ
diff --git a/plugins/jetpack/modules/contact-form/js/grunion.js b/plugins/jetpack/modules/contact-form/js/grunion.js
index 4fe391bf..835f7f80 100644
--- a/plugins/jetpack/modules/contact-form/js/grunion.js
+++ b/plugins/jetpack/modules/contact-form/js/grunion.js
@@ -22,6 +22,16 @@ GrunionFB_i18n = jQuery.extend( {
GrunionFB_i18n.moveInstructions = GrunionFB_i18n.moveInstructions.replace( "\n", '<br />' );
+FB.span = jQuery( '<span>' );
+FB.esc_html = function( string ) {
+ return FB.span.text( string ).html();
+};
+
+FB.esc_attr = function( string ) {
+ string = FB.esc_html( string );
+ return string.replace( '"', '&quot;' ).replace( "'", '&#039;' );
+};
+
FB.ContactForm = function() {
var fbForm = { // Main object that generated shortcode via AJAX call
'action' : 'grunion_shortcode',
@@ -31,28 +41,28 @@ FB.ContactForm = function() {
'fields' : {}
};
var defaultFields = {
- 'name': {
+ 'name': {
'label' : GrunionFB_i18n.nameLabel,
'type' : 'name',
'required' : true,
'options' : [],
'order' : '1'
- },
- 'email': {
+ },
+ 'email': {
'label' : GrunionFB_i18n.emailLabel,
'type' : 'email',
'required' : true,
'options' : [],
'order' : '2'
- },
- 'url': {
+ },
+ 'url': {
'label' : GrunionFB_i18n.urlLabel,
'type' : 'url',
'required' : false,
'options' : [],
'order' : '3'
- },
- 'comment': {
+ },
+ 'comment': {
'label' : GrunionFB_i18n.commentLabel,
'type' : 'textarea',
'required' : true,
@@ -66,7 +76,7 @@ FB.ContactForm = function() {
var optionsCache = {};
var optionsCount = 0; // increment for options
var shortcode;
-
+
function addField () {
try {
grunionNewCount++;
@@ -103,7 +113,7 @@ FB.ContactForm = function() {
}
}
function addOption () {
- try {
+ try {
optionsCount++;
var thisId = jQuery('#fb-field-id').val();
var thisType = jQuery('#fb-new-type').val();
@@ -157,9 +167,9 @@ FB.ContactForm = function() {
for (i=0; i<optionsCache[id].options.length; i++) {
if (optionsCache[id].options[i] !== undefined) {
if (thisType === "radio") {
- thisOptions = thisOptions + '<div id="fb-radio-' + id + '-' + i + '"><input type="radio" id="fb-field' + id + '" name="radio-' + id + '" /><span>' + optionsCache[id].options[i] + '</span><div class="clear"></div></div>';
+ thisOptions = thisOptions + '<div id="fb-radio-' + id + '-' + i + '"><input type="radio" id="fb-field' + id + '" name="radio-' + id + '" /><span>' + FB.esc_html( optionsCache[id].options[i] ) + '</span><div class="clear"></div></div>';
} else {
- thisOptions = thisOptions + '<option id="fb-' + id + '-' + i + '" value="' + id + '-' + i + '">' + optionsCache[id].options[i] + '</option>';
+ thisOptions = thisOptions + '<option id="fb-' + id + '-' + i + '" value="' + id + '-' + i + '">' + FB.esc_html( optionsCache[id].options[i] ) + '</option>';
}
}
}
@@ -277,9 +287,9 @@ FB.ContactForm = function() {
for (i=0; i<thisOptions.length; i++) {
if (thisOptions[i] !== undefined) {
if (thisType === "radio") {
- jQuery('#fb-new-options').append('<div id="fb-option-box-' + i + '" class="fb-new-fields"><span optionid="' + i + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + i + '" optionid="' + i + '" value="' + fbForm.fields[id].options[i] + '" class="fb-options" /><div>');
+ jQuery('#fb-new-options').append('<div id="fb-option-box-' + i + '" class="fb-new-fields"><span optionid="' + i + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + i + '" optionid="' + i + '" value="' + FB.esc_attr( fbForm.fields[id].options[i] ) + '" class="fb-options" /><div>');
} else {
- jQuery('#fb-new-options').append('<div id="fb-option-box-' + i + '" class="fb-new-fields"><span optionid="' + i + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + i + '" optionid="' + i + '" value="' + fbForm.fields[id].options[i] + '" class="fb-options" /><div>');
+ jQuery('#fb-new-options').append('<div id="fb-option-box-' + i + '" class="fb-new-fields"><span optionid="' + i + '" class="fb-remove-option"></span><label></label><input type="text" id="fb-option' + i + '" optionid="' + i + '" value="' + FB.esc_attr( fbForm.fields[id].options[i] ) + '" class="fb-options" /><div>');
}
}
}
@@ -301,6 +311,8 @@ FB.ContactForm = function() {
fbForm.fields = defaultFields;
} else {
jQuery.each(data.fields, function(index, value) {
+ if ( 1 == value.required )
+ value.required = 'true';
fbForm.fields[index] = value;
});
fbForm.to = data.to;
@@ -373,10 +385,10 @@ FB.ContactForm = function() {
}
}
var regexp = new RegExp("\\[contact-form\\b.*?\\/?\\](?:[\\s\\S]+?\\[\\/contact-form\\])?");
-
+
// Remove new lines that cause BR tags to show up
response = response.replace(/\n/g,' ');
-
+
// Add new shortcode
if (currentCode.match(regexp)) {
if (isVisual) {
@@ -526,11 +538,11 @@ FB.ContactForm = function() {
var isLoaded = thisType;
var thisId = jQuery('#fb-field-id').val();
if (!thisType) { var thisType = jQuery('#fb-new-type').val(); }
- if (!thisLabelText) { var thisLabelText = jQuery('#fb-new-field' + thisId + ' label').html(); }
+ if (!thisLabelText) { var thisLabelText = jQuery('#fb-new-field' + thisId + ' .label-text').html(); }
var isRequired = (thisRequired) ? '<span class="label-required">' + GrunionFB_i18n.requiredLabel + '</span>' : '';
- var thisLabel = '<label fieldid="' + thisId + '" for="fb-field' + thisId + '"><span class="label-text">' + thisLabelText + '</span>' + isRequired + '</label>';
+ var thisLabel = '<label fieldid="' + thisId + '" for="fb-field' + thisId + '"><span class="label-text">' + FB.esc_html( thisLabelText ) + '</span>' + isRequired + '</label>';
var thisRadio = '<input type="radio" name="radio-' + thisId + '" id="fb-field' + thisId + ' "disabled="disabled" />';
- var thisRadioLabel = '<label fieldid="' + thisId + '" for="fb-field' + thisId + '" class="fb-radio-label"><span class="label-text">' + thisLabelText + '</span>' + isRequired + '</label>';
+ var thisRadioLabel = '<label fieldid="' + thisId + '" for="fb-field' + thisId + '" class="fb-radio-label"><span class="label-text">' + FB.esc_html( thisLabelText ) + '</span>' + isRequired + '</label>';
var thisRadioRemove = '<div class="fb-remove fb-remove-small" id="' + thisId + '"></div>';
var thisRemove = '<div class="fb-remove" id="' + thisId + '"></div>';
var thisCheckbox = '<input type="checkbox" id="fb-field' + thisId + '" "disabled="disabled" />';
@@ -545,11 +557,11 @@ FB.ContactForm = function() {
break;
case "email":
removeOptions();
- jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
+ jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
break;
case "name":
removeOptions();
- jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
+ jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
break;
case "radio":
jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisLabel + thisRadioRemove + '<div fieldid="' + thisId + '" id="fb-custom-radio' + thisId + '"></div>');
@@ -578,7 +590,7 @@ FB.ContactForm = function() {
break;
case "text":
removeOptions();
- jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
+ jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
break;
case "textarea":
removeOptions();
@@ -586,7 +598,7 @@ FB.ContactForm = function() {
break;
case "url":
removeOptions();
- jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
+ jQuery('#fb-new-field' + thisId + ' .fb-fields').html(thisRemove + thisLabel + thisText);
break;
}
// update object
@@ -604,7 +616,7 @@ FB.ContactForm = function() {
var totalWidth = jQuery('body', window.parent.document).width();
var totalHeight = jQuery('body', window.parent.document).height();
var isIE6 = typeof document.body.style.maxHeight === "undefined";
-
+
jQuery('#TB_window, #TB_iframeContent', window.parent.document).css('width', '768px');
jQuery('#TB_window', window.parent.document).css({ left: (totalWidth-768)/2 + 'px', top: '23px', position: 'absolute', marginLeft: '0' });
if ( ! isIE6 ) { // take away IE6
@@ -632,7 +644,7 @@ FB.ContactForm = function() {
post_id: postId,
content: contentSource
};
-
+
jQuery.post(ajaxurl, data, function(response) {
// Setup fbForm
parseShortcode(jQuery.parseJSON(response));
diff --git a/plugins/jetpack/modules/custom-css.php b/plugins/jetpack/modules/custom-css.php
new file mode 100644
index 00000000..2b5e6a34
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * Module Name: Custom CSS
+ * Module Description: Customize the appearance of your site using CSS but without modifying your theme.
+ * Sort Order: 11
+ * First Introduced: 1.7
+ */
+
+function jetpack_load_custom_css() {
+ include dirname( __FILE__ ) . "/custom-css/custom-css.php";
+}
+
+add_action( 'jetpack_modules_loaded', 'custom_css_loaded' );
+
+function custom_css_loaded() {
+ Jetpack::enable_module_configurable( __FILE__ );
+ Jetpack::module_configuration_load( __FILE__, 'custom_css_configuration_load' );
+}
+
+function custom_css_configuration_load() {
+ wp_safe_redirect( admin_url( 'themes.php?page=editcss#settingsdiv' ) );
+ exit;
+}
+
+jetpack_load_custom_css(); \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php
new file mode 100644
index 00000000..f458a46e
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php
@@ -0,0 +1,1241 @@
+<?php
+
+/**
+ * CSSTidy - CSS Parser and Optimiser
+ *
+ * CSS Parser class
+ *
+ * Copyright 2005, 2006, 2007 Florian Schmitz
+ *
+ * This file is part of CSSTidy.
+ *
+ * CSSTidy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * CSSTidy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
+ * @package csstidy
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2007
+ * @author Brett Zamir (brettz9 at yahoo dot com) 2007
+ * @author Nikolay Matsievsky (speed at webo dot name) 2009-2010
+ * @author Cedric Morin (cedric at yterium dot com) 2010
+ */
+/**
+ * Defines ctype functions if required
+ *
+ * @version 1.0
+ */
+require_once('class.csstidy_ctype.php');
+
+/**
+ * Various CSS data needed for correct optimisations etc.
+ *
+ * @version 1.3
+ */
+require('data.inc.php');
+
+/**
+ * Contains a class for printing CSS code
+ *
+ * @version 1.0
+ */
+require('class.csstidy_print.php');
+
+/**
+ * Contains a class for optimising CSS code
+ *
+ * @version 1.0
+ */
+require('class.csstidy_optimise.php');
+
+/**
+ * CSS Parser class
+ *
+
+ * This class represents a CSS parser which reads CSS code and saves it in an array.
+ * In opposite to most other CSS parsers, it does not use regular expressions and
+ * thus has full CSS2 support and a higher reliability.
+ * Additional to that it applies some optimisations and fixes to the CSS code.
+ * An online version should be available here: http://cdburnerxp.se/cssparse/css_optimiser.php
+ * @package csstidy
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
+ * @version 1.3.1
+ */
+class csstidy {
+
+ /**
+ * Saves the parsed CSS. This array is empty if preserve_css is on.
+ * @var array
+ * @access public
+ */
+ var $css = array();
+ /**
+ * Saves the parsed CSS (raw)
+ * @var array
+ * @access private
+ */
+ var $tokens = array();
+ /**
+ * Printer class
+ * @see csstidy_print
+ * @var object
+ * @access public
+ */
+ var $print;
+ /**
+ * Optimiser class
+ * @see csstidy_optimise
+ * @var object
+ * @access private
+ */
+ var $optimise;
+ /**
+ * Saves the CSS charset (@charset)
+ * @var string
+ * @access private
+ */
+ var $charset = '';
+ /**
+ * Saves all @import URLs
+ * @var array
+ * @access private
+ */
+ var $import = array();
+ /**
+ * Saves the namespace
+ * @var string
+ * @access private
+ */
+ var $namespace = '';
+ /**
+ * Contains the version of csstidy
+ * @var string
+ * @access private
+ */
+ var $version = '1.3';
+ /**
+ * Stores the settings
+ * @var array
+ * @access private
+ */
+ var $settings = array();
+ /**
+ * Saves the parser-status.
+ *
+ * Possible values:
+ * - is = in selector
+ * - ip = in property
+ * - iv = in value
+ * - instr = in string (started at " or ' or ( )
+ * - ic = in comment (ignore everything)
+ * - at = in @-block
+ *
+ * @var string
+ * @access private
+ */
+ var $status = 'is';
+ /**
+ * Saves the current at rule (@media)
+ * @var string
+ * @access private
+ */
+ var $at = '';
+ /**
+ * Saves the current selector
+ * @var string
+ * @access private
+ */
+ var $selector = '';
+ /**
+ * Saves the current property
+ * @var string
+ * @access private
+ */
+ var $property = '';
+ /**
+ * Saves the position of , in selectors
+ * @var array
+ * @access private
+ */
+ var $sel_separate = array();
+ /**
+ * Saves the current value
+ * @var string
+ * @access private
+ */
+ var $value = '';
+ /**
+ * Saves the current sub-value
+ *
+ * Example for a subvalue:
+ * background:url(foo.png) red no-repeat;
+ * "url(foo.png)", "red", and "no-repeat" are subvalues,
+ * seperated by whitespace
+ * @var string
+ * @access private
+ */
+ var $sub_value = '';
+ /**
+ * Array which saves all subvalues for a property.
+ * @var array
+ * @see sub_value
+ * @access private
+ */
+ var $sub_value_arr = array();
+ /**
+ * Saves the stack of characters that opened the current strings
+ * @var array
+ * @access private
+ */
+ var $str_char = array();
+ var $cur_string = array();
+ /**
+ * Status from which the parser switched to ic or instr
+ * @var array
+ * @access private
+ */
+ var $from = array();
+ /**
+ /**
+ * =true if in invalid at-rule
+ * @var bool
+ * @access private
+ */
+ var $invalid_at = false;
+ /**
+ * =true if something has been added to the current selector
+ * @var bool
+ * @access private
+ */
+ var $added = false;
+ /**
+ * Array which saves the message log
+ * @var array
+ * @access private
+ */
+ var $log = array();
+ /**
+ * Saves the line number
+ * @var integer
+ * @access private
+ */
+ var $line = 1;
+ /**
+ * Marks if we need to leave quotes for a string
+ * @var array
+ * @access private
+ */
+ var $quoted_string = array();
+
+ /**
+ * List of tokens
+ * @var string
+ */
+ var $tokens_list = "";
+ /**
+ * Loads standard template and sets default settings
+ * @access private
+ * @version 1.3
+ */
+ function csstidy() {
+ $this->settings['remove_bslash'] = true;
+ $this->settings['compress_colors'] = true;
+ $this->settings['compress_font-weight'] = true;
+ $this->settings['lowercase_s'] = false;
+ /*
+ 1 common shorthands optimization
+ 2 + font property optimization
+ 3 + background property optimization
+ */
+ $this->settings['optimise_shorthands'] = 1;
+ $this->settings['remove_last_;'] = true;
+ /* rewrite all properties with low case, better for later gzip OK, safe*/
+ $this->settings['case_properties'] = 1;
+ /* sort properties in alpabetic order, better for later gzip
+ * but can cause trouble in case of overiding same propertie or using hack
+ */
+ $this->settings['sort_properties'] = false;
+ /*
+ 1, 3, 5, etc -- enable sorting selectors inside @media: a{}b{}c{}
+ 2, 5, 8, etc -- enable sorting selectors inside one CSS declaration: a,b,c{}
+ preserve order by default cause it can break functionnality
+ */
+ $this->settings['sort_selectors'] = 0;
+ /* is dangeroues to be used: CSS is broken sometimes */
+ $this->settings['merge_selectors'] = 0;
+ /* preserve or not browser hacks */
+ $this->settings['discard_invalid_selectors'] = false;
+ $this->settings['discard_invalid_properties'] = false;
+ $this->settings['css_level'] = 'CSS2.1';
+ $this->settings['preserve_css'] = false;
+ $this->settings['timestamp'] = false;
+ $this->settings['template'] = ''; // say that propertie exist
+ $this->set_cfg('template','default'); // call load_template
+ $this->optimise = new csstidy_optimise($this);
+
+ $this->tokens_list = & $GLOBALS['csstidy']['tokens'];
+ }
+
+ /**
+ * Get the value of a setting.
+ * @param string $setting
+ * @access public
+ * @return mixed
+ * @version 1.0
+ */
+ function get_cfg($setting) {
+ if (isset($this->settings[$setting])) {
+ return $this->settings[$setting];
+ }
+ return false;
+ }
+
+ /**
+ * Load a template
+ * @param string $template used by set_cfg to load a template via a configuration setting
+ * @access private
+ * @version 1.4
+ */
+ function _load_template($template) {
+ switch ($template) {
+ case 'default':
+ $this->load_template('default');
+ break;
+
+ case 'highest':
+ $this->load_template('highest_compression');
+ break;
+
+ case 'high':
+ $this->load_template('high_compression');
+ break;
+
+ case 'low':
+ $this->load_template('low_compression');
+ break;
+
+ default:
+ $this->load_template($template);
+ break;
+ }
+ }
+
+ /**
+ * Set the value of a setting.
+ * @param string $setting
+ * @param mixed $value
+ * @access public
+ * @return bool
+ * @version 1.0
+ */
+ function set_cfg($setting, $value=null) {
+ if (is_array($setting) && $value === null) {
+ foreach ($setting as $setprop => $setval) {
+ $this->settings[$setprop] = $setval;
+ }
+ if (array_key_exists('template', $setting)) {
+ $this->_load_template($this->settings['template']);
+ }
+ return true;
+ } else if (isset($this->settings[$setting]) && $value !== '') {
+ $this->settings[$setting] = $value;
+ if ($setting === 'template') {
+ $this->_load_template($this->settings['template']);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Adds a token to $this->tokens
+ * @param mixed $type
+ * @param string $data
+ * @param bool $do add a token even if preserve_css is off
+ * @access private
+ * @version 1.0
+ */
+ function _add_token($type, $data, $do = false) {
+ if ($this->get_cfg('preserve_css') || $do) {
+ $this->tokens[] = array($type, ($type == COMMENT) ? $data : trim($data));
+ }
+ }
+
+ /**
+ * Add a message to the message log
+ * @param string $message
+ * @param string $type
+ * @param integer $line
+ * @access private
+ * @version 1.0
+ */
+ function log($message, $type, $line = -1) {
+ if ($line === -1) {
+ $line = $this->line;
+ }
+ $line = intval($line);
+ $add = array('m' => $message, 't' => $type);
+ if (!isset($this->log[$line]) || !in_array($add, $this->log[$line])) {
+ $this->log[$line][] = $add;
+ }
+ }
+
+ /**
+ * Parse unicode notations and find a replacement character
+ * @param string $string
+ * @param integer $i
+ * @access private
+ * @return string
+ * @version 1.2
+ */
+ function _unicode(&$string, &$i) {
+ ++$i;
+ $add = '';
+ $replaced = false;
+
+ while ($i < strlen($string) && (ctype_xdigit($string{$i}) || ctype_space($string{$i})) && strlen($add) < 6) {
+ $add .= $string{$i};
+
+ if (ctype_space($string{$i})) {
+ break;
+ }
+ $i++;
+ }
+
+ if (hexdec($add) > 47 && hexdec($add) < 58 || hexdec($add) > 64 && hexdec($add) < 91 || hexdec($add) > 96 && hexdec($add) < 123) {
+ $this->log('Replaced unicode notation: Changed \\' . $add . ' to ' . chr(hexdec($add)), 'Information');
+ $add = chr(hexdec($add));
+ $replaced = true;
+ } else {
+ $add = trim('\\' . $add);
+ }
+
+ if (@ctype_xdigit($string{$i + 1}) && ctype_space($string{$i})
+ && !$replaced || !ctype_space($string{$i})) {
+ $i--;
+ }
+
+ if ($add !== '\\' || !$this->get_cfg('remove_bslash') || strpos($this->tokens_list, $string{$i + 1}) !== false) {
+ return $add;
+ }
+
+ if ($add === '\\') {
+ $this->log('Removed unnecessary backslash', 'Information');
+ }
+ return '';
+ }
+
+ /**
+ * Write formatted output to a file
+ * @param string $filename
+ * @param string $doctype when printing formatted, is a shorthand for the document type
+ * @param bool $externalcss when printing formatted, indicates whether styles to be attached internally or as an external stylesheet
+ * @param string $title when printing formatted, is the title to be added in the head of the document
+ * @param string $lang when printing formatted, gives a two-letter language code to be added to the output
+ * @access public
+ * @version 1.4
+ */
+ function write_page($filename, $doctype='xhtml1.1', $externalcss=true, $title='', $lang='en') {
+ $this->write($filename, true);
+ }
+
+ /**
+ * Write plain output to a file
+ * @param string $filename
+ * @param bool $formatted whether to print formatted or not
+ * @param string $doctype when printing formatted, is a shorthand for the document type
+ * @param bool $externalcss when printing formatted, indicates whether styles to be attached internally or as an external stylesheet
+ * @param string $title when printing formatted, is the title to be added in the head of the document
+ * @param string $lang when printing formatted, gives a two-letter language code to be added to the output
+ * @param bool $pre_code whether to add pre and code tags around the code (for light HTML formatted templates)
+ * @access public
+ * @version 1.4
+ */
+ function write($filename, $formatted=false, $doctype='xhtml1.1', $externalcss=true, $title='', $lang='en', $pre_code=true) {
+ $filename .= ( $formatted) ? '.xhtml' : '.css';
+
+ if (!is_dir('temp')) {
+ $madedir = mkdir('temp');
+ if (!$madedir) {
+ print 'Could not make directory "temp" in ' . dirname(__FILE__);
+ exit;
+ }
+ }
+ $handle = fopen('temp/' . $filename, 'w');
+ if ($handle) {
+ if (!$formatted) {
+ fwrite($handle, $this->print->plain());
+ } else {
+ fwrite($handle, $this->print->formatted_page($doctype, $externalcss, $title, $lang, $pre_code));
+ }
+ }
+ fclose($handle);
+ }
+
+ /**
+ * Loads a new template
+ * @param string $content either filename (if $from_file == true), content of a template file, "high_compression", "highest_compression", "low_compression", or "default"
+ * @param bool $from_file uses $content as filename if true
+ * @access public
+ * @version 1.1
+ * @see http://csstidy.sourceforge.net/templates.php
+ */
+ function load_template($content, $from_file=true) {
+ $predefined_templates = & $GLOBALS['csstidy']['predefined_templates'];
+ if ($content === 'high_compression' || $content === 'default' || $content === 'highest_compression' || $content === 'low_compression') {
+ $this->template = $predefined_templates[$content];
+ return;
+ }
+
+
+ if ($from_file) {
+ $content = strip_tags(file_get_contents($content), '<span>');
+ }
+ $content = str_replace("\r\n", "\n", $content); // Unify newlines (because the output also only uses \n)
+ $template = explode('|', $content);
+
+ for ($i = 0; $i < count($template); $i++) {
+ $this->template[$i] = $template[$i];
+ }
+ }
+
+ /**
+ * Starts parsing from URL
+ * @param string $url
+ * @access public
+ * @version 1.0
+ */
+ function parse_from_url($url) {
+ return $this->parse(@file_get_contents($url));
+ }
+
+ /**
+ * Checks if there is a token at the current position
+ * @param string $string
+ * @param integer $i
+ * @access public
+ * @version 1.11
+ */
+ function is_token(&$string, $i) {
+ return (strpos($this->tokens_list, $string{$i}) !== false && !csstidy::escaped($string, $i));
+ }
+
+ /**
+ * Parses CSS in $string. The code is saved as array in $this->css
+ * @param string $string the CSS code
+ * @access public
+ * @return bool
+ * @version 1.1
+ */
+ function parse($string) {
+ // Temporarily set locale to en_US in order to handle floats properly
+ $old = @setlocale(LC_ALL, 0);
+ @setlocale(LC_ALL, 'C');
+
+ // PHP bug? Settings need to be refreshed in PHP4
+ $this->print = new csstidy_print($this);
+ //$this->optimise = new csstidy_optimise($this);
+
+ $all_properties = & $GLOBALS['csstidy']['all_properties'];
+ $at_rules = & $GLOBALS['csstidy']['at_rules'];
+ $quoted_string_properties = & $GLOBALS['csstidy']['quoted_string_properties'];
+
+ $this->css = array();
+ $this->print->input_css = $string;
+ $string = str_replace("\r\n", "\n", $string) . ' ';
+ $cur_comment = '';
+
+ for ($i = 0, $size = strlen($string); $i < $size; $i++) {
+ if ($string{$i} === "\n" || $string{$i} === "\r") {
+ ++$this->line;
+ }
+
+ switch ($this->status) {
+ /* Case in at-block */
+ case 'at':
+ if (csstidy::is_token($string, $i)) {
+ if ($string{$i} === '/' && @$string{$i + 1} === '*') {
+ $this->status = 'ic';
+ ++$i;
+ $this->from[] = 'at';
+ } elseif ($string{$i} === '{') {
+ $this->status = 'is';
+ $this->at = $this->css_new_media_section($this->at);
+ $this->_add_token(AT_START, $this->at);
+ } elseif ($string{$i} === ',') {
+ $this->at = trim($this->at) . ',';
+ } elseif ($string{$i} === '\\') {
+ $this->at .= $this->_unicode($string, $i);
+ }
+ // fix for complicated media, i.e @media screen and (-webkit-min-device-pixel-ratio:1.5)
+ // '/' is included for ratios in Opera: (-o-min-device-pixel-ratio: 3/2)
+ elseif (in_array($string{$i}, array('(', ')', ':', '.', '/'))) {
+ $this->at .= $string{$i};
+ }
+ } else {
+ $lastpos = strlen($this->at) - 1;
+ if (!( (ctype_space($this->at{$lastpos}) || csstidy::is_token($this->at, $lastpos) && $this->at{$lastpos} === ',') && ctype_space($string{$i}))) {
+ $this->at .= $string{$i};
+ }
+ }
+ break;
+
+ /* Case in-selector */
+ case 'is':
+ if (csstidy::is_token($string, $i)) {
+ if ($string{$i} === '/' && @$string{$i + 1} === '*' && trim($this->selector) == '') {
+ $this->status = 'ic';
+ ++$i;
+ $this->from[] = 'is';
+ } elseif ($string{$i} === '@' && trim($this->selector) == '') {
+ // Check for at-rule
+ $this->invalid_at = true;
+ foreach ($at_rules as $name => $type) {
+ if (!strcasecmp(substr($string, $i + 1, strlen($name)), $name)) {
+ ($type === 'at') ? $this->at = '@' . $name : $this->selector = '@' . $name;
+ $this->status = $type;
+ $i += strlen($name);
+ $this->invalid_at = false;
+ }
+ }
+
+ if ($this->invalid_at) {
+ $this->selector = '@';
+ $invalid_at_name = '';
+ for ($j = $i + 1; $j < $size; ++$j) {
+ if (!ctype_alpha($string{$j})) {
+ break;
+ }
+ $invalid_at_name .= $string{$j};
+ }
+ $this->log('Invalid @-rule: ' . $invalid_at_name . ' (removed)', 'Warning');
+ }
+ } elseif (($string{$i} === '"' || $string{$i} === "'")) {
+ $this->cur_string[] = $string{$i};
+ $this->status = 'instr';
+ $this->str_char[] = $string{$i};
+ $this->from[] = 'is';
+ /* fixing CSS3 attribute selectors, i.e. a[href$=".mp3" */
+ $this->quoted_string[] = ($string{$i - 1} == '=' );
+ } elseif ($this->invalid_at && $string{$i} === ';') {
+ $this->invalid_at = false;
+ $this->status = 'is';
+ } elseif ($string{$i} === '{') {
+ $this->status = 'ip';
+ if($this->at == '') {
+ $this->at = $this->css_new_media_section(DEFAULT_AT);
+ }
+ $this->selector = $this->css_new_selector($this->at,$this->selector);
+ $this->_add_token(SEL_START, $this->selector);
+ $this->added = false;
+ } elseif ($string{$i} === '}') {
+ $this->_add_token(AT_END, $this->at);
+ $this->at = '';
+ $this->selector = '';
+ $this->sel_separate = array();
+ } elseif ($string{$i} === ',') {
+ $this->selector = trim($this->selector) . ',';
+ $this->sel_separate[] = strlen($this->selector);
+ } elseif ($string{$i} === '\\') {
+ $this->selector .= $this->_unicode($string, $i);
+ } elseif ($string{$i} === '*' && @in_array($string{$i + 1}, array('.', '#', '[', ':'))) {
+ // remove unnecessary universal selector, FS#147
+ } else {
+ $this->selector .= $string{$i};
+ }
+ } else {
+ $lastpos = strlen($this->selector) - 1;
+ if ($lastpos == -1 || !( (ctype_space($this->selector{$lastpos}) || csstidy::is_token($this->selector, $lastpos) && $this->selector{$lastpos} === ',') && ctype_space($string{$i}))) {
+ $this->selector .= $string{$i};
+ }
+ else if (ctype_space($string{$i}) && $this->get_cfg('preserve_css') && !$this->get_cfg('merge_selectors')) {
+ $this->selector .= $string{$i};
+ }
+ }
+ break;
+
+ /* Case in-property */
+ case 'ip':
+ if (csstidy::is_token($string, $i)) {
+ if (($string{$i} === ':' || $string{$i} === '=') && $this->property != '') {
+ $this->status = 'iv';
+ if (!$this->get_cfg('discard_invalid_properties') || csstidy::property_is_valid($this->property)) {
+ $this->property = $this->css_new_property($this->at,$this->selector,$this->property);
+ $this->_add_token(PROPERTY, $this->property);
+ }
+ } elseif ($string{$i} === '/' && @$string{$i + 1} === '*' && $this->property == '') {
+ $this->status = 'ic';
+ ++$i;
+ $this->from[] = 'ip';
+ } elseif ($string{$i} === '}') {
+ $this->explode_selectors();
+ $this->status = 'is';
+ $this->invalid_at = false;
+ $this->_add_token(SEL_END, $this->selector);
+ $this->selector = '';
+ $this->property = '';
+ } elseif ($string{$i} === ';') {
+ $this->property = '';
+ } elseif ($string{$i} === '\\') {
+ $this->property .= $this->_unicode($string, $i);
+ }
+ // else this is dumb IE a hack, keep it
+ elseif ($this->property=='' AND !ctype_space($string{$i})) {
+ $this->property .= $string{$i};
+ }
+ }
+ elseif (!ctype_space($string{$i})) {
+ $this->property .= $string{$i};
+ }
+ break;
+
+ /* Case in-value */
+ case 'iv':
+ $pn = (($string{$i} === "\n" || $string{$i} === "\r") && $this->property_is_next($string, $i + 1) || $i == strlen($string) - 1);
+ if ((csstidy::is_token($string, $i) || $pn) && (!($string{$i} == ',' && !ctype_space($string{$i+1})))) {
+ if ($string{$i} === '/' && @$string{$i + 1} === '*') {
+ $this->status = 'ic';
+ ++$i;
+ $this->from[] = 'iv';
+ } elseif (($string{$i} === '"' || $string{$i} === "'" || $string{$i} === '(')) {
+ $this->cur_string[] = $string{$i};
+ $this->str_char[] = ($string{$i} === '(') ? ')' : $string{$i};
+ $this->status = 'instr';
+ $this->from[] = 'iv';
+ $this->quoted_string[] = in_array(strtolower($this->property), $quoted_string_properties);
+ } elseif ($string{$i} === ',') {
+ $this->sub_value = trim($this->sub_value) . ',';
+ } elseif ($string{$i} === '\\') {
+ $this->sub_value .= $this->_unicode($string, $i);
+ } elseif ($string{$i} === ';' || $pn) {
+ if ($this->selector{0} === '@' && isset($at_rules[substr($this->selector, 1)]) && $at_rules[substr($this->selector, 1)] === 'iv') {
+ $this->status = 'is';
+
+ switch ($this->selector) {
+ case '@charset':
+ /* Add quotes to charset */
+ $this->sub_value_arr[] = '"' . trim($this->sub_value) . '"';
+ $this->charset = $this->sub_value_arr[0];
+ break;
+ case '@namespace':
+ /* Add quotes to namespace */
+ $this->sub_value_arr[] = '"' . trim($this->sub_value) . '"';
+ $this->namespace = implode(' ', $this->sub_value_arr);
+ break;
+ case '@import':
+ $this->sub_value = trim($this->sub_value);
+
+ if (empty($this->sub_value_arr)) {
+ // Quote URLs in imports only if they're not already inside url() and not already quoted.
+ if (substr($this->sub_value, 0, 4) != 'url(') {
+ if (!($this->sub_value{0} == substr($this->sub_value, -1) && in_array($this->sub_value{0}, array("'", '"')))) {
+ $this->sub_value = '"' . $this->sub_value . '"';
+ }
+ }
+ }
+
+ $this->sub_value_arr[] = $this->sub_value;
+ $this->import[] = implode(' ', $this->sub_value_arr);
+ break;
+ }
+
+ $this->sub_value_arr = array();
+ $this->sub_value = '';
+ $this->selector = '';
+ $this->sel_separate = array();
+ } else {
+ $this->status = 'ip';
+ }
+ } elseif ($string{$i} !== '}') {
+ $this->sub_value .= $string{$i};
+ }
+ if (($string{$i} === '}' || $string{$i} === ';' || $pn) && !empty($this->selector)) {
+ if ($this->at == '') {
+ $this->at = $this->css_new_media_section(DEFAULT_AT);
+ }
+
+ // case settings
+ if ($this->get_cfg('lowercase_s')) {
+ $this->selector = strtolower($this->selector);
+ }
+ $this->property = strtolower($this->property);
+
+ $this->optimise->subvalue();
+ if ($this->sub_value != '') {
+ if (substr($this->sub_value, 0, 6) == 'format') {
+ $format_strings = csstidy::parse_string_list(substr($this->sub_value, 7, -1));
+ if (!$format_strings) {
+ $this->sub_value = "";
+ }
+ else {
+ $this->sub_value = "format(";
+
+ foreach ($format_strings as $format_string) {
+ $this->sub_value .= '"' . str_replace('"', '\\"', $format_string) . '",';
+ }
+
+ $this->sub_value = substr($this->sub_value, 0, -1) . ")";
+ }
+ }
+ if ($this->sub_value != '') {
+ $this->sub_value_arr[] = $this->sub_value;
+ }
+ $this->sub_value = '';
+ }
+
+ $this->value = array_shift($this->sub_value_arr);
+ while(count($this->sub_value_arr)){
+ //$this->value .= (substr($this->value,-1,1)==','?'':' ').array_shift($this->sub_value_arr);
+ $this->value .= ' '.array_shift($this->sub_value_arr);
+ }
+
+ $this->optimise->value();
+
+ $valid = csstidy::property_is_valid($this->property);
+ if ((!$this->invalid_at || $this->get_cfg('preserve_css')) && (!$this->get_cfg('discard_invalid_properties') || $valid)) {
+ $this->css_add_property($this->at, $this->selector, $this->property, $this->value);
+ $this->_add_token(VALUE, $this->value);
+ $this->optimise->shorthands();
+ }
+ if (!$valid) {
+ if ($this->get_cfg('discard_invalid_properties')) {
+ $this->log('Removed invalid property: ' . $this->property, 'Warning');
+ } else {
+ $this->log('Invalid property in ' . strtoupper($this->get_cfg('css_level')) . ': ' . $this->property, 'Warning');
+ }
+ }
+
+ $this->property = '';
+ $this->sub_value_arr = array();
+ $this->value = '';
+ }
+ if ($string{$i} === '}') {
+ $this->explode_selectors();
+ $this->_add_token(SEL_END, $this->selector);
+ $this->status = 'is';
+ $this->invalid_at = false;
+ $this->selector = '';
+ }
+ } elseif (!$pn) {
+ $this->sub_value .= $string{$i};
+
+ if (ctype_space($string{$i}) || $string{$i} == ',') {
+ $this->optimise->subvalue();
+ if ($this->sub_value != '') {
+ $this->sub_value_arr[] = $this->sub_value;
+ $this->sub_value = '';
+ }
+ }
+ }
+ break;
+
+ /* Case in string */
+ case 'instr':
+ $_str_char = $this->str_char[count($this->str_char)-1];
+ $_cur_string = $this->cur_string[count($this->cur_string)-1];
+ $temp_add = $string{$i};
+
+ // Add another string to the stack. Strings can't be nested inside of quotes, only parentheses, but
+ // parentheticals can be nested more than once.
+ if ($_str_char === ")" && ($string{$i} === "(" || $string{$i} === '"' || $string{$i} === '\'') && !csstidy::escaped($string, $i)) {
+ $this->cur_string[] = $string{$i};
+ $this->str_char[] = $string{$i} == "(" ? ")" : $string{$i};
+ $this->from[] = 'instr';
+ $this->quoted_string[] = !($string{$i} === "(");
+ continue;
+ }
+
+ if ($_str_char !== ")" && ($string{$i} === "\n" || $string{$i} === "\r") && !($string{$i - 1} === '\\' && !csstidy::escaped($string, $i - 1))) {
+ $temp_add = "\\A";
+ $this->log('Fixed incorrect newline in string', 'Warning');
+ }
+
+ $_cur_string .= $temp_add;
+
+ if ($string{$i} === $_str_char && !csstidy::escaped($string, $i)) {
+ $_quoted_string = array_pop($this->quoted_string);
+
+ $this->status = array_pop($this->from);
+
+ if (!preg_match('|[' . implode('', $GLOBALS['csstidy']['whitespace']) . ']|uis', $_cur_string) && $this->property !== 'content') {
+ if (!$_quoted_string) {
+ if ($_str_char !== ')') {
+ // Convert properties like
+ // font-family: 'Arial';
+ // to
+ // font-family: Arial;
+ // or
+ // url("abc")
+ // to
+ // url(abc)
+ $_cur_string = substr($_cur_string, 1, -1);
+ }
+ } else {
+ $_quoted_string = false;
+ }
+ }
+
+ array_pop($this->cur_string);
+ array_pop($this->str_char);
+
+ if ($_str_char === ")") {
+ $_cur_string = "(" . trim(substr($_cur_string, 1, -1)) . ")";
+ }
+
+ if ($this->status === 'iv') {
+ if (!$_quoted_string){
+ if (strpos($_cur_string,',')!==false)
+ // we can on only remove space next to ','
+ $_cur_string = implode(',',array_map('trim',explode(',',$_cur_string)));
+ // and multiple spaces (too expensive)
+ if (strpos($_cur_string,' ')!==false)
+ $_cur_string = preg_replace(",\s+,"," ",$_cur_string);
+ }
+ $this->sub_value .= $_cur_string;
+ } elseif ($this->status === 'is') {
+ $this->selector .= $_cur_string;
+ } elseif ($this->status === 'instr') {
+ $this->cur_string[count($this->cur_string)-1] .= $_cur_string;
+ }
+ }
+ else {
+ $this->cur_string[count($this->cur_string)-1] = $_cur_string;
+ }
+ break;
+
+ /* Case in-comment */
+ case 'ic':
+ if ($string{$i} === '*' && $string{$i + 1} === '/') {
+ $this->status = array_pop($this->from);
+ $i++;
+ $this->_add_token(COMMENT, $cur_comment);
+ $cur_comment = '';
+ } else {
+ $cur_comment .= $string{$i};
+ }
+ break;
+ }
+ }
+
+ $this->optimise->postparse();
+
+ $this->print->_reset();
+
+ @setlocale(LC_ALL, $old); // Set locale back to original setting
+
+ return!(empty($this->css) && empty($this->import) && empty($this->charset) && empty($this->tokens) && empty($this->namespace));
+ }
+
+ /**
+ * Explodes selectors
+ * @access private
+ * @version 1.0
+ */
+ function explode_selectors() {
+ // Explode multiple selectors
+ if ($this->get_cfg('merge_selectors') === 1) {
+ $new_sels = array();
+ $lastpos = 0;
+ $this->sel_separate[] = strlen($this->selector);
+ foreach ($this->sel_separate as $num => $pos) {
+ if ($num == count($this->sel_separate) - 1) {
+ $pos += 1;
+ }
+
+ $new_sels[] = substr($this->selector, $lastpos, $pos - $lastpos - 1);
+ $lastpos = $pos;
+ }
+
+ if (count($new_sels) > 1) {
+ foreach ($new_sels as $selector) {
+ if (isset($this->css[$this->at][$this->selector])) {
+ $this->merge_css_blocks($this->at, $selector, $this->css[$this->at][$this->selector]);
+ }
+ }
+ unset($this->css[$this->at][$this->selector]);
+ }
+ }
+ $this->sel_separate = array();
+ }
+
+ /**
+ * Checks if a character is escaped (and returns true if it is)
+ * @param string $string
+ * @param integer $pos
+ * @access public
+ * @return bool
+ * @version 1.02
+ */
+ static function escaped(&$string, $pos) {
+ return!(@($string{$pos - 1} !== '\\') || csstidy::escaped($string, $pos - 1));
+ }
+
+ /**
+ * Adds a property with value to the existing CSS code
+ * @param string $media
+ * @param string $selector
+ * @param string $property
+ * @param string $new_val
+ * @access private
+ * @version 1.2
+ */
+ function css_add_property($media, $selector, $property, $new_val) {
+ if ($this->get_cfg('preserve_css') || trim($new_val) == '') {
+ return;
+ }
+
+ $this->added = true;
+ if (isset($this->css[$media][$selector][$property])) {
+ if ((csstidy::is_important($this->css[$media][$selector][$property]) && csstidy::is_important($new_val)) || !csstidy::is_important($this->css[$media][$selector][$property])) {
+ $this->css[$media][$selector][$property] = trim($new_val);
+ }
+ } else {
+ $this->css[$media][$selector][$property] = trim($new_val);
+ }
+ }
+
+ /**
+ * Start a new media section.
+ * Check if the media is not already known,
+ * else rename it with extra spaces
+ * to avoid merging
+ *
+ * @param string $media
+ * @return string
+ */
+ function css_new_media_section($media){
+ if($this->get_cfg('preserve_css')) {
+ return $media;
+ }
+
+ // if the last @media is the same as this
+ // keep it
+ if (!$this->css OR !is_array($this->css) OR empty($this->css)){
+ return $media;
+ }
+ end($this->css);
+ list($at,) = each($this->css);
+ if ($at == $media){
+ return $media;
+ }
+ while (isset($this->css[$media]))
+ if (is_numeric($media))
+ $media++;
+ else
+ $media .= " ";
+ return $media;
+ }
+
+ /**
+ * Start a new selector.
+ * If already referenced in this media section,
+ * rename it with extra space to avoid merging
+ * except if merging is required,
+ * or last selector is the same (merge siblings)
+ *
+ * never merge @font-face
+ *
+ * @param string $media
+ * @param string $selector
+ * @return string
+ */
+ function css_new_selector($media,$selector){
+ if($this->get_cfg('preserve_css')) {
+ return $selector;
+ }
+ $selector = trim($selector);
+ if (strncmp($selector,"@font-face",10)!=0){
+ if ($this->settings['merge_selectors'] != false)
+ return $selector;
+
+ if (!$this->css OR !isset($this->css[$media]) OR !$this->css[$media])
+ return $selector;
+
+ // if last is the same, keep it
+ end($this->css[$media]);
+ list($sel,) = each($this->css[$media]);
+ if ($sel == $selector){
+ return $selector;
+ }
+ }
+
+ while (isset($this->css[$media][$selector]))
+ $selector .= " ";
+ return $selector;
+ }
+
+ /**
+ * Start a new propertie.
+ * If already references in this selector,
+ * rename it with extra space to avoid override
+ *
+ * @param string $media
+ * @param string $selector
+ * @param string $property
+ * @return string
+ */
+ function css_new_property($media, $selector, $property){
+ if($this->get_cfg('preserve_css')) {
+ return $property;
+ }
+ if (!$this->css OR !isset($this->css[$media][$selector]) OR !$this->css[$media][$selector])
+ return $property;
+
+ while (isset($this->css[$media][$selector][$property]))
+ $property .= " ";
+
+ return $property;
+ }
+
+ /**
+ * Adds CSS to an existing media/selector
+ * @param string $media
+ * @param string $selector
+ * @param array $css_add
+ * @access private
+ * @version 1.1
+ */
+ function merge_css_blocks($media, $selector, $css_add) {
+ foreach ($css_add as $property => $value) {
+ $this->css_add_property($media, $selector, $property, $value, false);
+ }
+ }
+
+ /**
+ * Checks if $value is !important.
+ * @param string $value
+ * @return bool
+ * @access public
+ * @version 1.0
+ */
+ static function is_important(&$value) {
+ return (!strcasecmp(substr(str_replace($GLOBALS['csstidy']['whitespace'], '', $value), -10, 10), '!important'));
+ }
+
+ /**
+ * Returns a value without !important
+ * @param string $value
+ * @return string
+ * @access public
+ * @version 1.0
+ */
+ static function gvw_important($value) {
+ if (csstidy::is_important($value)) {
+ $value = trim($value);
+ $value = substr($value, 0, -9);
+ $value = trim($value);
+ $value = substr($value, 0, -1);
+ $value = trim($value);
+ return $value;
+ }
+ return $value;
+ }
+
+ /**
+ * Checks if the next word in a string from pos is a CSS property
+ * @param string $istring
+ * @param integer $pos
+ * @return bool
+ * @access private
+ * @version 1.2
+ */
+ function property_is_next($istring, $pos) {
+ $all_properties = & $GLOBALS['csstidy']['all_properties'];
+ $istring = substr($istring, $pos, strlen($istring) - $pos);
+ $pos = strpos($istring, ':');
+ if ($pos === false) {
+ return false;
+ }
+ $istring = strtolower(trim(substr($istring, 0, $pos)));
+ if (isset($all_properties[$istring])) {
+ $this->log('Added semicolon to the end of declaration', 'Warning');
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if a property is valid
+ * @param string $property
+ * @return bool;
+ * @access public
+ * @version 1.0
+ */
+ function property_is_valid($property) {
+ if (in_array(trim($property), $GLOBALS['csstidy']['multiple_properties'])) $property = trim($property);
+ $all_properties = & $GLOBALS['csstidy']['all_properties'];
+ return (isset($all_properties[$property]) && strpos($all_properties[$property], strtoupper($this->get_cfg('css_level'))) !== false );
+ }
+
+ /**
+ * Accepts a list of strings (e.g., the argument to format() in a @font-face src property)
+ * and returns a list of the strings. Converts things like:
+ *
+ * format(abc) => format("abc")
+ * format(abc def) => format("abc","def")
+ * format(abc "def") => format("abc","def")
+ * format(abc, def, ghi) => format("abc","def","ghi")
+ * format("abc",'def') => format("abc","def")
+ * format("abc, def, ghi") => format("abc, def, ghi")
+ *
+ * @param string
+ * @return array
+ */
+
+ function parse_string_list($value) {
+ $value = trim($value);
+
+ // Case: empty
+ if (!$value) return array();
+
+ $strings = array();
+
+ $in_str = false;
+ $current_string = "";
+
+ for ($i = 0, $_len = strlen($value); $i < $_len; $i++) {
+ if (($value{$i} == "," || $value{$i} === " ") && $in_str === true) {
+ $in_str = false;
+ $strings[] = $current_string;
+ $current_string = "";
+ }
+ else if ($value{$i} == '"' || $value{$i} == "'"){
+ if ($in_str === $value{$i}) {
+ $strings[] = $current_string;
+ $in_str = false;
+ $current_string = "";
+ continue;
+ }
+ else if (!$in_str) {
+ $in_str = $value{$i};
+ }
+ }
+ else {
+ if ($in_str){
+ $current_string .= $value{$i};
+ }
+ else {
+ if (!preg_match("/[\s,]/", $value{$i})) {
+ $in_str = true;
+ $current_string = $value{$i};
+ }
+ }
+ }
+ }
+
+ if ($current_string) {
+ $strings[] = $current_string;
+ }
+
+ return $strings;
+ }
+}
diff --git a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_ctype.php b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_ctype.php
new file mode 100644
index 00000000..bc5accc5
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_ctype.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * CSSTidy - CSS Parser and Optimiser
+ *
+ * CSS ctype functions
+ * Defines some functions that can be not defined.
+ *
+ * This file is part of CSSTidy.
+ *
+ * CSSTidy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CSSTidy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CSSTidy; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
+ * @package csstidy
+ * @author Nikolay Matsievsky (speed at webo dot name) 2009-2010
+ * @version 1.0
+ */
+/* ctype_space Check for whitespace character(s) */
+if (!function_exists('ctype_space')) {
+
+ function ctype_space($text) {
+ return!preg_match("/[^\s\r\n\t\f]/", $text);
+ }
+
+}
+/* ctype_alpha Check for alphabetic character(s) */
+if (!function_exists('ctype_alpha')) {
+
+ function ctype_alpha($text) {
+ return preg_match("/[a-zA-Z]/", $text);
+ }
+
+}
+?> \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_optimise.php b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_optimise.php
new file mode 100644
index 00000000..364573a3
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_optimise.php
@@ -0,0 +1,936 @@
+<?php
+
+/**
+ * CSSTidy - CSS Parser and Optimiser
+ *
+ * CSS Optimising Class
+ * This class optimises CSS data generated by csstidy.
+ *
+ * Copyright 2005, 2006, 2007 Florian Schmitz
+ *
+ * This file is part of CSSTidy.
+ *
+ * CSSTidy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * CSSTidy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
+ * @package csstidy
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2007
+ * @author Brett Zamir (brettz9 at yahoo dot com) 2007
+ * @author Nikolay Matsievsky (speed at webo dot name) 2009-2010
+ */
+
+/**
+ * CSS Optimising Class
+ *
+ * This class optimises CSS data generated by csstidy.
+ *
+ * @package csstidy
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
+ * @version 1.0
+ */
+class csstidy_optimise {
+
+ /**
+ * Constructor
+ * @param array $css contains the class csstidy
+ * @access private
+ * @version 1.0
+ */
+ function csstidy_optimise(&$css) {
+ $this->parser = & $css;
+ $this->css = & $css->css;
+ $this->sub_value = & $css->sub_value;
+ $this->at = & $css->at;
+ $this->selector = & $css->selector;
+ $this->property = & $css->property;
+ $this->value = & $css->value;
+ }
+
+ /**
+ * Optimises $css after parsing
+ * @access public
+ * @version 1.0
+ */
+ function postparse() {
+ if ($this->parser->get_cfg('preserve_css')) {
+ return;
+ }
+
+ if ($this->parser->get_cfg('merge_selectors') === 2) {
+ foreach ($this->css as $medium => $value) {
+ $this->merge_selectors($this->css[$medium]);
+ }
+ }
+
+ if ($this->parser->get_cfg('discard_invalid_selectors')) {
+ foreach ($this->css as $medium => $value) {
+ $this->discard_invalid_selectors($this->css[$medium]);
+ }
+ }
+
+ if ($this->parser->get_cfg('optimise_shorthands') > 0) {
+ foreach ($this->css as $medium => $value) {
+ foreach ($value as $selector => $value1) {
+ $this->css[$medium][$selector] = csstidy_optimise::merge_4value_shorthands($this->css[$medium][$selector]);
+
+ if ($this->parser->get_cfg('optimise_shorthands') < 2) {
+ continue;
+ }
+
+ $this->css[$medium][$selector] = csstidy_optimise::merge_font($this->css[$medium][$selector]);
+
+ if ($this->parser->get_cfg('optimise_shorthands') < 3) {
+ continue;
+ }
+
+ $this->css[$medium][$selector] = csstidy_optimise::merge_bg($this->css[$medium][$selector]);
+ if (empty($this->css[$medium][$selector])) {
+ unset($this->css[$medium][$selector]);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Optimises values
+ * @access public
+ * @version 1.0
+ */
+ function value() {
+ $shorthands = & $GLOBALS['csstidy']['shorthands'];
+
+ // optimise shorthand properties
+ if (isset($shorthands[$this->property])) {
+ $temp = csstidy_optimise::shorthand($this->value); // FIXME - move
+ if ($temp != $this->value) {
+ $this->parser->log('Optimised shorthand notation (' . $this->property . '): Changed "' . $this->value . '" to "' . $temp . '"', 'Information');
+ }
+ $this->value = $temp;
+ }
+
+ // Remove whitespace at ! important
+ if ($this->value != $this->compress_important($this->value)) {
+ $this->parser->log('Optimised !important', 'Information');
+ }
+ }
+
+ /**
+ * Optimises shorthands
+ * @access public
+ * @version 1.0
+ */
+ function shorthands() {
+ $shorthands = & $GLOBALS['csstidy']['shorthands'];
+
+ if (!$this->parser->get_cfg('optimise_shorthands') || $this->parser->get_cfg('preserve_css')) {
+ return;
+ }
+
+ if ($this->property === 'font' && $this->parser->get_cfg('optimise_shorthands') > 1) {
+ $this->css[$this->at][$this->selector]['font']='';
+ $this->parser->merge_css_blocks($this->at, $this->selector, csstidy_optimise::dissolve_short_font($this->value));
+ }
+ if ($this->property === 'background' && $this->parser->get_cfg('optimise_shorthands') > 2) {
+ $this->css[$this->at][$this->selector]['background']='';
+ $this->parser->merge_css_blocks($this->at, $this->selector, csstidy_optimise::dissolve_short_bg($this->value));
+ }
+ if (isset($shorthands[$this->property])) {
+ $this->parser->merge_css_blocks($this->at, $this->selector, csstidy_optimise::dissolve_4value_shorthands($this->property, $this->value));
+ if (is_array($shorthands[$this->property])) {
+ $this->css[$this->at][$this->selector][$this->property] = '';
+ }
+ }
+ }
+
+ /**
+ * Optimises a sub-value
+ * @access public
+ * @version 1.0
+ */
+ function subvalue() {
+ $replace_colors = & $GLOBALS['csstidy']['replace_colors'];
+
+ $this->sub_value = trim($this->sub_value);
+ if ($this->sub_value == '') { // caution : '0'
+ return;
+ }
+
+ $important = '';
+ if (csstidy::is_important($this->sub_value)) {
+ $important = '!important';
+ }
+ $this->sub_value = csstidy::gvw_important($this->sub_value);
+
+ // Compress font-weight
+ if ($this->property === 'font-weight' && $this->parser->get_cfg('compress_font-weight')) {
+ if ($this->sub_value === 'bold') {
+ $this->sub_value = '700';
+ $this->parser->log('Optimised font-weight: Changed "bold" to "700"', 'Information');
+ } else if ($this->sub_value === 'normal') {
+ $this->sub_value = '400';
+ $this->parser->log('Optimised font-weight: Changed "normal" to "400"', 'Information');
+ }
+ }
+
+ $temp = $this->compress_numbers($this->sub_value);
+ if (strcasecmp($temp, $this->sub_value) !== 0) {
+ if (strlen($temp) > strlen($this->sub_value)) {
+ $this->parser->log('Fixed invalid number: Changed "' . $this->sub_value . '" to "' . $temp . '"', 'Warning');
+ } else {
+ $this->parser->log('Optimised number: Changed "' . $this->sub_value . '" to "' . $temp . '"', 'Information');
+ }
+ $this->sub_value = $temp;
+ }
+ if ($this->parser->get_cfg('compress_colors')) {
+ $temp = $this->cut_color($this->sub_value);
+ if ($temp !== $this->sub_value) {
+ if (isset($replace_colors[$this->sub_value])) {
+ $this->parser->log('Fixed invalid color name: Changed "' . $this->sub_value . '" to "' . $temp . '"', 'Warning');
+ } else {
+ $this->parser->log('Optimised color: Changed "' . $this->sub_value . '" to "' . $temp . '"', 'Information');
+ }
+ $this->sub_value = $temp;
+ }
+ }
+ $this->sub_value .= $important;
+ }
+
+ /**
+ * Compresses shorthand values. Example: margin:1px 1px 1px 1px -> margin:1px
+ * @param string $value
+ * @access public
+ * @return string
+ * @version 1.0
+ */
+ function shorthand($value) {
+ $important = '';
+ if (csstidy::is_important($value)) {
+ $values = csstidy::gvw_important($value);
+ $important = '!important';
+ }
+ else
+ $values = $value;
+
+ $values = explode(' ', $values);
+ switch (count($values)) {
+ case 4:
+ if ($values[0] == $values[1] && $values[0] == $values[2] && $values[0] == $values[3]) {
+ return $values[0] . $important;
+ } elseif ($values[1] == $values[3] && $values[0] == $values[2]) {
+ return $values[0] . ' ' . $values[1] . $important;
+ } elseif ($values[1] == $values[3]) {
+ return $values[0] . ' ' . $values[1] . ' ' . $values[2] . $important;
+ }
+ break;
+
+ case 3:
+ if ($values[0] == $values[1] && $values[0] == $values[2]) {
+ return $values[0] . $important;
+ } elseif ($values[0] == $values[2]) {
+ return $values[0] . ' ' . $values[1] . $important;
+ }
+ break;
+
+ case 2:
+ if ($values[0] == $values[1]) {
+ return $values[0] . $important;
+ }
+ break;
+ }
+
+ return $value;
+ }
+
+ /**
+ * Removes unnecessary whitespace in ! important
+ * @param string $string
+ * @return string
+ * @access public
+ * @version 1.1
+ */
+ function compress_important(&$string) {
+ if (csstidy::is_important($string)) {
+ $string = csstidy::gvw_important($string) . '!important';
+ }
+ return $string;
+ }
+
+ /**
+ * Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces 4 color names by #-values.
+ * @param string $color
+ * @return string
+ * @version 1.1
+ */
+ function cut_color($color) {
+ $replace_colors = & $GLOBALS['csstidy']['replace_colors'];
+
+ // rgb(0,0,0) -> #000000 (or #000 in this case later)
+ if (strtolower(substr($color, 0, 4)) === 'rgb(') {
+ $color_tmp = substr($color, 4, strlen($color) - 5);
+ $color_tmp = explode(',', $color_tmp);
+ for ($i = 0; $i < count($color_tmp); $i++) {
+ $color_tmp[$i] = trim($color_tmp[$i]);
+ if (substr($color_tmp[$i], -1) === '%') {
+ $color_tmp[$i] = round((255 * $color_tmp[$i]) / 100);
+ }
+ if ($color_tmp[$i] > 255)
+ $color_tmp[$i] = 255;
+ }
+ $color = '#';
+ for ($i = 0; $i < 3; $i++) {
+ if ($color_tmp[$i] < 16) {
+ $color .= '0' . dechex($color_tmp[$i]);
+ } else {
+ $color .= dechex($color_tmp[$i]);
+ }
+ }
+ }
+
+ // Fix bad color names
+ if (isset($replace_colors[strtolower($color)])) {
+ $color = $replace_colors[strtolower($color)];
+ }
+
+ // #aabbcc -> #abc
+ if (strlen($color) == 7) {
+ $color_temp = strtolower($color);
+ if ($color_temp{0} === '#' && $color_temp{1} == $color_temp{2} && $color_temp{3} == $color_temp{4} && $color_temp{5} == $color_temp{6}) {
+ $color = '#' . $color{1} . $color{3} . $color{5};
+ }
+ }
+
+ switch (strtolower($color)) {
+ /* color name -> hex code */
+ case 'black': return '#000';
+ case 'fuchsia': return '#f0f';
+ case 'white': return '#fff';
+ case 'yellow': return '#ff0';
+
+ /* hex code -> color name */
+ case '#800000': return 'maroon';
+ case '#ffa500': return 'orange';
+ case '#808000': return 'olive';
+ case '#800080': return 'purple';
+ case '#008000': return 'green';
+ case '#000080': return 'navy';
+ case '#008080': return 'teal';
+ case '#c0c0c0': return 'silver';
+ case '#808080': return 'gray';
+ case '#f00': return 'red';
+ }
+
+ return $color;
+ }
+
+ /**
+ * Compresses numbers (ie. 1.0 becomes 1 or 1.100 becomes 1.1 )
+ * @param string $subvalue
+ * @return string
+ * @version 1.2
+ */
+ function compress_numbers($subvalue) {
+ $unit_values = & $GLOBALS['csstidy']['unit_values'];
+ $color_values = & $GLOBALS['csstidy']['color_values'];
+
+ // for font:1em/1em sans-serif...;
+ if ($this->property === 'font') {
+ $temp = explode('/', $subvalue);
+ } else {
+ $temp = array($subvalue);
+ }
+ for ($l = 0; $l < count($temp); $l++) {
+ // if we are not dealing with a number at this point, do not optimise anything
+ $number = $this->AnalyseCssNumber($temp[$l]);
+ if ($number === false) {
+ return $subvalue;
+ }
+
+ // Fix bad colors
+ if (in_array($this->property, $color_values)) {
+ if (strlen($temp[$l]) == 3 || strlen($temp[$l]) == 6) {
+ $temp[$l] = '#' . $temp[$l];
+ }
+ else {
+ $temp[$l] = "0";
+ }
+ continue;
+ }
+
+ if (abs($number[0]) > 0) {
+ if ($number[1] == '' && in_array($this->property, $unit_values, true)) {
+ $number[1] = 'px';
+ }
+ } else {
+ $number[1] = '';
+ }
+
+ $temp[$l] = $number[0] . $number[1];
+ }
+
+ return ((count($temp) > 1) ? $temp[0] . '/' . $temp[1] : $temp[0]);
+ }
+
+ /**
+ * Checks if a given string is a CSS valid number. If it is,
+ * an array containing the value and unit is returned
+ * @param string $string
+ * @return array ('unit' if unit is found or '' if no unit exists, number value) or false if no number
+ */
+ function AnalyseCssNumber($string) {
+ // most simple checks first
+ if (strlen($string) == 0 || ctype_alpha($string{0})) {
+ return false;
+ }
+
+ $units = & $GLOBALS['csstidy']['units'];
+ $return = array(0, '');
+
+ $return[0] = floatval($string);
+ if (abs($return[0]) > 0 && abs($return[0]) < 1) {
+ if ($return[0] < 0) {
+ $return[0] = '-' . ltrim(substr($return[0], 1), '0');
+ } else {
+ $return[0] = ltrim($return[0], '0');
+ }
+ }
+
+ // Look for unit and split from value if exists
+ foreach ($units as $unit) {
+ $expectUnitAt = strlen($string) - strlen($unit);
+ if (!($unitInString = stristr($string, $unit))) { // mb_strpos() fails with "false"
+ continue;
+ }
+ $actualPosition = strpos($string, $unitInString);
+ if ($expectUnitAt === $actualPosition) {
+ $return[1] = $unit;
+ $string = substr($string, 0, - strlen($unit));
+ break;
+ }
+ }
+ if (!is_numeric($string)) {
+ return false;
+ }
+ return $return;
+ }
+
+ /**
+ * Merges selectors with same properties. Example: a{color:red} b{color:red} -> a,b{color:red}
+ * Very basic and has at least one bug. Hopefully there is a replacement soon.
+ * @param array $array
+ * @return array
+ * @access public
+ * @version 1.2
+ */
+ function merge_selectors(&$array) {
+ $css = $array;
+ foreach ($css as $key => $value) {
+ if (!isset($css[$key])) {
+ continue;
+ }
+ $newsel = '';
+
+ // Check if properties also exist in another selector
+ $keys = array();
+ // PHP bug (?) without $css = $array; here
+ foreach ($css as $selector => $vali) {
+ if ($selector == $key) {
+ continue;
+ }
+
+ if ($css[$key] === $vali) {
+ $keys[] = $selector;
+ }
+ }
+
+ if (!empty($keys)) {
+ $newsel = $key;
+ unset($css[$key]);
+ foreach ($keys as $selector) {
+ unset($css[$selector]);
+ $newsel .= ',' . $selector;
+ }
+ $css[$newsel] = $value;
+ }
+ }
+ $array = $css;
+ }
+
+ /**
+ * Removes invalid selectors and their corresponding rule-sets as
+ * defined by 4.1.7 in REC-CSS2. This is a very rudimentary check
+ * and should be replaced by a full-blown parsing algorithm or
+ * regular expression
+ * @version 1.4
+ */
+ function discard_invalid_selectors(&$array) {
+ $invalid = array('+' => true, '~' => true, ',' => true, '>' => true);
+ foreach ($array as $selector => $decls) {
+ $ok = true;
+ $selectors = array_map('trim', explode(',', $selector));
+ foreach ($selectors as $s) {
+ $simple_selectors = preg_split('/\s*[+>~\s]\s*/', $s);
+ foreach ($simple_selectors as $ss) {
+ if ($ss === '')
+ $ok = false;
+ // could also check $ss for internal structure,
+ // but that probably would be too slow
+ }
+ }
+ if (!$ok)
+ unset($array[$selector]);
+ }
+ }
+
+ /**
+ * Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;...
+ * @param string $property
+ * @param string $value
+ * @return array
+ * @version 1.0
+ * @see merge_4value_shorthands()
+ */
+ function dissolve_4value_shorthands($property, $value) {
+ $shorthands = & $GLOBALS['csstidy']['shorthands'];
+ if (!is_array($shorthands[$property])) {
+ $return[$property] = $value;
+ return $return;
+ }
+
+ $important = '';
+ if (csstidy::is_important($value)) {
+ $value = csstidy::gvw_important($value);
+ $important = '!important';
+ }
+ $values = explode(' ', $value);
+
+
+ $return = array();
+ if (count($values) == 4) {
+ for ($i = 0; $i < 4; $i++) {
+ $return[$shorthands[$property][$i]] = $values[$i] . $important;
+ }
+ } elseif (count($values) == 3) {
+ $return[$shorthands[$property][0]] = $values[0] . $important;
+ $return[$shorthands[$property][1]] = $values[1] . $important;
+ $return[$shorthands[$property][3]] = $values[1] . $important;
+ $return[$shorthands[$property][2]] = $values[2] . $important;
+ } elseif (count($values) == 2) {
+ for ($i = 0; $i < 4; $i++) {
+ $return[$shorthands[$property][$i]] = (($i % 2 != 0)) ? $values[1] . $important : $values[0] . $important;
+ }
+ } else {
+ for ($i = 0; $i < 4; $i++) {
+ $return[$shorthands[$property][$i]] = $values[0] . $important;
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Explodes a string as explode() does, however, not if $sep is escaped or within a string.
+ * @param string $sep seperator
+ * @param string $string
+ * @return array
+ * @version 1.0
+ */
+ function explode_ws($sep, $string) {
+ $status = 'st';
+ $to = '';
+
+ $output = array();
+ $num = 0;
+ for ($i = 0, $len = strlen($string); $i < $len; $i++) {
+ switch ($status) {
+ case 'st':
+ if ($string{$i} == $sep && !csstidy::escaped($string, $i)) {
+ ++$num;
+ } elseif ($string{$i} === '"' || $string{$i} === '\'' || $string{$i} === '(' && !csstidy::escaped($string, $i)) {
+ $status = 'str';
+ $to = ($string{$i} === '(') ? ')' : $string{$i};
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
+ } else {
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
+ }
+ break;
+
+ case 'str':
+ if ($string{$i} == $to && !csstidy::escaped($string, $i)) {
+ $status = 'st';
+ }
+ (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
+ break;
+ }
+ }
+
+ if (isset($output[0])) {
+ return $output;
+ } else {
+ return array($output);
+ }
+ }
+
+ /**
+ * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands()
+ * @param array $array
+ * @return array
+ * @version 1.2
+ * @see dissolve_4value_shorthands()
+ */
+ function merge_4value_shorthands($array) {
+ $return = $array;
+ $shorthands = & $GLOBALS['csstidy']['shorthands'];
+
+ foreach ($shorthands as $key => $value) {
+ if (isset($array[$value[0]]) && isset($array[$value[1]])
+ && isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0) {
+ $return[$key] = '';
+
+ $important = '';
+ for ($i = 0; $i < 4; $i++) {
+ $val = $array[$value[$i]];
+ if (csstidy::is_important($val)) {
+ $important = '!important';
+ $return[$key] .= csstidy::gvw_important($val) . ' ';
+ } else {
+ $return[$key] .= $val . ' ';
+ }
+ unset($return[$value[$i]]);
+ }
+ $return[$key] = csstidy_optimise::shorthand(trim($return[$key] . $important));
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Dissolve background property
+ * @param string $str_value
+ * @return array
+ * @version 1.0
+ * @see merge_bg()
+ * @todo full CSS 3 compliance
+ */
+ function dissolve_short_bg($str_value) {
+ // don't try to explose background gradient !
+ if (stripos($str_value, "gradient(")!==FALSE)
+ return array('background'=>$str_value);
+
+ $background_prop_default = & $GLOBALS['csstidy']['background_prop_default'];
+ $repeat = array('repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'space');
+ $attachment = array('scroll', 'fixed', 'local');
+ $clip = array('border', 'padding');
+ $origin = array('border', 'padding', 'content');
+ $pos = array('top', 'center', 'bottom', 'left', 'right');
+ $important = '';
+ $return = array('background-image' => null, 'background-size' => null, 'background-repeat' => null, 'background-position' => null, 'background-attachment' => null, 'background-clip' => null, 'background-origin' => null, 'background-color' => null);
+
+ if (csstidy::is_important($str_value)) {
+ $important = ' !important';
+ $str_value = csstidy::gvw_important($str_value);
+ }
+
+ $str_value = csstidy_optimise::explode_ws(',', $str_value);
+ for ($i = 0; $i < count($str_value); $i++) {
+ $have['clip'] = false;
+ $have['pos'] = false;
+ $have['color'] = false;
+ $have['bg'] = false;
+
+ if (is_array($str_value[$i])) {
+ $str_value[$i] = $str_value[$i][0];
+ }
+ $str_value[$i] = csstidy_optimise::explode_ws(' ', trim($str_value[$i]));
+
+ for ($j = 0; $j < count($str_value[$i]); $j++) {
+ if ($have['bg'] === false && (substr($str_value[$i][$j], 0, 4) === 'url(' || $str_value[$i][$j] === 'none')) {
+ $return['background-image'] .= $str_value[$i][$j] . ',';
+ $have['bg'] = true;
+ } elseif (in_array($str_value[$i][$j], $repeat, true)) {
+ $return['background-repeat'] .= $str_value[$i][$j] . ',';
+ } elseif (in_array($str_value[$i][$j], $attachment, true)) {
+ $return['background-attachment'] .= $str_value[$i][$j] . ',';
+ } elseif (in_array($str_value[$i][$j], $clip, true) && !$have['clip']) {
+ $return['background-clip'] .= $str_value[$i][$j] . ',';
+ $have['clip'] = true;
+ } elseif (in_array($str_value[$i][$j], $origin, true)) {
+ $return['background-origin'] .= $str_value[$i][$j] . ',';
+ } elseif ($str_value[$i][$j]{0} === '(') {
+ $return['background-size'] .= substr($str_value[$i][$j], 1, -1) . ',';
+ } elseif (in_array($str_value[$i][$j], $pos, true) || is_numeric($str_value[$i][$j]{0}) || $str_value[$i][$j]{0} === null || $str_value[$i][$j]{0} === '-' || $str_value[$i][$j]{0} === '.') {
+ $return['background-position'] .= $str_value[$i][$j];
+ if (!$have['pos'])
+ $return['background-position'] .= ' '; else
+ $return['background-position'].= ',';
+ $have['pos'] = true;
+ }
+ elseif (!$have['color']) {
+ $return['background-color'] .= $str_value[$i][$j] . ',';
+ $have['color'] = true;
+ }
+ }
+ }
+
+ foreach ($background_prop_default as $bg_prop => $default_value) {
+ if ($return[$bg_prop] !== null) {
+ $return[$bg_prop] = substr($return[$bg_prop], 0, -1) . $important;
+ }
+ else
+ $return[$bg_prop] = $default_value . $important;
+ }
+ return $return;
+ }
+
+ /**
+ * Merges all background properties
+ * @param array $input_css
+ * @return array
+ * @version 1.0
+ * @see dissolve_short_bg()
+ * @todo full CSS 3 compliance
+ */
+ function merge_bg($input_css) {
+ $background_prop_default = & $GLOBALS['csstidy']['background_prop_default'];
+ // Max number of background images. CSS3 not yet fully implemented
+ $number_of_values = @max(count(csstidy_optimise::explode_ws(',', $input_css['background-image'])), count(csstidy_optimise::explode_ws(',', $input_css['background-color'])), 1);
+ // Array with background images to check if BG image exists
+ $bg_img_array = @csstidy_optimise::explode_ws(',', csstidy::gvw_important($input_css['background-image']));
+ $new_bg_value = '';
+ $important = '';
+
+ // if background properties is here and not empty, don't try anything
+ if (isset($input_css['background']) AND $input_css['background'])
+ return $input_css;
+
+ for ($i = 0; $i < $number_of_values; $i++) {
+ foreach ($background_prop_default as $bg_property => $default_value) {
+ // Skip if property does not exist
+ if (!isset($input_css[$bg_property])) {
+ continue;
+ }
+
+ $cur_value = $input_css[$bg_property];
+ // skip all optimisation if gradient() somewhere
+ if (stripos($cur_value, "gradient(")!==FALSE)
+ return $input_css;
+
+ // Skip some properties if there is no background image
+ if ((!isset($bg_img_array[$i]) || $bg_img_array[$i] === 'none')
+ && ($bg_property === 'background-size' || $bg_property === 'background-position'
+ || $bg_property === 'background-attachment' || $bg_property === 'background-repeat')) {
+ continue;
+ }
+
+ // Remove !important
+ if (csstidy::is_important($cur_value)) {
+ $important = ' !important';
+ $cur_value = csstidy::gvw_important($cur_value);
+ }
+
+ // Do not add default values
+ if ($cur_value === $default_value) {
+ continue;
+ }
+
+ $temp = csstidy_optimise::explode_ws(',', $cur_value);
+
+ if (isset($temp[$i])) {
+ if ($bg_property === 'background-size') {
+ $new_bg_value .= '(' . $temp[$i] . ') ';
+ } else {
+ $new_bg_value .= $temp[$i] . ' ';
+ }
+ }
+ }
+
+ $new_bg_value = trim($new_bg_value);
+ if ($i != $number_of_values - 1)
+ $new_bg_value .= ',';
+ }
+
+ // Delete all background-properties
+ foreach ($background_prop_default as $bg_property => $default_value) {
+ unset($input_css[$bg_property]);
+ }
+
+ // Add new background property
+ if ($new_bg_value !== '')
+ $input_css['background'] = $new_bg_value . $important;
+ elseif(isset ($input_css['background']))
+ $input_css['background'] = 'none';
+
+ return $input_css;
+ }
+
+ /**
+ * Dissolve font property
+ * @param string $str_value
+ * @return array
+ * @version 1.3
+ * @see merge_font()
+ */
+ function dissolve_short_font($str_value) {
+ $font_prop_default = & $GLOBALS['csstidy']['font_prop_default'];
+ $font_weight = array('normal', 'bold', 'bolder', 'lighter', 100, 200, 300, 400, 500, 600, 700, 800, 900);
+ $font_variant = array('normal', 'small-caps');
+ $font_style = array('normal', 'italic', 'oblique');
+ $important = '';
+ $return = array('font-style' => null, 'font-variant' => null, 'font-weight' => null, 'font-size' => null, 'line-height' => null, 'font-family' => null);
+
+ if (csstidy::is_important($str_value)) {
+ $important = '!important';
+ $str_value = csstidy::gvw_important($str_value);
+ }
+
+ $have['style'] = false;
+ $have['variant'] = false;
+ $have['weight'] = false;
+ $have['size'] = false;
+ // Detects if font-family consists of several words w/o quotes
+ $multiwords = false;
+
+ // Workaround with multiple font-family
+ $str_value = csstidy_optimise::explode_ws(',', trim($str_value));
+
+ $str_value[0] = csstidy_optimise::explode_ws(' ', trim($str_value[0]));
+
+ for ($j = 0; $j < count($str_value[0]); $j++) {
+ if ($have['weight'] === false && in_array($str_value[0][$j], $font_weight)) {
+ $return['font-weight'] = $str_value[0][$j];
+ $have['weight'] = true;
+ } elseif ($have['variant'] === false && in_array($str_value[0][$j], $font_variant)) {
+ $return['font-variant'] = $str_value[0][$j];
+ $have['variant'] = true;
+ } elseif ($have['style'] === false && in_array($str_value[0][$j], $font_style)) {
+ $return['font-style'] = $str_value[0][$j];
+ $have['style'] = true;
+ } elseif ($have['size'] === false && (is_numeric($str_value[0][$j]{0}) || $str_value[0][$j]{0} === null || $str_value[0][$j]{0} === '.')) {
+ $size = csstidy_optimise::explode_ws('/', trim($str_value[0][$j]));
+ $return['font-size'] = $size[0];
+ if (isset($size[1])) {
+ $return['line-height'] = $size[1];
+ } else {
+ $return['line-height'] = ''; // don't add 'normal' !
+ }
+ $have['size'] = true;
+ } else {
+ if (isset($return['font-family'])) {
+ $return['font-family'] .= ' ' . $str_value[0][$j];
+ $multiwords = true;
+ } else {
+ $return['font-family'] = $str_value[0][$j];
+ }
+ }
+ }
+ // add quotes if we have several qords in font-family
+ if ($multiwords !== false) {
+ $return['font-family'] = '"' . $return['font-family'] . '"';
+ }
+ $i = 1;
+ while (isset($str_value[$i])) {
+ $return['font-family'] .= ',' . trim($str_value[$i]);
+ $i++;
+ }
+
+ // Fix for 100 and more font-size
+ if ($have['size'] === false && isset($return['font-weight']) &&
+ is_numeric($return['font-weight']{0})) {
+ $return['font-size'] = $return['font-weight'];
+ unset($return['font-weight']);
+ }
+
+ foreach ($font_prop_default as $font_prop => $default_value) {
+ if ($return[$font_prop] !== null) {
+ $return[$font_prop] = $return[$font_prop] . $important;
+ }
+ else
+ $return[$font_prop] = $default_value . $important;
+ }
+ return $return;
+ }
+
+ /**
+ * Merges all fonts properties
+ * @param array $input_css
+ * @return array
+ * @version 1.3
+ * @see dissolve_short_font()
+ */
+ function merge_font($input_css) {
+ $font_prop_default = & $GLOBALS['csstidy']['font_prop_default'];
+ $new_font_value = '';
+ $important = '';
+ // Skip if not font-family and font-size set
+ if (isset($input_css['font-family']) && isset($input_css['font-size'])) {
+ // fix several words in font-family - add quotes
+ if (isset($input_css['font-family'])) {
+ $families = explode(",", $input_css['font-family']);
+ $result_families = array();
+ foreach ($families as $family) {
+ $family = trim($family);
+ $len = strlen($family);
+ if (strpos($family, " ") &&
+ !(($family{0} == '"' && $family{$len - 1} == '"') ||
+ ($family{0} == "'" && $family{$len - 1} == "'"))) {
+ $family = '"' . $family . '"';
+ }
+ $result_families[] = $family;
+ }
+ $input_css['font-family'] = implode(",", $result_families);
+ }
+ foreach ($font_prop_default as $font_property => $default_value) {
+
+ // Skip if property does not exist
+ if (!isset($input_css[$font_property])) {
+ continue;
+ }
+
+ $cur_value = $input_css[$font_property];
+
+ // Skip if default value is used
+ if ($cur_value === $default_value) {
+ continue;
+ }
+
+ // Remove !important
+ if (csstidy::is_important($cur_value)) {
+ $important = '!important';
+ $cur_value = csstidy::gvw_important($cur_value);
+ }
+
+ $new_font_value .= $cur_value;
+ // Add delimiter
+ $new_font_value .= ( $font_property === 'font-size' &&
+ isset($input_css['line-height'])) ? '/' : ' ';
+ }
+
+ $new_font_value = trim($new_font_value);
+
+ // Delete all font-properties
+ foreach ($font_prop_default as $font_property => $default_value) {
+ if ($font_property!=='font' OR !$new_font_value)
+ unset($input_css[$font_property]);
+ }
+
+ // Add new font property
+ if ($new_font_value !== '') {
+ $input_css['font'] = $new_font_value . $important;
+ }
+ }
+
+ return $input_css;
+ }
+
+}
diff --git a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_print.php b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_print.php
new file mode 100644
index 00000000..00a1956b
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_print.php
@@ -0,0 +1,408 @@
+<?php
+
+/**
+ * CSSTidy - CSS Parser and Optimiser
+ *
+ * CSS Printing class
+ * This class prints CSS data generated by csstidy.
+ *
+ * Copyright 2005, 2006, 2007 Florian Schmitz
+ *
+ * This file is part of CSSTidy.
+ *
+ * CSSTidy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * CSSTidy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
+ * @package csstidy
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2007
+ * @author Brett Zamir (brettz9 at yahoo dot com) 2007
+ * @author Cedric Morin (cedric at yterium dot com) 2010
+ */
+
+/**
+ * CSS Printing class
+ *
+ * This class prints CSS data generated by csstidy.
+ *
+ * @package csstidy
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2006
+ * @version 1.0.1
+ */
+class csstidy_print {
+
+ /**
+ * Saves the input CSS string
+ * @var string
+ * @access private
+ */
+ var $input_css = '';
+ /**
+ * Saves the formatted CSS string
+ * @var string
+ * @access public
+ */
+ var $output_css = '';
+ /**
+ * Saves the formatted CSS string (plain text)
+ * @var string
+ * @access public
+ */
+ var $output_css_plain = '';
+
+ /**
+ * Constructor
+ * @param array $css contains the class csstidy
+ * @access private
+ * @version 1.0
+ */
+ function csstidy_print(&$css) {
+ $this->parser = & $css;
+ $this->css = & $css->css;
+ $this->template = & $css->template;
+ $this->tokens = & $css->tokens;
+ $this->charset = & $css->charset;
+ $this->import = & $css->import;
+ $this->namespace = & $css->namespace;
+ }
+
+ /**
+ * Resets output_css and output_css_plain (new css code)
+ * @access private
+ * @version 1.0
+ */
+ function _reset() {
+ $this->output_css = '';
+ $this->output_css_plain = '';
+ }
+
+ /**
+ * Returns the CSS code as plain text
+ * @param string $default_media default @media to add to selectors without any @media
+ * @return string
+ * @access public
+ * @version 1.0
+ */
+ function plain($default_media='') {
+ $this->_print(true, $default_media);
+ return $this->output_css_plain;
+ }
+
+ /**
+ * Returns the formatted CSS code
+ * @param string $default_media default @media to add to selectors without any @media
+ * @return string
+ * @access public
+ * @version 1.0
+ */
+ function formatted($default_media='') {
+ $this->_print(false, $default_media);
+ return $this->output_css;
+ }
+
+ /**
+ * Returns the formatted CSS code to make a complete webpage
+ * @param string $doctype shorthand for the document type
+ * @param bool $externalcss indicates whether styles to be attached internally or as an external stylesheet
+ * @param string $title title to be added in the head of the document
+ * @param string $lang two-letter language code to be added to the output
+ * @return string
+ * @access public
+ * @version 1.4
+ */
+ function formatted_page($doctype='xhtml1.1', $externalcss=true, $title='', $lang='en') {
+ switch ($doctype) {
+ case 'xhtml1.0strict':
+ $doctype_output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
+ break;
+ case 'xhtml1.1':
+ default:
+ $doctype_output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
+ break;
+ }
+
+ $output = $cssparsed = '';
+ $this->output_css_plain = & $output;
+
+ $output .= $doctype_output . "\n" . '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . $lang . '"';
+ $output .= ( $doctype === 'xhtml1.1') ? '>' : ' lang="' . $lang . '">';
+ $output .= "\n<head>\n <title>$title</title>";
+
+ if ($externalcss) {
+ $output .= "\n <style type=\"text/css\">\n";
+ $cssparsed = file_get_contents('cssparsed.css');
+ $output .= $cssparsed; // Adds an invisible BOM or something, but not in css_optimised.php
+ $output .= "\n</style>";
+ } else {
+ $output .= "\n" . ' <link rel="stylesheet" type="text/css" href="cssparsed.css" />';
+// }
+ }
+ $output .= "\n</head>\n<body><code id=\"copytext\">";
+ $output .= $this->formatted();
+ $output .= '</code>' . "\n" . '</body></html>';
+ return $this->output_css_plain;
+ }
+
+ /**
+ * Returns the formatted CSS Code and saves it into $this->output_css and $this->output_css_plain
+ * @param bool $plain plain text or not
+ * @param string $default_media default @media to add to selectors without any @media
+ * @access private
+ * @version 2.0
+ */
+ function _print($plain = false, $default_media='') {
+ if ($this->output_css && $this->output_css_plain) {
+ return;
+ }
+
+ $output = '';
+ if (!$this->parser->get_cfg('preserve_css')) {
+ $this->_convert_raw_css($default_media);
+ }
+
+ $template = & $this->template;
+
+ if ($plain) {
+ $template = array_map('strip_tags', $template);
+ }
+
+ if ($this->parser->get_cfg('timestamp')) {
+ array_unshift($this->tokens, array(COMMENT, ' CSSTidy ' . $this->parser->version . ': ' . date('r') . ' '));
+ }
+
+ if (!empty($this->charset)) {
+ $output .= $template[0] . '@charset ' . $template[5] . $this->charset . $template[6];
+ }
+
+ if (!empty($this->import)) {
+ for ($i = 0, $size = count($this->import); $i < $size; $i++) {
+ $import_components = explode(' ', $this->import[$i]);
+ if (substr($import_components[0], 0, 4) === 'url(' && substr($import_components[0], -1, 1) === ')') {
+ $import_components[0] = '\'' . trim(substr($import_components[0], 4, -1), "'\"") . '\'';
+ $this->import[$i] = implode(' ', $import_components);
+ $this->parser->log('Optimised @import : Removed "url("', 'Information');
+ }
+ $output .= $template[0] . '@import ' . $template[5] . $this->import[$i] . $template[6];
+ }
+ }
+
+ if (!empty($this->namespace)) {
+ if (substr($this->namespace, 0, 4) === 'url(' && substr($this->namespace, -1, 1) === ')') {
+ $this->namespace = '\'' . substr($this->namespace, 4, -1) . '\'';
+ $this->parser->log('Optimised @namespace : Removed "url("', 'Information');
+ }
+ $output .= $template[0] . '@namespace ' . $template[5] . $this->namespace . $template[6];
+ }
+
+ $output .= $template[13];
+ $in_at_out = '';
+ $out = & $output;
+
+ foreach ($this->tokens as $key => $token) {
+ switch ($token[0]) {
+ case AT_START:
+ $out .= $template[0] . $this->_htmlsp($token[1], $plain) . $template[1];
+ $out = & $in_at_out;
+ break;
+
+ case SEL_START:
+ if ($this->parser->get_cfg('lowercase_s'))
+ $token[1] = strtolower($token[1]);
+ $out .= ( $token[1]{0} !== '@') ? $template[2] . $this->_htmlsp($token[1], $plain) : $template[0] . $this->_htmlsp($token[1], $plain);
+ $out .= $template[3];
+ break;
+
+ case PROPERTY:
+ if ($this->parser->get_cfg('case_properties') === 2) {
+ $token[1] = strtoupper($token[1]);
+ } elseif ($this->parser->get_cfg('case_properties') === 1) {
+ $token[1] = strtolower($token[1]);
+ }
+ $out .= $template[4] . $this->_htmlsp($token[1], $plain) . ':' . $template[5];
+ break;
+
+ case VALUE:
+ $out .= $this->_htmlsp($token[1], $plain);
+ if ($this->_seeknocomment($key, 1) == SEL_END && $this->parser->get_cfg('remove_last_;')) {
+ $out .= str_replace(';', '', $template[6]);
+ } else {
+ $out .= $template[6];
+ }
+ break;
+
+ case SEL_END:
+ $out .= $template[7];
+ if ($this->_seeknocomment($key, 1) != AT_END)
+ $out .= $template[8];
+ break;
+
+ case AT_END:
+ $out = & $output;
+ $out .= $template[10] . str_replace("\n", "\n" . $template[10], $in_at_out);
+ $in_at_out = '';
+ $out .= $template[9];
+ break;
+
+ case COMMENT:
+ $out .= $template[11] . '/*' . $this->_htmlsp($token[1], $plain) . '*/' . $template[12];
+ break;
+ }
+ }
+
+ $output = trim($output);
+
+ if (!$plain) {
+ $this->output_css = $output;
+ $this->_print(true);
+ } else {
+ // If using spaces in the template, don't want these to appear in the plain output
+ $this->output_css_plain = str_replace('&#160;', '', $output);
+ }
+ }
+
+ /**
+ * Gets the next token type which is $move away from $key, excluding comments
+ * @param integer $key current position
+ * @param integer $move move this far
+ * @return mixed a token type
+ * @access private
+ * @version 1.0
+ */
+ function _seeknocomment($key, $move) {
+ $go = ($move > 0) ? 1 : -1;
+ for ($i = $key + 1; abs($key - $i) - 1 < abs($move); $i += $go) {
+ if (!isset($this->tokens[$i])) {
+ return;
+ }
+ if ($this->tokens[$i][0] == COMMENT) {
+ $move += 1;
+ continue;
+ }
+ return $this->tokens[$i][0];
+ }
+ }
+
+ /**
+ * Converts $this->css array to a raw array ($this->tokens)
+ * @param string $default_media default @media to add to selectors without any @media
+ * @access private
+ * @version 1.0
+ */
+ function _convert_raw_css($default_media='') {
+ $this->tokens = array();
+
+ foreach ($this->css as $medium => $val) {
+ if ($this->parser->get_cfg('sort_selectors'))
+ ksort($val);
+ if (intval($medium) < DEFAULT_AT) {
+ $this->parser->_add_token(AT_START, $medium, true);
+ }
+ elseif ($default_media) {
+ $this->parser->_add_token(AT_START, $default_media, true);
+ }
+
+ foreach ($val as $selector => $vali) {
+ if ($this->parser->get_cfg('sort_properties'))
+ ksort($vali);
+ $this->parser->_add_token(SEL_START, $selector, true);
+
+ foreach ($vali as $property => $valj) {
+ $this->parser->_add_token(PROPERTY, $property, true);
+ $this->parser->_add_token(VALUE, $valj, true);
+ }
+
+ $this->parser->_add_token(SEL_END, $selector, true);
+ }
+
+ if (intval($medium) < DEFAULT_AT) {
+ $this->parser->_add_token(AT_END, $medium, true);
+ }
+ elseif ($default_media) {
+ $this->parser->_add_token(AT_END, $default_media, true);
+ }
+ }
+ }
+
+ /**
+ * Same as htmlspecialchars, only that chars are not replaced if $plain !== true. This makes print_code() cleaner.
+ * @param string $string
+ * @param bool $plain
+ * @return string
+ * @see csstidy_print::_print()
+ * @access private
+ * @version 1.0
+ */
+ function _htmlsp($string, $plain) {
+ if (!$plain) {
+ return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
+ }
+ return $string;
+ }
+
+ /**
+ * Get compression ratio
+ * @access public
+ * @return float
+ * @version 1.2
+ */
+ function get_ratio() {
+ if (!$this->output_css_plain) {
+ $this->formatted();
+ }
+ return round((strlen($this->input_css) - strlen($this->output_css_plain)) / strlen($this->input_css), 3) * 100;
+ }
+
+ /**
+ * Get difference between the old and new code in bytes and prints the code if necessary.
+ * @access public
+ * @return string
+ * @version 1.1
+ */
+ function get_diff() {
+ if (!$this->output_css_plain) {
+ $this->formatted();
+ }
+
+ $diff = strlen($this->output_css_plain) - strlen($this->input_css);
+
+ if ($diff > 0) {
+ return '+' . $diff;
+ } elseif ($diff == 0) {
+ return '+-' . $diff;
+ }
+
+ return $diff;
+ }
+
+ /**
+ * Get the size of either input or output CSS in KB
+ * @param string $loc default is "output"
+ * @access public
+ * @return integer
+ * @version 1.0
+ */
+ function size($loc = 'output') {
+ if ($loc === 'output' && !$this->output_css) {
+ $this->formatted();
+ }
+
+ if ($loc === 'input') {
+ return (strlen($this->input_css) / 1000);
+ } else {
+ return (strlen($this->output_css_plain) / 1000);
+ }
+ }
+
+}
diff --git a/plugins/jetpack/modules/custom-css/csstidy/cssparse.css b/plugins/jetpack/modules/custom-css/csstidy/cssparse.css
new file mode 100644
index 00000000..38fc40b4
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/cssparse.css
@@ -0,0 +1,118 @@
+@import url("cssparsed.css");
+
+html, body {
+font:0.8em Verdana,Helvetica,sans-serif;
+background:#F8F8F6;
+}
+
+code {
+font-size:1.2em;
+}
+
+div#rightcol {
+padding-left:32em;
+}
+
+fieldset {
+display:block;
+margin:0.5em 0;
+padding:1em;
+border:solid #7284AB 2px;
+}
+fieldset.code_output {
+display:inline;
+}
+
+h1 {
+font-size:2em;
+}
+
+small {
+font-size:0.7em;
+}
+
+fieldset#field_input {
+float:left;
+margin:0 0.5em 1em 0;
+}
+
+fieldset#options,fieldset#code_layout {
+width:31em;
+}
+
+input#submit {
+clear:both;
+display:block;
+margin:1em;
+}
+
+select {
+margin:2px 0 0;
+}
+
+label.block {
+display:block;
+}
+
+legend {
+background:#c4E1C3;
+padding:2px 4px;
+border:dashed 1px;
+}
+
+textarea#css_text {
+width:27em;
+height:370px;
+display:block;
+margin-right:1em;
+}
+
+.help {
+cursor:help;
+}
+
+p.important {
+border:solid 1px red;
+font-weight:bold;
+padding:1em;
+background:white;
+}
+
+p {
+margin:1em 0;
+}
+
+dl {
+padding-left:0.5em;
+}
+
+dt {
+font-weight:bold;
+margin:0;
+float:left;
+clear:both;
+height:1.5em;
+}
+
+dd {
+margin:0 0 0 4em;
+height:1.5em;
+}
+
+fieldset#messages {
+background:white;
+padding:0 0 0 1em;
+}
+
+fieldset#messages div {
+height:10em;
+overflow:auto;
+}
+
+dd.Warning {
+color:orange;
+}
+
+dd.Information {
+color:green;
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/csstidy/cssparsed.css b/plugins/jetpack/modules/custom-css/csstidy/cssparsed.css
new file mode 100644
index 00000000..5aaf2bb1
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/cssparsed.css
@@ -0,0 +1,29 @@
+code#copytext {
+ white-space: pre;
+ font-family: Verdana;
+}
+
+.at {
+color:darkblue;
+}
+
+.format {
+color:gray;
+}
+
+.property {
+color:green;
+}
+
+.selector {
+color:blue;
+}
+
+.value {
+color:red;
+left: 500px;
+}
+
+.comment {
+color:orange;
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/csstidy/data-wp.inc.php b/plugins/jetpack/modules/custom-css/csstidy/data-wp.inc.php
new file mode 100644
index 00000000..f39ecbf8
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/data-wp.inc.php
@@ -0,0 +1,75 @@
+<?php
+
+unset( $GLOBALS['csstidy']['all_properties']['binding'] );
+
+$GLOBALS['csstidy']['all_properties']['text-size-adjust'] = 'CSS3.0';
+
+// Support browser prefixes for properties only in the latest CSS draft
+foreach ( $GLOBALS['csstidy']['all_properties'] as $property => $levels ) {
+ if ( strpos( $levels, "," ) === false ) {
+ $GLOBALS['csstidy']['all_properties']['-moz-' . $property] = $levels;
+ $GLOBALS['csstidy']['all_properties']['-webkit-' . $property] = $levels;
+ $GLOBALS['csstidy']['all_properties']['-ms-' . $property] = $levels;
+ $GLOBALS['csstidy']['all_properties']['-o-' . $property] = $levels;
+ $GLOBALS['csstidy']['all_properties']['-khtml-' . $property] = $levels;
+
+ if ( in_array( $property, $GLOBALS['csstidy']['unit_values'] ) ) {
+ $GLOBALS['csstidy']['unit_values'][] = '-moz-' . $property;
+ $GLOBALS['csstidy']['unit_values'][] = '-webkit-' . $property;
+ $GLOBALS['csstidy']['unit_values'][] = '-ms-' . $property;
+ $GLOBALS['csstidy']['unit_values'][] = '-o-' . $property;
+ $GLOBALS['csstidy']['unit_values'][] = '-khtml-' . $property;
+ }
+
+ if ( in_array( $property, $GLOBALS['csstidy']['color_values'] ) ) {
+ $GLOBALS['csstidy']['color_values'][] = '-moz-' . $property;
+ $GLOBALS['csstidy']['color_values'][] = '-webkit-' . $property;
+ $GLOBALS['csstidy']['color_values'][] = '-ms-' . $property;
+ $GLOBALS['csstidy']['color_values'][] = '-o-' . $property;
+ $GLOBALS['csstidy']['color_values'][] = '-khtml-' . $property;
+ }
+ }
+}
+
+foreach ( $GLOBALS['csstidy']['multiple_properties'] as $property ) {
+ if ( '-' != $property[0] ) {
+ $GLOBALS['csstidy']['multiple_properties'][] = '-o-' . $property;
+ $GLOBALS['csstidy']['multiple_properties'][] = '-ms-' . $property;
+ $GLOBALS['csstidy']['multiple_properties'][] = '-webkit-' . $property;
+ $GLOBALS['csstidy']['multiple_properties'][] = '-moz-' . $property;
+ $GLOBALS['csstidy']['multiple_properties'][] = '-khtml-' . $property;
+ }
+}
+
+/**
+ * CSS Animation
+ *
+ * @see https://developer.mozilla.org/en/CSS/CSS_animations
+ */
+$GLOBALS['csstidy']['at_rules']['-webkit-keyframes'] = 'at';
+$GLOBALS['csstidy']['at_rules']['-moz-keyframes'] = 'at';
+$GLOBALS['csstidy']['at_rules']['-ms-keyframes'] = 'at';
+
+/**
+ * Non-standard CSS properties. They're not part of any spec, but we say
+ * they're in all of them so that we can support them.
+ */
+$GLOBALS['csstidy']['all_properties']['-webkit-filter'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-moz-filter'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-ms-filter'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['filter'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['scrollbar-face-color'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-ms-interpolation-mode'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-rendering'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-webkit-transform-origin-x'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-webkit-transform-origin-y'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-webkit-transform-origin-z'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-webkit-font-smoothing'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-font-smooth'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-o-object-fit'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['object-fit'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['-o-object-position'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['object-position'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-overflow'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['zoom'] = 'CSS3.0';
+
diff --git a/plugins/jetpack/modules/custom-css/csstidy/data.inc.php b/plugins/jetpack/modules/custom-css/csstidy/data.inc.php
new file mode 100644
index 00000000..c0855681
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/data.inc.php
@@ -0,0 +1,661 @@
+<?php
+/**
+ * Various CSS Data for CSSTidy
+ *
+ * This file is part of CSSTidy.
+ *
+ * CSSTidy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * CSSTidy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CSSTidy; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
+ * @package csstidy
+ * @author Florian Schmitz (floele at gmail dot com) 2005
+ * @author Nikolay Matsievsky (speed at webo dot name) 2010
+ */
+
+define('AT_START', 1);
+define('AT_END', 2);
+define('SEL_START', 3);
+define('SEL_END', 4);
+define('PROPERTY', 5);
+define('VALUE', 6);
+define('COMMENT', 7);
+define('DEFAULT_AT', 41);
+
+/**
+ * All whitespace allowed in CSS
+ *
+ * @global array $GLOBALS['csstidy']['whitespace']
+ * @version 1.0
+ */
+$GLOBALS['csstidy']['whitespace'] = array(' ',"\n","\t","\r","\x0B");
+
+/**
+ * All CSS tokens used by csstidy
+ *
+ * @global string $GLOBALS['csstidy']['tokens']
+ * @version 1.0
+ */
+$GLOBALS['csstidy']['tokens'] = '/@}{;:=\'"(,\\!$%&)*+.<>?[]^`|~';
+
+/**
+ * All CSS units (CSS 3 units included)
+ *
+ * @see compress_numbers()
+ * @global array $GLOBALS['csstidy']['units']
+ * @version 1.0
+ */
+$GLOBALS['csstidy']['units'] = array('in','cm','mm','pt','pc','px','rem','em','%','ex','gd','vw','vh','vm','deg','grad','rad','ms','s','khz','hz');
+
+/**
+ * Available at-rules
+ *
+ * @global array $GLOBALS['csstidy']['at_rules']
+ * @version 1.0
+ */
+$GLOBALS['csstidy']['at_rules'] = array('page' => 'is','font-face' => 'is','charset' => 'iv', 'import' => 'iv','namespace' => 'iv','media' => 'at','keyframes' => 'at');
+
+ /**
+ * Properties that need a value with unit
+ *
+ * @todo CSS3 properties
+ * @see compress_numbers();
+ * @global array $GLOBALS['csstidy']['unit_values']
+ * @version 1.2
+ */
+$GLOBALS['csstidy']['unit_values'] = array ('background', 'background-position', 'background-size', 'border', 'border-top', 'border-right', 'border-bottom', 'border-left', 'border-width',
+ 'border-top-width', 'border-right-width', 'border-left-width', 'border-bottom-width', 'bottom', 'border-spacing', 'column-gap', 'column-width',
+ 'font-size', 'height', 'left', 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 'max-height',
+ 'max-width', 'min-height', 'min-width', 'outline', 'outline-width', 'padding', 'padding-top', 'padding-right',
+ 'padding-bottom', 'padding-left', 'perspective', 'right', 'top', 'text-indent', 'letter-spacing', 'word-spacing', 'width');
+
+/**
+ * Properties that allow <color> as value
+ *
+ * @todo CSS3 properties
+ * @see compress_numbers();
+ * @global array $GLOBALS['csstidy']['color_values']
+ * @version 1.0
+ */
+$GLOBALS['csstidy']['color_values'] = array();
+$GLOBALS['csstidy']['color_values'][] = 'background-color';
+$GLOBALS['csstidy']['color_values'][] = 'border-color';
+$GLOBALS['csstidy']['color_values'][] = 'border-top-color';
+$GLOBALS['csstidy']['color_values'][] = 'border-right-color';
+$GLOBALS['csstidy']['color_values'][] = 'border-bottom-color';
+$GLOBALS['csstidy']['color_values'][] = 'border-left-color';
+$GLOBALS['csstidy']['color_values'][] = 'color';
+$GLOBALS['csstidy']['color_values'][] = 'outline-color';
+$GLOBALS['csstidy']['color_values'][] = 'column-rule-color';
+
+/**
+ * Default values for the background properties
+ *
+ * @todo Possibly property names will change during CSS3 development
+ * @global array $GLOBALS['csstidy']['background_prop_default']
+ * @see dissolve_short_bg()
+ * @see merge_bg()
+ * @version 1.0
+ */
+$GLOBALS['csstidy']['background_prop_default'] = array();
+$GLOBALS['csstidy']['background_prop_default']['background-image'] = 'none';
+$GLOBALS['csstidy']['background_prop_default']['background-size'] = 'auto';
+$GLOBALS['csstidy']['background_prop_default']['background-repeat'] = 'repeat';
+$GLOBALS['csstidy']['background_prop_default']['background-position'] = '0 0';
+$GLOBALS['csstidy']['background_prop_default']['background-attachment'] = 'scroll';
+$GLOBALS['csstidy']['background_prop_default']['background-clip'] = 'border';
+$GLOBALS['csstidy']['background_prop_default']['background-origin'] = 'padding';
+$GLOBALS['csstidy']['background_prop_default']['background-color'] = 'transparent';
+
+/**
+ * Default values for the font properties
+ *
+ * @global array $GLOBALS['csstidy']['font_prop_default']
+ * @see merge_fonts()
+ * @version 1.3
+ */
+$GLOBALS['csstidy']['font_prop_default'] = array();
+$GLOBALS['csstidy']['font_prop_default']['font-style'] = 'normal';
+$GLOBALS['csstidy']['font_prop_default']['font-variant'] = 'normal';
+$GLOBALS['csstidy']['font_prop_default']['font-weight'] = 'normal';
+$GLOBALS['csstidy']['font_prop_default']['font-size'] = '';
+$GLOBALS['csstidy']['font_prop_default']['line-height'] = '';
+$GLOBALS['csstidy']['font_prop_default']['font-family'] = '';
+
+/**
+ * A list of non-W3C color names which get replaced by their hex-codes
+ *
+ * @global array $GLOBALS['csstidy']['replace_colors']
+ * @see cut_color()
+ * @version 1.0
+ */
+$GLOBALS['csstidy']['replace_colors'] = array();
+$GLOBALS['csstidy']['replace_colors']['aliceblue'] = '#f0f8ff';
+$GLOBALS['csstidy']['replace_colors']['antiquewhite'] = '#faebd7';
+$GLOBALS['csstidy']['replace_colors']['aquamarine'] = '#7fffd4';
+$GLOBALS['csstidy']['replace_colors']['azure'] = '#f0ffff';
+$GLOBALS['csstidy']['replace_colors']['beige'] = '#f5f5dc';
+$GLOBALS['csstidy']['replace_colors']['bisque'] = '#ffe4c4';
+$GLOBALS['csstidy']['replace_colors']['blanchedalmond'] = '#ffebcd';
+$GLOBALS['csstidy']['replace_colors']['blueviolet'] = '#8a2be2';
+$GLOBALS['csstidy']['replace_colors']['brown'] = '#a52a2a';
+$GLOBALS['csstidy']['replace_colors']['burlywood'] = '#deb887';
+$GLOBALS['csstidy']['replace_colors']['cadetblue'] = '#5f9ea0';
+$GLOBALS['csstidy']['replace_colors']['chartreuse'] = '#7fff00';
+$GLOBALS['csstidy']['replace_colors']['chocolate'] = '#d2691e';
+$GLOBALS['csstidy']['replace_colors']['coral'] = '#ff7f50';
+$GLOBALS['csstidy']['replace_colors']['cornflowerblue'] = '#6495ed';
+$GLOBALS['csstidy']['replace_colors']['cornsilk'] = '#fff8dc';
+$GLOBALS['csstidy']['replace_colors']['crimson'] = '#dc143c';
+$GLOBALS['csstidy']['replace_colors']['cyan'] = '#00ffff';
+$GLOBALS['csstidy']['replace_colors']['darkblue'] = '#00008b';
+$GLOBALS['csstidy']['replace_colors']['darkcyan'] = '#008b8b';
+$GLOBALS['csstidy']['replace_colors']['darkgoldenrod'] = '#b8860b';
+$GLOBALS['csstidy']['replace_colors']['darkgray'] = '#a9a9a9';
+$GLOBALS['csstidy']['replace_colors']['darkgreen'] = '#006400';
+$GLOBALS['csstidy']['replace_colors']['darkkhaki'] = '#bdb76b';
+$GLOBALS['csstidy']['replace_colors']['darkmagenta'] = '#8b008b';
+$GLOBALS['csstidy']['replace_colors']['darkolivegreen'] = '#556b2f';
+$GLOBALS['csstidy']['replace_colors']['darkorange'] = '#ff8c00';
+$GLOBALS['csstidy']['replace_colors']['darkorchid'] = '#9932cc';
+$GLOBALS['csstidy']['replace_colors']['darkred'] = '#8b0000';
+$GLOBALS['csstidy']['replace_colors']['darksalmon'] = '#e9967a';
+$GLOBALS['csstidy']['replace_colors']['darkseagreen'] = '#8fbc8f';
+$GLOBALS['csstidy']['replace_colors']['darkslateblue'] = '#483d8b';
+$GLOBALS['csstidy']['replace_colors']['darkslategray'] = '#2f4f4f';
+$GLOBALS['csstidy']['replace_colors']['darkturquoise'] = '#00ced1';
+$GLOBALS['csstidy']['replace_colors']['darkviolet'] = '#9400d3';
+$GLOBALS['csstidy']['replace_colors']['deeppink'] = '#ff1493';
+$GLOBALS['csstidy']['replace_colors']['deepskyblue'] = '#00bfff';
+$GLOBALS['csstidy']['replace_colors']['dimgray'] = '#696969';
+$GLOBALS['csstidy']['replace_colors']['dodgerblue'] = '#1e90ff';
+$GLOBALS['csstidy']['replace_colors']['feldspar'] = '#d19275';
+$GLOBALS['csstidy']['replace_colors']['firebrick'] = '#b22222';
+$GLOBALS['csstidy']['replace_colors']['floralwhite'] = '#fffaf0';
+$GLOBALS['csstidy']['replace_colors']['forestgreen'] = '#228b22';
+$GLOBALS['csstidy']['replace_colors']['gainsboro'] = '#dcdcdc';
+$GLOBALS['csstidy']['replace_colors']['ghostwhite'] = '#f8f8ff';
+$GLOBALS['csstidy']['replace_colors']['gold'] = '#ffd700';
+$GLOBALS['csstidy']['replace_colors']['goldenrod'] = '#daa520';
+$GLOBALS['csstidy']['replace_colors']['greenyellow'] = '#adff2f';
+$GLOBALS['csstidy']['replace_colors']['honeydew'] = '#f0fff0';
+$GLOBALS['csstidy']['replace_colors']['hotpink'] = '#ff69b4';
+$GLOBALS['csstidy']['replace_colors']['indianred'] = '#cd5c5c';
+$GLOBALS['csstidy']['replace_colors']['indigo'] = '#4b0082';
+$GLOBALS['csstidy']['replace_colors']['ivory'] = '#fffff0';
+$GLOBALS['csstidy']['replace_colors']['khaki'] = '#f0e68c';
+$GLOBALS['csstidy']['replace_colors']['lavender'] = '#e6e6fa';
+$GLOBALS['csstidy']['replace_colors']['lavenderblush'] = '#fff0f5';
+$GLOBALS['csstidy']['replace_colors']['lawngreen'] = '#7cfc00';
+$GLOBALS['csstidy']['replace_colors']['lemonchiffon'] = '#fffacd';
+$GLOBALS['csstidy']['replace_colors']['lightblue'] = '#add8e6';
+$GLOBALS['csstidy']['replace_colors']['lightcoral'] = '#f08080';
+$GLOBALS['csstidy']['replace_colors']['lightcyan'] = '#e0ffff';
+$GLOBALS['csstidy']['replace_colors']['lightgoldenrodyellow'] = '#fafad2';
+$GLOBALS['csstidy']['replace_colors']['lightgrey'] = '#d3d3d3';
+$GLOBALS['csstidy']['replace_colors']['lightgreen'] = '#90ee90';
+$GLOBALS['csstidy']['replace_colors']['lightpink'] = '#ffb6c1';
+$GLOBALS['csstidy']['replace_colors']['lightsalmon'] = '#ffa07a';
+$GLOBALS['csstidy']['replace_colors']['lightseagreen'] = '#20b2aa';
+$GLOBALS['csstidy']['replace_colors']['lightskyblue'] = '#87cefa';
+$GLOBALS['csstidy']['replace_colors']['lightslateblue'] = '#8470ff';
+$GLOBALS['csstidy']['replace_colors']['lightslategray'] = '#778899';
+$GLOBALS['csstidy']['replace_colors']['lightsteelblue'] = '#b0c4de';
+$GLOBALS['csstidy']['replace_colors']['lightyellow'] = '#ffffe0';
+$GLOBALS['csstidy']['replace_colors']['limegreen'] = '#32cd32';
+$GLOBALS['csstidy']['replace_colors']['linen'] = '#faf0e6';
+$GLOBALS['csstidy']['replace_colors']['magenta'] = '#ff00ff';
+$GLOBALS['csstidy']['replace_colors']['mediumaquamarine'] = '#66cdaa';
+$GLOBALS['csstidy']['replace_colors']['mediumblue'] = '#0000cd';
+$GLOBALS['csstidy']['replace_colors']['mediumorchid'] = '#ba55d3';
+$GLOBALS['csstidy']['replace_colors']['mediumpurple'] = '#9370d8';
+$GLOBALS['csstidy']['replace_colors']['mediumseagreen'] = '#3cb371';
+$GLOBALS['csstidy']['replace_colors']['mediumslateblue'] = '#7b68ee';
+$GLOBALS['csstidy']['replace_colors']['mediumspringgreen'] = '#00fa9a';
+$GLOBALS['csstidy']['replace_colors']['mediumturquoise'] = '#48d1cc';
+$GLOBALS['csstidy']['replace_colors']['mediumvioletred'] = '#c71585';
+$GLOBALS['csstidy']['replace_colors']['midnightblue'] = '#191970';
+$GLOBALS['csstidy']['replace_colors']['mintcream'] = '#f5fffa';
+$GLOBALS['csstidy']['replace_colors']['mistyrose'] = '#ffe4e1';
+$GLOBALS['csstidy']['replace_colors']['moccasin'] = '#ffe4b5';
+$GLOBALS['csstidy']['replace_colors']['navajowhite'] = '#ffdead';
+$GLOBALS['csstidy']['replace_colors']['oldlace'] = '#fdf5e6';
+$GLOBALS['csstidy']['replace_colors']['olivedrab'] = '#6b8e23';
+$GLOBALS['csstidy']['replace_colors']['orangered'] = '#ff4500';
+$GLOBALS['csstidy']['replace_colors']['orchid'] = '#da70d6';
+$GLOBALS['csstidy']['replace_colors']['palegoldenrod'] = '#eee8aa';
+$GLOBALS['csstidy']['replace_colors']['palegreen'] = '#98fb98';
+$GLOBALS['csstidy']['replace_colors']['paleturquoise'] = '#afeeee';
+$GLOBALS['csstidy']['replace_colors']['palevioletred'] = '#d87093';
+$GLOBALS['csstidy']['replace_colors']['papayawhip'] = '#ffefd5';
+$GLOBALS['csstidy']['replace_colors']['peachpuff'] = '#ffdab9';
+$GLOBALS['csstidy']['replace_colors']['peru'] = '#cd853f';
+$GLOBALS['csstidy']['replace_colors']['pink'] = '#ffc0cb';
+$GLOBALS['csstidy']['replace_colors']['plum'] = '#dda0dd';
+$GLOBALS['csstidy']['replace_colors']['powderblue'] = '#b0e0e6';
+$GLOBALS['csstidy']['replace_colors']['rosybrown'] = '#bc8f8f';
+$GLOBALS['csstidy']['replace_colors']['royalblue'] = '#4169e1';
+$GLOBALS['csstidy']['replace_colors']['saddlebrown'] = '#8b4513';
+$GLOBALS['csstidy']['replace_colors']['salmon'] = '#fa8072';
+$GLOBALS['csstidy']['replace_colors']['sandybrown'] = '#f4a460';
+$GLOBALS['csstidy']['replace_colors']['seagreen'] = '#2e8b57';
+$GLOBALS['csstidy']['replace_colors']['seashell'] = '#fff5ee';
+$GLOBALS['csstidy']['replace_colors']['sienna'] = '#a0522d';
+$GLOBALS['csstidy']['replace_colors']['skyblue'] = '#87ceeb';
+$GLOBALS['csstidy']['replace_colors']['slateblue'] = '#6a5acd';
+$GLOBALS['csstidy']['replace_colors']['slategray'] = '#708090';
+$GLOBALS['csstidy']['replace_colors']['snow'] = '#fffafa';
+$GLOBALS['csstidy']['replace_colors']['springgreen'] = '#00ff7f';
+$GLOBALS['csstidy']['replace_colors']['steelblue'] = '#4682b4';
+$GLOBALS['csstidy']['replace_colors']['tan'] = '#d2b48c';
+$GLOBALS['csstidy']['replace_colors']['thistle'] = '#d8bfd8';
+$GLOBALS['csstidy']['replace_colors']['tomato'] = '#ff6347';
+$GLOBALS['csstidy']['replace_colors']['turquoise'] = '#40e0d0';
+$GLOBALS['csstidy']['replace_colors']['violet'] = '#ee82ee';
+$GLOBALS['csstidy']['replace_colors']['violetred'] = '#d02090';
+$GLOBALS['csstidy']['replace_colors']['wheat'] = '#f5deb3';
+$GLOBALS['csstidy']['replace_colors']['whitesmoke'] = '#f5f5f5';
+$GLOBALS['csstidy']['replace_colors']['yellowgreen'] = '#9acd32';
+
+/**
+ * A list of all shorthand properties that are devided into four properties and/or have four subvalues
+ *
+ * @global array $GLOBALS['csstidy']['shorthands']
+ * @todo Are there new ones in CSS3?
+ * @see dissolve_4value_shorthands()
+ * @see merge_4value_shorthands()
+ * @version 1.0
+ */
+$GLOBALS['csstidy']['shorthands'] = array();
+$GLOBALS['csstidy']['shorthands']['border-color'] = array('border-top-color','border-right-color','border-bottom-color','border-left-color');
+$GLOBALS['csstidy']['shorthands']['border-style'] = array('border-top-style','border-right-style','border-bottom-style','border-left-style');
+$GLOBALS['csstidy']['shorthands']['border-width'] = array('border-top-width','border-right-width','border-bottom-width','border-left-width');
+$GLOBALS['csstidy']['shorthands']['margin'] = array('margin-top','margin-right','margin-bottom','margin-left');
+$GLOBALS['csstidy']['shorthands']['padding'] = array('padding-top','padding-right','padding-bottom','padding-left');
+$GLOBALS['csstidy']['shorthands']['-moz-border-radius'] = 0;
+
+/**
+ * All CSS Properties. Needed for csstidy::property_is_next()
+ *
+ * @global array $GLOBALS['csstidy']['all_properties']
+ * @todo Add CSS3 properties
+ * @version 1.0
+ * @see csstidy::property_is_next()
+ */
+$GLOBALS['csstidy']['all_properties']['alignment-adjust'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['alignment-baseline'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['animation'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['animation-delay'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['animation-direction'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['animation-duration'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['animation-iteration-count'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['animation-name'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['animation-play-state'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['animation-timing-function'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['appearance'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['azimuth'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['backface-visibility'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background-attachment'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background-clip'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background-color'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background-image'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background-origin'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background-position'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background-repeat'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['background-size'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['baseline-shift'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['binding'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['bleed'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['bookmark-label'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['bookmark-level'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['bookmark-state'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['bookmark-target'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-bottom'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-bottom-color'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-bottom-left-radius'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-bottom-right-radius'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-bottom-style'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-bottom-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-collapse'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-color'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-image'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-image-outset'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-image-repeat'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-image-slice'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-image-source'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-image-width'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-left'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-left-color'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-left-style'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-left-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-radius'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-right'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-right-color'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-right-style'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-right-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-spacing'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-style'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-top'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-top-color'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-top-left-radius'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-top-right-radius'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-top-style'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-top-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['border-width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['bottom'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['box-decoration-break'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['box-shadow'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['box-sizing'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['break-after'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['break-before'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['break-inside'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['caption-side'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['clear'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['clip'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['color'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['color-profile'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-count'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-fill'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-gap'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-rule'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-rule-color'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-rule-style'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-rule-width'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-span'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['column-width'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['columns'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['content'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['counter-increment'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['counter-reset'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['crop'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['cue'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['cue-after'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['cue-before'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['cursor'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['direction'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['display'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['dominant-baseline'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['drop-initial-after-adjust'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['drop-initial-after-align'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['drop-initial-before-adjust'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['drop-initial-before-align'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['drop-initial-size'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['drop-initial-value'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['elevation'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['empty-cells'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['fit'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['fit-position'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['flex-align'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['flex-flow'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['flex-line-pack'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['flex-order'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['flex-pack'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['float'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['float-offset'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['font'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['font-family'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['font-size'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['font-size-adjust'] = 'CSS2.0,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['font-stretch'] = 'CSS2.0,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['font-style'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['font-variant'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['font-weight'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['grid-columns'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['grid-rows'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['hanging-punctuation'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['height'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['hyphenate-after'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['hyphenate-before'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['hyphenate-character'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['hyphenate-lines'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['hyphenate-resource'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['hyphens'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['icon'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['image-orientation'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['image-rendering'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['image-resolution'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['inline-box-align'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['left'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['letter-spacing'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['line-break'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['line-height'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['line-stacking'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['line-stacking-ruby'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['line-stacking-shift'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['line-stacking-strategy'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['list-style'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['list-style-image'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['list-style-position'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['list-style-type'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['margin'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['margin-bottom'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['margin-left'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['margin-right'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['margin-top'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['marker-offset'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['marks'] = 'CSS2.0,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['marquee-direction'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['marquee-loop'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['marquee-play-count'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['marquee-speed'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['marquee-style'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['max-height'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['max-width'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['min-height'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['min-width'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['move-to'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['nav-down'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['nav-index'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['nav-left'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['nav-right'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['nav-up'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['opacity'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['orphans'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['outline'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['outline-color'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['outline-offset'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['outline-style'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['outline-width'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['overflow'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['overflow-style'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['overflow-wrap'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['overflow-x'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['overflow-y'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['padding'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['padding-bottom'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['padding-left'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['padding-right'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['padding-top'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['page'] = 'CSS2.0,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['page-break-after'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['page-break-before'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['page-break-inside'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['page-policy'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['pause'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['pause-after'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['pause-before'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['perspective'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['perspective-origin'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['phonemes'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['pitch'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['pitch-range'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['play-during'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['position'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['presentation-level'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['punctuation-trim'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['quotes'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['rendering-intent'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['resize'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['rest'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['rest-after'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['rest-before'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['richness'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['right'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['rotation'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['rotation-point'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['ruby-align'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['ruby-overhang'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['ruby-position'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['ruby-span'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['size'] = 'CSS2.0,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['speak'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['speak-header'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['speak-numeral'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['speak-punctuation'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['speech-rate'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['src'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['stress'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['string-set'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['tab-size'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['table-layout'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['target'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['target-name'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['target-new'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['target-position'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-align'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-align-last'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-decoration'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-decoration-color'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-decoration-line'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-decoration-skip'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-decoration-style'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-emphasis'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-emphasis-color'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-emphasis-position'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-emphasis-style'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-height'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-indent'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-justify'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-outline'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-shadow'] = 'CSS2.0,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-space-collapse'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-transform'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-underline-position'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['text-wrap'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['top'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['transform'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['transform-origin'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['transform-style'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['transition'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['transition-delay'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['transition-duration'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['transition-property'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['transition-timing-function'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['unicode-bidi'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['vertical-align'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['visibility'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['voice-balance'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['voice-duration'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['voice-family'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['voice-pitch'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['voice-pitch-range'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['voice-rate'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['voice-stress'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['voice-volume'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['volume'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['white-space'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['widows'] = 'CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['width'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['word-break'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['word-spacing'] = 'CSS1.0,CSS2.0,CSS2.1,CSS3.0';
+$GLOBALS['csstidy']['all_properties']['word-wrap'] = 'CSS3.0';
+$GLOBALS['csstidy']['all_properties']['z-index'] = 'CSS2.0,CSS2.1,CSS3.0';
+
+/**
+ * An array containing all properties that can accept a quoted string as a value.
+ *
+ * @global array $GLOBALS['csstidy']['quoted_string_properties']
+ */
+$GLOBALS['csstidy']['quoted_string_properties'] = array('content', 'font', 'font-family', 'quotes');
+
+/**
+ * An array containing all properties that can be defined multiple times without being overwritten.
+ * All unit values are included so that units like rem can be supported with fallbacks to px or em.
+ *
+ * @global array $GLOBALS['csstidy']['quoted_string_properties']
+ */
+$GLOBALS['csstidy']['multiple_properties'] = array_merge( $GLOBALS['csstidy']['unit_values'], array('background', 'background-image', 'transition') );
+
+/**
+ * An array containing all predefined templates.
+ *
+ * @global array $GLOBALS['csstidy']['predefined_templates']
+ * @version 1.0
+ * @see csstidy::load_template()
+ */
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="at">'; //string before @rule
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '</span> <span class="format">{</span>'."\n"; //bracket after @-rule
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="selector">'; //string before selector
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '</span> <span class="format">{</span>'."\n"; //bracket after selector
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="property">'; //string before property
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '</span><span class="value">'; //string after property+before value
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '</span><span class="format">;</span>'."\n"; //string after value
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="format">}</span>'; //closing bracket - selector
+$GLOBALS['csstidy']['predefined_templates']['default'][] = "\n\n"; //space between blocks {...}
+$GLOBALS['csstidy']['predefined_templates']['default'][] = "\n".'<span class="format">}</span>'. "\n\n"; //closing bracket @-rule
+$GLOBALS['csstidy']['predefined_templates']['default'][] = ''; //indent in @-rule
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '<span class="comment">'; // before comment
+$GLOBALS['csstidy']['predefined_templates']['default'][] = '</span>'."\n"; // after comment
+$GLOBALS['csstidy']['predefined_templates']['default'][] = "\n"; // after last line @-rule
+
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="at">';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span> <span class="format">{</span>'."\n";
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="selector">';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="format">{</span>';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="property">';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="value">';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span><span class="format">;</span>';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="format">}</span>';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = "\n";
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = "\n". '<span class="format">}'."\n".'</span>';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '';
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '<span class="comment">'; // before comment
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = '</span>'; // after comment
+$GLOBALS['csstidy']['predefined_templates']['high_compression'][] = "\n";
+
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="at">';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">{</span>';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="selector">';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">{</span>';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="property">';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="value">';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span><span class="format">;</span>';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="format">}</span>';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="format">}</span>';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '';
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '<span class="comment">'; // before comment
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '</span>'; // after comment
+$GLOBALS['csstidy']['predefined_templates']['highest_compression'][] = '';
+
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '<span class="at">';
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span> <span class="format">{</span>'."\n";
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '<span class="selector">';
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span>'."\n".'<span class="format">{</span>'."\n";
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = ' <span class="property">';
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span><span class="value">';
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span><span class="format">;</span>'."\n";
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '<span class="format">}</span>';
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = "\n\n";
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = "\n".'<span class="format">}</span>'."\n\n";
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = ' ';
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '<span class="comment">'; // before comment
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = '</span>'."\n"; // after comment
+$GLOBALS['csstidy']['predefined_templates']['low_compression'][] = "\n";
+
+require dirname( __FILE__ ) . '/data-wp.inc.php';
+
+?>
diff --git a/plugins/jetpack/modules/custom-css/csstidy/lang.inc.php b/plugins/jetpack/modules/custom-css/csstidy/lang.inc.php
new file mode 100644
index 00000000..9e6b24b0
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/lang.inc.php
@@ -0,0 +1,311 @@
+<?php
+
+/**
+ * Localization of CSS Optimiser Interface of CSSTidy
+ *
+ * Copyright 2005, 2006, 2007 Florian Schmitz
+ *
+ * This file is part of CSSTidy.
+ *
+ * CSSTidy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * CSSTidy is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
+ * @package csstidy
+ * @author Florian Schmitz (floele at gmail dot com) 2005-2007
+ * @author Brett Zamir (brettz9 at yahoo dot com) 2007
+ */
+
+
+if(isset($_GET['lang'])) {
+ $l = $_GET['lang'];
+}
+else if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+ $l = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
+ $l = strtolower(substr($l, 0, 2));
+}
+else {
+ $l = '';
+}
+
+$l = (in_array($l, array('de', 'fr', 'zh'))) ? $l : 'en';
+
+// note 5 in all but French, and 40 in all are orphaned
+
+$lang = array();
+$lang['en'][0] = 'CSS Formatter and Optimiser/Optimizer (based on CSSTidy ';
+$lang['en'][1] = 'CSS Formatter and Optimiser';
+$lang['en'][2] = '(based on';
+$lang['en'][3] = '(plaintext)';
+$lang['en'][4] = 'Important Note:';
+$lang['en'][6] = 'Your code should be well-formed. This is <strong>not a validator</strong> which points out errors in your CSS code. To make sure that your code is valid, use the <a href="http://jigsaw.w3.org/css-validator/">W3C Validator</a>.';
+$lang['en'][7] = 'all comments are removed';
+$lang['en'][8] = 'CSS Input:';
+$lang['en'][9] = 'CSS-Code:';
+$lang['en'][10] = 'CSS from URL:';
+$lang['en'][11] = 'Code Layout:';
+$lang['en'][12] = 'Compression&#160;(code&#160;layout):';
+$lang['en'][13] = 'Highest (no readability, smallest size)';
+$lang['en'][14] = 'High (moderate readability, smaller size)';
+$lang['en'][15] = 'Standard (balance between readability and size)';
+$lang['en'][16] = 'Low (higher readability)';
+$lang['en'][17] = 'Custom (enter below)';
+$lang['en'][18] = 'Custom <a href="http://csstidy.sourceforge.net/templates.php">template</a>';
+$lang['en'][19] = 'Options';
+$lang['en'][20] = 'Sort Selectors (caution)';
+$lang['en'][21] = 'Sort Properties';
+$lang['en'][22] = 'Regroup selectors';
+$lang['en'][23] = 'Optimise shorthands';
+$lang['en'][24] = 'Compress colors';
+$lang['en'][25] = 'Lowercase selectors';
+$lang['en'][26] = 'Case for properties:';
+$lang['en'][27] = 'Lowercase';
+$lang['en'][28] = 'No or invalid CSS input or wrong URL!';
+$lang['en'][29] = 'Uppercase';
+$lang['en'][30] = 'lowercase elementnames needed for XHTML';
+$lang['en'][31] = 'Remove unnecessary backslashes';
+$lang['en'][32] = 'convert !important-hack';
+$lang['en'][33] = 'Output as file';
+$lang['en'][34] = 'Bigger compression because of smaller newlines (copy &#38; paste doesn\'t work)';
+$lang['en'][35] = 'Process CSS';
+$lang['en'][36] = 'Compression Ratio';
+$lang['en'][37] = 'Input';
+$lang['en'][38] = 'Output';
+$lang['en'][39] = 'Language';
+$lang['en'][41] = 'Attention: This may change the behaviour of your CSS Code!';
+$lang['en'][42] = 'Remove last ;';
+$lang['en'][43] = 'Discard invalid properties';
+$lang['en'][44] = 'Only safe optimisations';
+$lang['en'][45] = 'Compress font-weight';
+$lang['en'][46] = 'Save comments';
+$lang['en'][47] = 'Do not change anything';
+$lang['en'][48] = 'Only seperate selectors (split at ,)';
+$lang['en'][49] = 'Merge selectors with the same properties (fast)';
+$lang['en'][50] = 'Merge selectors intelligently (slow)';
+$lang['en'][51] = 'Preserve CSS';
+$lang['en'][52] = 'Save comments, hacks, etc. Most optimisations can *not* be applied if this is enabled.';
+$lang['en'][53] = 'None';
+$lang['en'][54] = 'Don\'t optimise';
+$lang['en'][55] = 'Safe optimisations';
+$lang['en'][56] = 'All optimisations';
+$lang['en'][57] = 'Add timestamp';
+$lang['en'][58] = 'Copy to clipboard';
+$lang['en'][59] = 'Back to top';
+$lang['en'][60] = 'Your browser doesn\'t support copy to clipboard.';
+$lang['en'][61] = 'For bugs and suggestions feel free to';
+$lang['en'][62] = 'contact me';
+$lang['en'][63] = 'Output CSS code as complete HTML document';
+$lang['en'][64] = 'Code';
+$lang['en'][65] = 'CSS to style CSS output';
+$lang['en'][66] = 'You need to go to about:config in your URL bar, select \'signed.applets.codebase_principal_support\' in the filter field, and set its value to true in order to use this feature; however, be aware that doing so increases security risks.';
+
+
+$lang['de'][0] = 'CSS Formatierer und Optimierer (basierend auf CSSTidy ';
+$lang['de'][1] = 'CSS Formatierer und Optimierer';
+$lang['de'][2] = '(basierend auf';
+$lang['de'][3] = '(Textversion)';
+$lang['de'][4] = 'Wichtiger Hinweis:';
+$lang['de'][6] = 'Der CSS Code sollte wohlgeformt sein. Der CSS Code wird <strong>nicht auf Gültigkeit überprüft</strong>. Um sicherzugehen dass dein Code valide ist, benutze den <a href="http://jigsaw.w3.org/css-validator/">W3C Validierungsservice</a>.';
+$lang['de'][7] = 'alle Kommentare werden entfernt';
+$lang['de'][8] = 'CSS Eingabe:';
+$lang['de'][9] = 'CSS-Code:';
+$lang['de'][10] = 'CSS von URL:';
+$lang['de'][11] = 'Code Layout:';
+$lang['de'][12] = 'Komprimierung&#160;(Code&#160;Layout):';
+$lang['de'][13] = 'Höchste (keine Lesbarkeit, niedrigste Größe)';
+$lang['de'][14] = 'Hoch (mittelmäßige Lesbarkeit, geringe Größe)';
+$lang['de'][15] = 'Standard (Kompromiss zwischen Lesbarkeit und Größe)';
+$lang['de'][16] = 'Niedrig (höhere Lesbarkeit)';
+$lang['de'][17] = 'Benutzerdefiniert (unten eingeben)';
+$lang['de'][18] = 'Benutzerdefinierte <a href="http://csstidy.sourceforge.net/templates.php">Vorlage</a>';
+$lang['de'][19] = 'Optionen';
+$lang['de'][20] = 'Selektoren sortieren (Vorsicht)';
+$lang['de'][21] = 'Eigenschaften sortieren';
+$lang['de'][22] = 'Selektoren umgruppieren';
+$lang['de'][23] = 'Shorthands optimieren';
+$lang['de'][24] = 'Farben komprimieren';
+$lang['de'][25] = 'Selektoren in Kleinbuchstaben';
+$lang['de'][26] = 'Groß-/Kleinschreibung für Eigenschaften';
+$lang['de'][27] = 'Kleinbuchstaben';
+$lang['de'][28] = 'Keine oder ungültige CSS Eingabe oder falsche URL!';
+$lang['de'][29] = 'Großbuchstaben';
+$lang['de'][30] = 'kleingeschriebene Elementnamen benötigt für XHTML';
+$lang['de'][31] = 'Unnötige Backslashes entfernen';
+$lang['de'][32] = '!important-Hack konvertieren';
+$lang['de'][33] = 'Als Datei ausgeben';
+$lang['de'][34] = 'Größere Komprimierung augrund von kleineren Neuezeile-Zeichen';
+$lang['de'][35] = 'CSS verarbeiten';
+$lang['de'][36] = 'Komprimierungsrate';
+$lang['de'][37] = 'Eingabe';
+$lang['de'][38] = 'Ausgabe';
+$lang['de'][39] = 'Sprache';
+$lang['de'][41] = 'Achtung: Dies könnte das Verhalten ihres CSS-Codes verändern!';
+$lang['de'][42] = 'Letztes ; entfernen';
+$lang['de'][43] = 'Ungültige Eigenschaften entfernen';
+$lang['de'][44] = 'Nur sichere Optimierungen';
+$lang['de'][45] = 'font-weight komprimieren';
+$lang['de'][46] = 'Kommentare beibehalten';
+$lang['de'][47] = 'Nichts ändern';
+$lang['de'][48] = 'Selektoren nur trennen (am Komma)';
+$lang['de'][49] = 'Selektoren mit gleichen Eigenschaften zusammenfassen (schnell)';
+$lang['de'][50] = 'Selektoren intelligent zusammenfassen (langsam!)';
+$lang['de'][51] = 'CSS erhalten';
+$lang['de'][52] = 'Kommentare, Hacks, etc. speichern. Viele Optimierungen sind dann aber nicht mehr möglich.';
+$lang['de'][53] = 'Keine';
+$lang['de'][54] = 'Nicht optimieren';
+$lang['de'][55] = 'Sichere Optimierungen';
+$lang['de'][56] = 'Alle Optimierungen';
+$lang['de'][57] = 'Zeitstempel hinzufügen';
+$lang['de'][58] = 'Copy to clipboard';
+$lang['de'][59] = 'Back to top';
+$lang['de'][60] = 'Your browser doesn\'t support copy to clipboard.';
+$lang['de'][61] = 'For bugs and suggestions feel free to';
+$lang['de'][62] = 'contact me';
+$lang['de'][63] = 'Output CSS code as complete HTML document';
+$lang['de'][64] = 'Code';
+$lang['de'][65] = 'CSS to style CSS output';
+$lang['de'][66] = 'You need to go to about:config in your URL bar, select \'signed.applets.codebase_principal_support\' in the filter field, and set its value to true in order to use this feature; however, be aware that doing so increases security risks.';
+
+
+$lang['fr'][0] = 'CSS Formatteur et Optimiseur (basé sur CSSTidy ';
+$lang['fr'][1] = 'CSS Formatteur et Optimiseur';
+$lang['fr'][2] = '(basé sur ';
+$lang['fr'][3] = '(Version texte)';
+$lang['fr'][4] = 'Note Importante&#160;:';
+$lang['fr'][6] = 'Votre code doit être valide. Ce n’est <strong>pas un validateur</strong> qui signale les erreurs dans votre code CSS. Pour être sûr que votre code est correct, utilisez le validateur&#160;: <a href="http://jigsaw.w3.org/css-validator/">W3C Validator</a>.';
+$lang['fr'][7] = 'tous les commentaires sont enlevés';
+$lang['fr'][8] = 'Champ CSS&#160;:';
+$lang['fr'][9] = 'Code CSS&#160;:';
+$lang['fr'][10] = 'CSS en provenance d’une URL&#160;:<br />';
+$lang['fr'][11] = 'Mise en page du code&#160;:';
+$lang['fr'][12] = 'Compression (mise en page du code)&#160;:';
+$lang['fr'][13] = 'La plus élevée (aucune lisibilité, taille minimale)';
+$lang['fr'][14] = 'Élevée (lisibilité modérée, petite taille)';
+$lang['fr'][15] = 'Normale (équilibre entre lisibilité et taille)';
+$lang['fr'][16] = 'Faible (lisibilité élevée)';
+$lang['fr'][17] = 'Sur mesure (entrer ci-dessous)';
+$lang['fr'][18] = '<a href="http://csstidy.sourceforge.net/templates.php">Gabarit</a> sur mesure';
+$lang['fr'][19] = 'Options';
+$lang['fr'][20] = 'Trier les sélecteurs (attention)';
+$lang['fr'][21] = 'Trier les propriétés';
+$lang['fr'][22] = 'Regrouper les sélecteurs';
+$lang['fr'][23] = 'Propriétés raccourcies';
+$lang['fr'][24] = 'Compresser les couleurs';
+$lang['fr'][25] = 'Sélecteurs en minuscules';
+$lang['fr'][26] = 'Case pour les propriétés&#160;:';
+$lang['fr'][27] = 'Minuscule';
+$lang['fr'][28] = 'CSS non valide ou URL incorrecte&#160;!';
+$lang['fr'][29] = 'Majuscule';
+$lang['fr'][30] = 'les noms des éléments en minuscules (indispensables pour XHTML)';
+$lang['fr'][31] = 'enlever les antislashs inutiles';
+$lang['fr'][32] = 'convertir !important-hack';
+$lang['fr'][33] = 'Sauver en tant que fichier';
+$lang['fr'][34] = 'Meilleure compression grâce aux caractères de saut de ligne plus petits (copier &#38; coller ne marche pas)';
+$lang['fr'][35] = 'Compresser la CSS';
+$lang['fr'][36] = 'Facteur de Compression';
+$lang['fr'][37] = 'Entrée';
+$lang['fr'][38] = 'Sortie';
+$lang['fr'][39] = 'Langue';
+$lang['fr'][41] = 'Attention&#160;: ceci peut changer le comportement de votre code CSS&#160;!';
+$lang['fr'][42] = 'Enlever le dernier ;';
+$lang['fr'][43] = 'Supprimer les propriétés non valide';
+$lang['fr'][44] = 'Seulement les optimisations sûres';
+$lang['fr'][45] = 'Compresser font-weight';
+$lang['fr'][46] = 'Sauvegarder les commentaires ';
+$lang['fr'][47] = 'Ne rien changer';
+$lang['fr'][48] = 'Sépare les sélecteurs (sépare au niveau de ,)';
+$lang['fr'][49] = 'Fusionne les sélecteurs avec les mêmes propriétés (rapide)';
+$lang['fr'][50] = 'Fusionne les sélecteurs intelligemment (lent)';
+$lang['fr'][51] = 'Préserver la CSS';
+$lang['fr'][52] = 'Sauvegarder les commentaires, hacks, etc. La plupart des optimisations ne peuvent *pas* être appliquées si cela est activé.';
+$lang['fr'][53] = 'Aucun';
+$lang['fr'][54] = 'Ne pas optimiser';
+$lang['fr'][55] = 'Optimisations sûres';
+$lang['fr'][56] = 'Toutes les optimisations';
+$lang['fr'][57] = 'Ajouter un timestamp';
+$lang['fr'][58] = 'Copier dans le presse-papiers';
+$lang['fr'][59] = 'Retour en haut';
+$lang['fr'][60] = 'Votre navigateur ne suporte pas la copie vers le presse-papiers.';
+$lang['fr'][61] = 'Pour signaler des bugs ou pour des suggestions,';
+$lang['fr'][62] = 'contactez-moi';
+$lang['fr'][63] = 'Sauver le code CSS comme document complet HTML';
+$lang['fr'][64] = 'Code';
+$lang['fr'][65] = 'CSS pour colorier la sortie CSS';
+$lang['fr'][66] = 'Vous devez aller dans about:config dans votre barre d’adresse, selectionner \'signed.applets.codebase_principal_support\' dans le champ Filtre et attribuez-lui la valeur \'true\' pour utiliser cette fonctionnalité; toutefois, soyez conscient que cela augmente les risques de sécurité.';
+
+
+$lang['zh'][0] = 'CSS整形與最佳化工具(使用 CSSTidy ';
+$lang['zh'][1] = 'CSS整形與最佳化工具';
+$lang['zh'][2] = '(使用';
+$lang['zh'][3] = '(純文字)';
+$lang['zh'][4] = 'é‡è¦äº‹é …:';
+$lang['zh'][6] = '你的原始碼必須是良構的(well-formed). 這個工具<strong>沒有內建驗證器(validator)</strong>. 驗證器能夠指出你CSS原始碼裡的錯誤. 請使用 <a href="http://jigsaw.w3.org/css-validator/">W3C 驗證器</a>, 確ä¿ä½ çš„原始碼åˆä¹Žè¦ç¯„.';
+$lang['zh'][7] = '所有註解都移除了';
+$lang['zh'][8] = 'CSS 輸入:';
+$lang['zh'][9] = 'CSS 原始碼:';
+$lang['zh'][10] = 'CSS 檔案網å€(URL):';
+$lang['zh'][11] = '原始碼è¦åŠƒ:';
+$lang['zh'][12] = '壓縮程度(原始碼è¦åŠƒ):';
+$lang['zh'][13] = '最高 (沒有辦法讀, 檔案最å°)';
+$lang['zh'][14] = '高 (é©åº¦çš„å¯è®€æ€§, 檔案å°)';
+$lang['zh'][15] = '標準 (兼顧å¯è®€æ€§èˆ‡æª”案大å°)';
+$lang['zh'][16] = '低 (注é‡å¯è®€æ€§)';
+$lang['zh'][17] = '自訂 (在下方設定)';
+$lang['zh'][18] = '自訂<a href="http://csstidy.sourceforge.net/templates.php">樣æ¿</a>';
+$lang['zh'][19] = 'é¸é …';
+$lang['zh'][20] = 'æ•´ç†é¸æ“‡ç¬¦(請謹慎使用)';
+$lang['zh'][21] = 'æ•´ç†å±¬æ€§';
+$lang['zh'][22] = 'é‡çµ„é¸æ“‡ç¬¦';
+$lang['zh'][23] = '速記法(shorthand)最佳化';
+$lang['zh'][24] = '壓縮色彩語法';
+$lang['zh'][25] = '改用å°å¯«é¸æ“‡ç¬¦';
+$lang['zh'][26] = '屬性的字形:';
+$lang['zh'][27] = 'å°å¯«';
+$lang['zh'][28] = '沒有輸入CSS, 語法ä¸ç¬¦åˆè¦å®š, 或是網å€éŒ¯èª¤!';
+$lang['zh'][29] = '大寫';
+$lang['zh'][30] = 'XHTML必須使用å°å¯«çš„元素å稱';
+$lang['zh'][31] = '移除ä¸å¿…è¦çš„å斜線';
+$lang['zh'][32] = 'è½‰æ› !important-hack';
+$lang['zh'][33] = '輸出æˆæª”案形å¼';
+$lang['zh'][34] = '由於比較少æ›è¡Œå­—å…ƒ, 會有更大的壓縮比率(複製&#38;貼上沒有用)';
+$lang['zh'][35] = '執行';
+$lang['zh'][36] = '壓縮比率';
+$lang['zh'][37] = '輸入';
+$lang['zh'][38] = '輸出';
+$lang['zh'][39] = '語言';
+$lang['zh'][41] = '注æ„: 這或許會變更你CSS原始碼的行為!';
+$lang['zh'][42] = '除去最後一個分號';
+$lang['zh'][43] = '拋棄ä¸ç¬¦åˆè¦å®šçš„屬性';
+$lang['zh'][44] = 'åªå®‰å…¨åœ°æœ€ä½³åŒ–';
+$lang['zh'][45] = '壓縮 font-weight';
+$lang['zh'][46] = 'ä¿ç•™è¨»è§£';
+$lang['zh'][47] = '什麼都ä¸è¦æ”¹';
+$lang['zh'][48] = 'åªåˆ†é–‹åŽŸæœ¬ç”¨é€—號分隔的é¸æ“‡ç¬¦';
+$lang['zh'][49] = 'åˆä½µæœ‰ç›¸åŒå±¬æ€§çš„é¸æ“‡ç¬¦(快速)';
+$lang['zh'][50] = 'è°æ˜Žåœ°åˆä½µé¸æ“‡ç¬¦(慢速)';
+$lang['zh'][51] = 'ä¿è­·CSS';
+$lang['zh'][52] = 'ä¿ç•™è¨»è§£èˆ‡ hack 等等. 如果啟用這個é¸é …, 大多數的最佳化程åºéƒ½ä¸æœƒåŸ·è¡Œ.';
+$lang['zh'][53] = 'ä¸æ”¹è®Š';
+$lang['zh'][54] = 'ä¸åšæœ€ä½³åŒ–';
+$lang['zh'][55] = '安全地最佳化';
+$lang['zh'][56] = '全部最佳化';
+$lang['zh'][57] = '加上時間戳記';
+$lang['zh'][58] = 'å¤åˆ¶åˆ°å‰ªè´´æ¿';
+$lang['zh'][59] = '回到页é¢ä¸Šæ–¹';
+$lang['zh'][60] = 'ä½ çš„æµè§ˆå™¨ä¸æ”¯æŒå¤åˆ¶åˆ°å‰ªè´´æ¿ã€‚';
+$lang['zh'][61] = '如果程åºæœ‰é”™è¯¯æˆ–你有建议,欢迎';
+$lang['zh'][62] = '和我è”ç³»';
+$lang['zh'][63] = 'Output CSS code as complete HTML document';
+$lang['zh'][64] = '代ç ';
+$lang['zh'][65] = 'CSS to style CSS output';
+$lang['zh'][66] = 'You need to go to about:config in your URL bar, select \'signed.applets.codebase_principal_support\' in the filter field, and set its value to true in order to use this feature; however, be aware that doing so increases security risks.';
diff --git a/plugins/jetpack/modules/custom-css/csstidy/wordpress-standard.tpl b/plugins/jetpack/modules/custom-css/csstidy/wordpress-standard.tpl
new file mode 100644
index 00000000..9499e839
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/csstidy/wordpress-standard.tpl
@@ -0,0 +1,10 @@
+| {
+|| {
+| | |;
+|}|
+
+|
+}
+
+| ||
+|
diff --git a/plugins/jetpack/modules/custom-css/custom-css.php b/plugins/jetpack/modules/custom-css/custom-css.php
new file mode 100644
index 00000000..9bc0c211
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css.php
@@ -0,0 +1,1468 @@
+<?php
+
+class Jetpack_Custom_CSS {
+ static function init() {
+ add_action( 'switch_theme', array( __CLASS__, 'reset' ) );
+ add_action( 'wp_restore_post_revision', array( __CLASS__, 'restore_revision' ), 10, 2 );
+
+ // Save revisions for posts of type safecss.
+ add_filter( 'revision_redirect', array( __CLASS__, 'revision_redirect' ) );
+
+ // Override the edit link, the default link causes a redirect loop
+ add_filter( 'get_edit_post_link', array( __CLASS__, 'revision_post_link' ), 10, 3 );
+
+ if ( ! is_admin() )
+ add_filter( 'stylesheet_uri', array( __CLASS__, 'style_filter' ) );
+
+ define( 'SAFECSS_USE_ACE', ! jetpack_is_mobile() && ! Jetpack_User_Agent_Info::is_ipad() && apply_filters( 'safecss_use_ace', true ) );
+
+ // Register safecss as a custom post_type
+ // Explicit capability definitions are largely unnecessary because the posts are manipulated in code via an options page, managing CSS revisions does check the capabilities, so let's ensure that the proper caps are checked.
+ register_post_type( 'safecss', array(
+ // These are the defaults
+ // 'exclude_from_search' => true,
+ // 'public' => false,
+ // 'publicly_queryable' => false,
+ // 'show_ui' => false,
+ 'supports' => array( 'revisions' ),
+ 'label' => 'Custom CSS',
+ 'can_export' => false,
+ 'rewrite' => false,
+ 'capabilities' => array(
+ 'edit_post' => 'edit_theme_options',
+ 'read_post' => 'read',
+ 'delete_post' => 'edit_theme_options',
+ 'edit_posts' => 'edit_theme_options',
+ 'edit_others_posts' => 'edit_theme_options',
+ 'publish_posts' => 'edit_theme_options',
+ 'read_private_posts' => 'read'
+ )
+ ) );
+
+ // Short-circuit WP if this is a CSS stylesheet request
+ if ( isset( $_GET['custom-css'] ) ) {
+ header( 'Content-Type: text/css', true, 200 );
+ header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 31536000) . ' GMT' ); // 1 year
+ Jetpack_Custom_CSS::print_css();
+ exit;
+ }
+
+ if ( isset( $_GET['page'] ) && 'editcss' == $_GET['page'] && is_admin() ) {
+ // Do migration routine if necessary
+ Jetpack_Custom_CSS::upgrade();
+
+ do_action( 'safecss_migrate_post' );
+ }
+
+ add_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
+
+ if ( !current_user_can( 'switch_themes' ) && !is_super_admin() )
+ return;
+
+ add_action( 'admin_menu', array( 'Jetpack_Custom_CSS', 'menu' ) );
+
+ if ( isset( $_POST['safecss'] ) && false == strstr( $_SERVER[ 'REQUEST_URI' ], 'options.php' ) ) {
+ check_admin_referer( 'safecss' );
+
+ $save_result = self::save( array(
+ 'css' => $_POST['safecss'],
+ 'is_preview' => isset( $_POST['action'] ) && $_POST['action'] == 'preview',
+ 'preprocessor' => isset( $_POST['custom_css_preprocessor'] ) ? $_POST['custom_css_preprocessor'] : '',
+ 'add_to_existing' => isset( $_POST['add_to_existing'] ) ? $_POST['add_to_existing'] == 'true' : true,
+ 'content_width' => isset( $_POST['custom_content_width'] ) ? $_POST['custom_content_width'] : false,
+ ) );
+
+ if ( $_POST['action'] == 'preview' ) {
+ wp_safe_redirect( add_query_arg( 'csspreview', 'true', get_option( 'home' ) ) );
+ exit;
+ }
+
+ if ( $save_result )
+ add_action( 'admin_notices', array( 'Jetpack_Custom_CSS', 'saved_message' ) );
+ }
+
+ // Modify all internal links so that preview state persists
+ if ( Jetpack_Custom_CSS::is_preview() )
+ ob_start( array( 'Jetpack_Custom_CSS', 'buffer' ) );
+ }
+
+ /**
+ * Save new custom CSS. This should be the entry point for any third-party code using Jetpack_Custom_CSS
+ * to save CSS.
+ *
+ * @param array $args Array of arguments:
+ * string $css The CSS (or LESS or Sass)
+ * bool $is_preview Whether this CSS is preview or published
+ * bool $add_to_existing Whether this CSS replaces the theme's CSS or supplements it.
+ * int $content_width A custom $content_width to go along with this CSS.
+ * @return int The post ID of the saved Custom CSS post.
+ */
+ public static function save( $args = array() ) {
+ $defaults = array(
+ 'css' => '',
+ 'is_preview' => false,
+ 'preprocessor' => '',
+ 'add_to_existing' => true,
+ 'content_width' => false,
+ );
+
+ $args = wp_parse_args( $args, $defaults );
+
+ // Remove wp_filter_post_kses, this causes CSS escaping issues
+ remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
+ remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' );
+ remove_all_filters( 'content_save_pre' );
+
+ do_action( 'safecss_save_pre', $args );
+
+ $warnings = array();
+
+ safecss_class();
+ $csstidy = new csstidy();
+ $csstidy->optimise = new safecss( $csstidy );
+
+ $csstidy->set_cfg( 'remove_bslash', false );
+ $csstidy->set_cfg( 'compress_colors', false );
+ $csstidy->set_cfg( 'compress_font-weight', false );
+ $csstidy->set_cfg( 'optimise_shorthands', 0 );
+ $csstidy->set_cfg( 'remove_last_;', false );
+ $csstidy->set_cfg( 'case_properties', false );
+ $csstidy->set_cfg( 'discard_invalid_properties', true );
+ $csstidy->set_cfg( 'css_level', 'CSS3.0' );
+ $csstidy->set_cfg( 'preserve_css', true );
+ $csstidy->set_cfg( 'template', dirname( __FILE__ ) . '/csstidy/wordpress-standard.tpl' );
+
+ $css = $orig = stripslashes( $args['css'] );
+
+ $css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $prev = $css );
+
+ if ( $css != $prev )
+ $warnings[] = 'preg_replace found stuff';
+
+ // Some people put weird stuff in their CSS, KSES tends to be greedy
+ $css = str_replace( '<=', '&lt;=', $css );
+ // Why KSES instead of strip_tags? Who knows?
+ $css = wp_kses_split( $prev = $css, array(), array() );
+ $css = str_replace( '&gt;', '>', $css ); // kses replaces lone '>' with &gt;
+ // Why both KSES and strip_tags? Because we just added some '>'.
+ $css = strip_tags( $css );
+
+ if ( $css != $prev )
+ $warnings[] = 'kses found stuff';
+
+ // if we're not using a preprocessor
+ if ( ! $args['preprocessor'] ) {
+ do_action( 'safecss_parse_pre', $csstidy, $css, $args );
+
+ $csstidy->parse( $css );
+
+ do_action( 'safecss_parse_post', $csstidy, $warnings, $args );
+
+ $css = $csstidy->print->plain();
+ }
+
+ if ( $args['content_width'] && intval( $args['content_width']) > 0 && ( ! isset( $GLOBALS['content_width'] ) || $args['content_width'] != $GLOBALS['content_width'] ) )
+ $custom_content_width = intval( $args['content_width'] );
+ else
+ $custom_content_width = false;
+
+ if ( $args['add_to_existing'] )
+ $add_to_existing = 'yes';
+ else
+ $add_to_existing = 'no';
+
+ if ( $args['is_preview'] || Jetpack_Custom_CSS::is_freetrial() ) {
+ // Save the CSS
+ $safecss_revision_id = Jetpack_Custom_CSS::save_revision( $css, true, $args['preprocessor'] );
+
+ // Cache Buster
+ update_option( 'safecss_preview_rev', intval( get_option( 'safecss_preview_rev' ) ) + 1);
+
+ update_metadata( 'post', $safecss_revision_id, 'custom_css_add', $add_to_existing );
+ update_metadata( 'post', $safecss_revision_id, 'content_width', $custom_content_width );
+ update_metadata( 'post', $safecss_revision_id, 'custom_css_preprocessor', $args['preprocessor'] );
+
+ if ( $args['is_preview'] ) {
+ return $safecss_revision_id;
+ }
+
+ // Freetrial only.
+ do_action( 'safecss_save_preview_post' );
+ }
+
+ // Save the CSS
+ $safecss_post_id = Jetpack_Custom_CSS::save_revision( $css, false, $args['preprocessor'] );
+
+ $safecss_post_revision = Jetpack_Custom_CSS::get_current_revision();
+
+ update_option( 'safecss_rev', intval( get_option( 'safecss_rev' ) ) + 1 );
+
+ update_post_meta( $safecss_post_id, 'custom_css_add', $add_to_existing );
+ update_post_meta( $safecss_post_id, 'content_width', $custom_content_width );
+ update_post_meta( $safecss_post_id, 'custom_css_preprocessor', $args['preprocessor'] );
+ update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_add', $add_to_existing );
+ update_metadata( 'post', $safecss_post_revision['ID'], 'content_width', $custom_content_width );
+ update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_preprocessor', $args['preprocessor'] );
+
+ return $safecss_post_id;
+ }
+
+ /**
+ * Get the published custom CSS post.
+ *
+ * @return array
+ */
+ static function get_post() {
+ $custom_css_post_id = Jetpack_Custom_CSS::post_id();
+
+ if ( $custom_css_post_id )
+ return get_post( $custom_css_post_id, ARRAY_A );
+
+ return array();
+ }
+
+ /**
+ * Get the post ID of the published custom CSS post.
+ *
+ * @return int|bool The post ID if it exists; false otherwise.
+ */
+ static function post_id() {
+ $custom_css_post_id = wp_cache_get( 'custom_css_post_id' );
+
+ if ( false === $custom_css_post_id ) {
+ $custom_css_post = array_shift( get_posts( array(
+ 'posts_per_page' => 1,
+ 'post_type' => 'safecss',
+ 'post_status' => 'publish',
+ 'orderby' => 'date',
+ 'order' => 'DESC'
+ ) ) );
+
+ if ( $custom_css_post )
+ $custom_css_post_id = $custom_css_post->ID;
+ else
+ $custom_css_post_id = 0;
+
+ // Save post_id=0 to note that no safecss post exists.
+ wp_cache_set( 'custom_css_post_id', $custom_css_post_id );
+ }
+
+ if ( ! $custom_css_post_id )
+ return false;
+
+ return $custom_css_post_id;
+ }
+
+ /**
+ * Get the current revision of the original safecss record
+ *
+ * @return object
+ */
+ static function get_current_revision() {
+ $safecss_post = Jetpack_Custom_CSS::get_post();
+
+ if ( empty( $safecss_post ) ) {
+ return false;
+ }
+
+ $revisions = wp_get_post_revisions( $safecss_post['ID'], array( 'posts_per_page' => 1, 'orderby' => 'date', 'order' => 'DESC' ) );
+
+ // Empty array if no revisions exist
+ if ( empty( $revisions ) ) {
+ // Return original post
+ return $safecss_post;
+ } else {
+ // Return the first entry in $revisions, this will be the current revision
+ $current_revision = get_object_vars( array_shift( $revisions ) );
+ return $current_revision;
+ }
+ }
+
+ /**
+ * Save new revision of CSS
+ * Checks to see if content was modified before really saving
+ *
+ * @param string $css
+ * @param bool $is_preview
+ * @return bool|int If nothing was saved, returns false. If a post
+ * or revision was saved, returns the post ID.
+ */
+ static function save_revision( $css, $is_preview = false, $preprocessor = '' ) {
+ $safecss_post = Jetpack_Custom_CSS::get_post();
+
+ $compressed_css = Jetpack_Custom_CSS::minify( $css, $preprocessor );
+
+ // If null, there was no original safecss record, so create one
+ if ( null == $safecss_post ) {
+ if ( ! $css )
+ return false;
+
+ $post = array();
+ $post['post_content'] = $css;
+ $post['post_title'] = 'safecss';
+ $post['post_status'] = 'publish';
+ $post['post_type'] = 'safecss';
+ $post['post_content_filtered'] = $compressed_css;
+
+ // Set excerpt to current theme, for display in revisions list
+ if ( function_exists( 'wp_get_theme' ) ) {
+ $current_theme = wp_get_theme();
+ $post['post_excerpt'] = $current_theme->Name;
+ }
+ else {
+ $post['post_excerpt'] = get_current_theme();
+ }
+
+ // Insert the CSS into wp_posts
+ $post_id = wp_insert_post( $post );
+ wp_cache_set( 'custom_css_post_id', $post_id );
+ return $post_id;
+ }
+
+ // Update CSS in post array with new value passed to this function
+ $safecss_post['post_content'] = $css;
+ $safecss_post['post_content_filtered'] = $compressed_css;
+
+ // Set excerpt to current theme, for display in revisions list
+ if ( function_exists( 'wp_get_theme' ) ) {
+ $current_theme = wp_get_theme();
+ $safecss_post['post_excerpt'] = $current_theme->Name;
+ }
+ else {
+ $safecss_post['post_excerpt'] = get_current_theme();
+ }
+
+ // Don't carry over last revision's timestamps, otherwise revisions all have matching timestamps
+ unset( $safecss_post['post_date'] );
+ unset( $safecss_post['post_date_gmt'] );
+ unset( $safecss_post['post_modified'] );
+ unset( $safecss_post['post_modified_gmt'] );
+
+ // Do not update post if we are only saving a preview
+ if ( false === $is_preview ) {
+ $post_id = wp_update_post( $safecss_post );
+ wp_cache_set( 'custom_css_post_id', $post_id );
+ return $post_id;
+ }
+ else if ( ! defined( 'DOING_MIGRATE' ) ) {
+ return _wp_put_post_revision( $safecss_post );
+ }
+ }
+
+ static function skip_stylesheet() {
+ if ( Jetpack_Custom_CSS::is_customizer_preview() ) {
+ return false;
+ }
+ else {
+ if ( Jetpack_Custom_CSS::is_preview() ) {
+ $safecss_post = Jetpack_Custom_CSS::get_current_revision();
+
+ return (bool) ( get_option( 'safecss_preview_add' ) == 'no' || get_post_meta( $safecss_post['ID'], 'custom_css_add', true ) == 'no' );
+ }
+ else {
+ $custom_css_post_id = Jetpack_Custom_CSS::post_id();
+
+ return (bool) ( get_option( 'safecss_add' ) == 'no' || ( $custom_css_post_id && get_post_meta( $custom_css_post_id, 'custom_css_add', true ) == 'no' ) );
+ }
+ }
+ }
+
+ static function is_preview() {
+ return isset( $_GET['csspreview'] ) && $_GET['csspreview'] === 'true';
+ }
+
+ /*
+ * False when the site has the Custom Design upgrade.
+ * Used only on WordPress.com.
+ */
+ static function is_freetrial() {
+ return apply_filters( 'safecss_is_freetrial', false );
+ }
+
+ static function get_css( $compressed = false ) {
+ $default_css = apply_filters( 'safecss_get_css_error', false );
+
+ if ( $default_css !== false )
+ return $default_css;
+
+ $option = ( Jetpack_Custom_CSS::is_preview() || Jetpack_Custom_CSS::is_freetrial() ) ? 'safecss_preview' : 'safecss';
+
+ if ( 'safecss' == $option ) {
+ if ( get_option( 'safecss_revision_migrated' ) ) {
+ $safecss_post = Jetpack_Custom_CSS::get_post();
+ $css = ( $compressed && $safecss_post['post_content_filtered'] ) ? $safecss_post['post_content_filtered'] : $safecss_post['post_content'];
+ } else {
+ $current_revision = Jetpack_Custom_CSS::get_current_revision();
+ if ( false === $current_revision ) {
+ $css = '';
+ } else {
+ $css = ( $compressed && $current_revision['post_content_filtered'] ) ? $current_revision['post_content_filtered'] : $current_revision['post_content'];
+ }
+ }
+
+ // Fix for un-migrated Custom CSS
+ if ( empty( $safecss_post ) ) {
+ $_css = get_option( 'safecss' );
+ if ( !empty( $_css ) ) {
+ $css = $_css;
+ }
+ }
+ }
+ else if ( 'safecss_preview' == $option ) {
+ $safecss_post = Jetpack_Custom_CSS::get_current_revision();
+ $css = $safecss_post['post_content'];
+ $css = stripslashes( $css );
+ $css = Jetpack_Custom_CSS::minify( $css, get_post_meta( $safecss_post['ID'], 'custom_css_preprocessor', true ) );
+ }
+
+ $css = str_replace( array( '\\\00BB \\\0020', '\0BB \020', '0BB 020' ), '\00BB \0020', $css );
+
+ if ( empty( $css ) ) {
+ $css = "/*\n"
+ . wordwrap(
+ apply_filters(
+ 'safecss_default_css',
+ __(
+ "Welcome to Custom CSS!\n\nCSS (Cascading Style Sheets) is a kind of code that tells the browser how to render a web page. You may delete these comments and get started with your customizations.\n\nBy default, your stylesheet will be loaded after the theme stylesheets, which means that your rules can take precedence and override the theme CSS rules. Just write here what you want to change, you don't need to copy all your theme's stylesheet content.",
+ 'jetpack'
+ )
+ )
+ )
+ . "\n*/";
+ }
+
+ $css = apply_filters( 'safecss_css', $css );
+
+ return $css;
+ }
+
+ static function print_css() {
+ do_action( 'safecss_print_pre' );
+
+ echo Jetpack_Custom_CSS::get_css( true );
+ }
+
+ static function link_tag() {
+ global $blog_id, $current_blog;
+
+ if ( apply_filters( 'safecss_style_error', false ) )
+ return;
+
+ if ( ! is_super_admin() && isset( $current_blog ) && ( 1 == $current_blog->spam || 1 == $current_blog->deleted ) )
+ return;
+
+ if ( Jetpack_Custom_CSS::is_customizer_preview() )
+ return;
+
+ $css = '';
+ $option = Jetpack_Custom_CSS::is_preview() ? 'safecss_preview' : 'safecss';
+
+ if ( 'safecss' == $option ) {
+ if ( get_option( 'safecss_revision_migrated' ) ) {
+ $safecss_post = Jetpack_Custom_CSS::get_post();
+
+ if ( ! empty( $safecss_post['post_content'] ) ) {
+ $css = $safecss_post['post_content'];
+ }
+ } else {
+ $current_revision = Jetpack_Custom_CSS::get_current_revision();
+
+ if ( ! empty( $current_revision['post_content'] ) ) {
+ $css = $current_revision['post_content'];
+ }
+ }
+
+ // Fix for un-migrated Custom CSS
+ if ( empty( $safecss_post ) ) {
+ $_css = get_option( 'safecss' );
+ if ( !empty( $_css ) ) {
+ $css = $_css;
+ }
+ }
+ }
+
+ if ( 'safecss_preview' == $option ) {
+ $safecss_post = Jetpack_Custom_CSS::get_current_revision();
+
+ if ( !empty( $safecss_post['post_content'] ) ) {
+ $css = $safecss_post['post_content'];
+ }
+ }
+
+ $css = str_replace( array( '\\\00BB \\\0020', '\0BB \020', '0BB 020' ), '\00BB \0020', $css );
+
+ if ( $css == '' )
+ return;
+
+ $href = trailingslashit( site_url() );
+ $href = add_query_arg( 'custom-css', 1, $href );
+ $href = add_query_arg( 'csblog', $blog_id, $href );
+ $href = add_query_arg( 'cscache', 6, $href );
+ $href = add_query_arg( 'csrev', (int) get_option( $option . '_rev' ), $href );
+
+ $href = apply_filters( 'safecss_href', $href, $blog_id );
+
+ if ( Jetpack_Custom_CSS::is_preview() )
+ $href = add_query_arg( 'csspreview', 'true', $href );
+
+ ?>
+ <link rel="stylesheet" id="custom-css-css" type="text/css" href="<?php echo esc_url( $href ); ?>" />
+ <?php
+ }
+
+ static function style_filter( $current ) {
+ if ( Jetpack_Custom_CSS::is_freetrial() && ( ! Jetpack_Custom_CSS::is_preview() || ! current_user_can( 'switch_themes' ) ) )
+ return $current;
+ else if ( Jetpack_Custom_CSS::skip_stylesheet() )
+ return apply_filters( 'safecss_style_filter_url', plugins_url( 'custom-css/blank.css', __FILE__ ) );
+
+ return $current;
+ }
+
+ static function buffer( $html ) {
+ $html = str_replace( '</body>', Jetpack_Custom_CSS::preview_flag(), $html );
+ return preg_replace_callback( '!href=([\'"])(.*?)\\1!', array( 'Jetpack_Custom_CSS', 'preview_links' ), $html );
+ }
+
+ static function preview_links( $matches ) {
+ if ( 0 !== strpos( $matches[2], get_option( 'home' ) ) )
+ return $matches[0];
+
+ $link = wp_specialchars_decode( $matches[2] );
+ $link = add_query_arg( 'csspreview', 'true', $link );
+ $link = esc_url( $link );
+ return "href={$matches[1]}$link{$matches[1]}";
+ }
+
+ /**
+ * Places a black bar above every preview page
+ */
+ static function preview_flag() {
+ if ( is_admin() )
+ return;
+
+ $message = esc_html__( 'Preview: changes must be saved or they will be lost', 'jetpack' );
+ $message = apply_filters( 'safecss_preview_message', $message );
+
+ $preview_flag_js = "var flag = document.createElement('div');
+ flag.innerHTML = " . json_encode( $message ) . ";
+ flag.style.background = 'black';
+ flag.style.color = 'white';
+ flag.style.textAlign = 'center';
+ flag.style.fontSize = '15px';
+ flag.style.padding = '1px';
+ document.body.style.paddingTop = '32px';
+ document.body.insertBefore(flag, document.body.childNodes[0]);
+ ";
+
+ $preview_flag_js = apply_filters( 'safecss_preview_flag_js', $preview_flag_js );
+ if ( $preview_flag_js ) {
+ $preview_flag_js = '<script type="text/javascript">
+ // <![CDATA[
+ ' . $preview_flag_js . '
+ // ]]>
+ </script>';
+ }
+
+ return $preview_flag_js;
+ }
+
+ static function menu() {
+ $parent = 'themes.php';
+ $title = __( 'Edit CSS', 'jetpack' );
+ $hook = add_theme_page( $title, $title, 'edit_theme_options', 'editcss', array( 'Jetpack_Custom_CSS', 'admin' ) );
+ add_action( "admin_print_scripts-$hook", array( 'Jetpack_Custom_CSS', 'enqueue_scripts' ) );
+ add_action( "admin_head-$hook", array( 'Jetpack_Custom_CSS', 'admin_head' ) );
+ add_action( "load-revision.php", array( 'Jetpack_Custom_CSS', 'prettify_post_revisions' ) );
+ add_action( "load-$hook", array( 'Jetpack_Custom_CSS', 'update_title' ) );
+ }
+
+ /**
+ * Adds a menu item in the appearance section for this plugin's administration
+ * page. Also adds hooks to enqueue the CSS and JS for the admin page.
+ */
+ static function update_title() {
+ global $title;
+ $title = __( 'CSS', 'jetpack' );
+ }
+
+ static function prettify_post_revisions() {
+ add_filter( 'the_title', array( 'Jetpack_Custom_CSS', 'post_title' ), 10, 2 );
+ add_action( 'admin_head', array( 'Jetpack_Custom_CSS', 'remove_title_excerpt_from_revisions' ) );
+ }
+
+ static function remove_title_excerpt_from_revisions() {
+ global $post;
+
+ if ( !$post ) {
+ return;
+ }
+
+ if ( 'safecss' != $post->post_type ) {
+ return;
+ }
+ ?>
+ <style type="text/css">
+ #revision-field-post_title, #revision-field-post_excerpt {
+ display: none;
+ }
+ </style>
+ <?php
+ }
+
+ static function post_title( $title, $post_id ) {
+ if ( !$post_id = (int) $post_id ) {
+ return $title;
+ }
+
+ if ( !$post = get_post( $post_id ) ) {
+ return $title;
+ }
+
+ if ( 'safecss' != $post->post_type ) {
+ return $title;
+ }
+
+ return __( 'Custom CSS Stylesheet', 'jetpack' );
+ }
+
+ static function enqueue_scripts() {
+ wp_enqueue_script( 'postbox' );
+
+ if ( defined( 'SAFECSS_USE_ACE' ) && SAFECSS_USE_ACE ) {
+ $url = plugins_url( 'custom-css/js/', __FILE__ );
+ wp_enqueue_script( 'jquery.spin' );
+ wp_enqueue_script( 'safecss-ace', $url . 'ace/ace.js', array(), '20130213', true );
+ wp_enqueue_script( 'safecss-ace-css', $url . 'ace/mode-css.js', array( 'safecss-ace' ), '20130213', true );
+ wp_enqueue_script( 'safecss-ace-use', $url . 'safecss-ace.js', array( 'jquery', 'safecss-ace-css' ), '20130213', true );
+ }
+ }
+
+ static function admin_head() {
+ ?>
+ <style type="text/css">
+ #safecssform {
+ position: relative;
+ }
+
+ #poststuff {
+ padding-top: 0;
+ }
+
+ #safecss {
+ min-height: 250px;
+ width: 100%;
+ }
+
+ .misc-pub-section > span {
+ font-weight: bold;
+ }
+
+ .misc-pub-section > div {
+ margin-top: 3px;
+ }
+
+ <?php
+
+ if ( defined( 'SAFECSS_USE_ACE' ) && SAFECSS_USE_ACE ) {
+
+ ?>
+ #safecss-container {
+ position: relative;
+ width: 99.5%;
+ height: 400px;
+ border: 1px solid #dfdfdf;
+ border-radius: 3px;
+ }
+
+ #safecss-container .ace_editor {
+ font-family: Consolas, Monaco, Courier, monospace;
+ }
+
+ #safecss-ace {
+ width: 100%;
+ height: 100%;
+ display: none; /* Hide on load otherwise it looks weird */
+ }
+
+ #safecss-ace.ace_editor {
+ display: block;
+ }
+
+ #safecss-container .ace-tm .ace_gutter {
+ background-color: #ededed;
+ }
+ <?php
+ }
+
+ ?>
+ </style>
+ <script type="text/javascript">
+ /*<![CDATA[*/
+ var safecssResize, safecssInit;
+
+ <?php
+
+ if ( defined( 'SAFECSS_USE_ACE' ) && SAFECSS_USE_ACE ) {
+ ?>var safecssAceSrcPath = <?php echo json_encode( parse_url( plugins_url( 'custom-css/js/ace/', __FILE__ ), PHP_URL_PATH ) ); ?>;<?php
+ }
+
+ ?>
+
+ ( function ( $ ) {
+ var safe, win;
+
+ safecssResize = function () {
+ safe.height( win.height() - safe.offset().top - 250 );
+ };
+
+ safecssInit = function() {
+ safe = $('#safecss');
+ win = $(window);
+
+ postboxes.add_postbox_toggles('editcss');
+ safecssResize();
+ var button = document.getElementById( 'preview' );
+ button.onclick = function ( event ) {
+ <?php
+
+ // hack for now for previewing.
+ // TODO: move all of this JS into its own file.
+ if ( defined( 'SAFECSS_USE_ACE' ) && SAFECSS_USE_ACE ) { echo "\t\taceSyncCSS();\n"; }
+
+ ?>
+ document.forms["safecssform"].target = "csspreview";
+ document.forms["safecssform"].action.value = 'preview';
+ document.forms["safecssform"].submit();
+ document.forms["safecssform"].target = "";
+ document.forms["safecssform"].action.value = 'save';
+
+ event = event || window.event;
+
+ if ( event.preventDefault )
+ event.preventDefault();
+
+ return false;
+ }
+ };
+
+ window.onresize = safecssResize;
+ addLoadEvent( safecssInit );
+ } )( jQuery );
+
+ jQuery( function ( $ ) {
+ $( '.edit-preprocessor' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#preprocessor-select' ).slideDown();
+ $( this ).hide();
+ } );
+
+ $( '.cancel-preprocessor' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#preprocessor-select' ).slideUp( function () {
+ $( '.edit-preprocessor' ).show();
+ $( '#preprocessor_choices' ).val( $( '#custom_css_preprocessor' ).val() );
+ } );
+ } );
+
+ $( '.save-preprocessor' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#preprocessor-select' ).slideUp();
+ $( '#preprocessor-display' ).text( $( '#preprocessor_choices option:selected' ).text() );
+ $( '#custom_css_preprocessor' ).val( $( '#preprocessor_choices' ).val() );
+ $( '.edit-preprocessor' ).show();
+ } );
+ } );
+ /*]]>*/
+ </script>
+ <?php
+ }
+
+ static function saved_message() {
+ echo '<div id="message" class="updated fade"><p><strong>' . __( 'Stylesheet saved.', 'jetpack' ) . '</strong></p></div>';
+ }
+
+ static function admin() {
+ add_meta_box( 'submitdiv', __( 'Publish', 'jetpack' ), array( __CLASS__, 'publish_box' ), 'editcss', 'side' );
+
+ $safecss_post = Jetpack_Custom_CSS::get_post();
+
+ if ( ! empty( $safecss_post ) && 0 < $safecss_post['ID'] && wp_get_post_revisions( $safecss_post['ID'] ) )
+ add_meta_box( 'revisionsdiv', __( 'CSS Revisions', 'jetpack' ), array( __CLASS__, 'revisions_meta_box' ), 'editcss', 'side' );
+
+ ?>
+ <div class="wrap columns-2">
+ <?php do_action( 'custom_design_header' ); ?>
+ <h2><?php _e( 'CSS Stylesheet Editor', 'jetpack' ); ?></h2>
+ <form id="safecssform" action="" method="post">
+ <?php wp_nonce_field( 'safecss' ) ?>
+ <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
+ <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
+ <input type="hidden" name="action" value="save" />
+ <div id="poststuff" class="metabox-holder has-right-sidebar">
+ <p class="css-support"><?php echo apply_filters( 'safecss_intro_text', __( 'New to CSS? Start with a <a href="http://www.htmldog.com/guides/cssbeginner/">beginner tutorial</a>. Questions?
+ Ask in the <a href="http://wordpress.org/support/forum/themes-and-templates">Themes and Templates forum</a>.', 'jetpack' ) ); ?></p>
+ <div id="postbox-container-1" class="inner-sidebar">
+ <?php do_meta_boxes( 'editcss', 'side', $safecss_post ); ?>
+ </div>
+ <div id="post-body">
+ <div id="post-body-content">
+ <div class="postarea">
+ <?php if ( defined( 'SAFECSS_USE_ACE' ) && SAFECSS_USE_ACE ) { ?>
+ <div id="safecss-container">
+ <div id="safecss-ace"></div>
+ </div>
+ <script type="text/javascript">
+ jQuery.fn.spin && jQuery("#safecss-container").spin( 'large' );
+ </script>
+ <textarea id="safecss" name="safecss" class="hide-if-js"><?php echo esc_textarea( Jetpack_Custom_CSS::get_css() ); ?></textarea>
+ <div class="clear"></div>
+ <?php } else { ?>
+ <p><textarea id="safecss" name="safecss"><?php echo str_replace('</textarea>', '&lt;/textarea&gt', Jetpack_Custom_CSS::get_css()); ?></textarea></p>
+ <?php } ?>
+ </div>
+ </div>
+ </div>
+ <br class="clear" />
+ </div>
+ </form>
+ </div>
+ <?php
+ }
+
+ static function publish_box() {
+ ?>
+ <div id="minor-publishing">
+ <div id="misc-publishing-actions">
+ <?php
+
+ $preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
+
+ if ( ! empty( $preprocessors ) ) {
+ $safecss_post = Jetpack_Custom_CSS::get_current_revision();
+ $selected_preprocessor_key = get_post_meta( $safecss_post['ID'], 'custom_css_preprocessor', true );
+ $selected_preprocessor = isset( $preprocessors[$selected_preprocessor_key] ) ? $preprocessors[$selected_preprocessor_key] : null;
+
+ ?>
+ <div class="misc-pub-section">
+ <label><?php esc_html_e( 'Preprocessor:', 'jetpack' ); ?></label>
+ <span id="preprocessor-display"><?php echo esc_html( $selected_preprocessor ? $selected_preprocessor['name'] : __( 'None', 'jetpack' ) ); ?></span>
+ <a class="edit-preprocessor hide-if-no-js" href="#preprocessor"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
+ <div id="preprocessor-select" class="hide-if-js">
+ <input type="hidden" name="custom_css_preprocessor" id="custom_css_preprocessor" value="<?php echo esc_attr( $selected_preprocessor_key ); ?>" />
+ <select id="preprocessor_choices">
+ <option value=""><?php esc_html_e( 'None', 'jetpack' ); ?></option>
+ <?php
+
+ foreach ( $preprocessors as $preprocessor_key => $preprocessor ) {
+ ?>
+ <option value="<?php echo esc_attr( $preprocessor_key ); ?>" <?php selected( $selected_preprocessor_key, $preprocessor_key ); ?>><?php echo esc_html( $preprocessor['name'] ); ?></option>
+ <?php
+ }
+
+ ?>
+ </select>
+ <a class="save-preprocessor hide-if-no-js button" href="#preprocessor"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
+ <a class="cancel-preprocessor hide-if-no-js" href="#preprocessor"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
+ </div>
+ </div>
+ <?php
+ }
+
+ $safecss_post = Jetpack_Custom_CSS::get_current_revision();
+
+ $add_css = ( get_post_meta( $safecss_post['ID'], 'custom_css_add', true ) != 'no' );
+
+ ?>
+ <div class="misc-pub-section">
+ <label><?php esc_html_e( 'Mode:', 'jetpack' ); ?></label>
+ <span id="css-mode-display"><?php echo esc_html( $add_css ? __( 'Add-on', 'jetpack' ) : __( 'Replacement', 'jetpack' ) ); ?></span>
+ <a class="edit-css-mode hide-if-no-js" href="#css-mode"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
+ <div id="css-mode-select" class="hide-if-js">
+ <input type="hidden" name="add_to_existing" id="add_to_existing" value="<?php echo $add_css ? 'true' : 'false'; ?>" />
+ <p>
+ <label>
+ <input type="radio" name="add_to_existing_display" value="true" <?php checked( $add_css ); ?>/>
+ <?php _e( 'Add-on CSS <b>(Recommended)</b>', 'jetpack' ); ?>
+ </label>
+ <br />
+ <label>
+ <input type="radio" name="add_to_existing_display" value="false" <?php checked( ! $add_css ); ?>/>
+ <?php printf( __( 'Replace <a href="%s">theme\'s CSS</a> <b>(Advanced)</b>', 'jetpack' ), apply_filters( 'safecss_theme_stylesheet_url', get_stylesheet_uri() ) ); ?>
+ </label>
+ </p>
+ <a class="save-css-mode hide-if-no-js button" href="#css-mode"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
+ <a class="cancel-css-mode hide-if-no-js" href="#css-mode"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
+ </div>
+ <script type="text/javascript">
+ jQuery( function ( $ ) {
+ $( '.edit-css-mode' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#css-mode-select' ).slideDown();
+ $( this ).hide();
+ } );
+
+ $( '.cancel-css-mode' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#css-mode-select' ).slideUp( function () {
+ $( '.edit-css-mode' ).show();
+ $( 'input[name=add_to_existing_display][value=' + $( '#add_to_existing' ).val() + ']' ).attr( 'checked', true );
+ } );
+ } );
+
+ $( '.save-css-mode' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#css-mode-select' ).slideUp();
+ $( '#css-mode-display' ).text( $( 'input[name=add_to_existing_display]:checked' ).val() == 'true' ? 'Add-on' : 'Replacement' );
+ $( '#add_to_existing' ).val( $( 'input[name=add_to_existing_display]:checked' ).val() );
+ $( '.edit-css-mode' ).show();
+ } );
+ } );
+ </script>
+ </div>
+ <?php do_action( 'custom_css_submitbox_misc_actions' ); ?>
+ </div>
+ </div>
+ <div id="major-publishing-actions">
+ <input type="button" class="button" id="preview" name="preview" value="<?php esc_attr_e( 'Preview', 'jetpack' ) ?>" />
+ <div id="publishing-action">
+ <input type="submit" class="button-primary" id="save" name="save" value="<?php ( Jetpack_Custom_CSS::is_freetrial() ) ? esc_attr_e( 'Save &amp; Buy Upgrade', 'jetpack' ) : esc_attr_e( 'Save Stylesheet', 'jetpack' ); ?>" />
+ </div>
+ </div>
+ <?php
+ }
+
+ /**
+ * Render metabox listing CSS revisions and the themes that correspond to the revisions.
+ * Called by afecss_admin *
+ * @param array $safecss_post
+ * @global $post
+ * @uses WP_Query, wp_post_revision_title, esc_html, add_query_arg, menu_page_url, wp_reset_query
+ * @return string
+ */
+ static function revisions_meta_box( $safecss_post ) {
+ $max_revisions = defined( 'WP_POST_REVISIONS' ) && is_numeric( WP_POST_REVISIONS ) ? (int) WP_POST_REVISIONS : 25;
+ $posts_per_page = isset( $_GET['show_all_rev'] ) ? $max_revisions : 6;
+
+ $revisions = new WP_Query( array(
+ 'posts_per_page' => $posts_per_page,
+ 'post_type' => 'revision',
+ 'post_status' => 'inherit',
+ 'post_parent' => $safecss_post['ID'],
+ 'orderby' => 'date',
+ 'order' => 'DESC'
+ ) );
+
+ if ( $revisions->have_posts() ) { ?>
+ <ul class="post-revisions"><?php
+
+ global $post;
+
+ while ( $revisions->have_posts() ) :
+ $revisions->the_post();
+
+ ?><li>
+ <?php
+ echo wp_post_revision_title( $post );
+
+ if ( ! empty( $post->post_excerpt ) )
+ echo ' (' . esc_html( $post->post_excerpt ) . ')';
+ ?>
+ </li><?php
+
+ endwhile;
+
+ ?></ul><?php
+
+ if ( $revisions->found_posts > 6 ) {
+ ?>
+ <br>
+ <a href="<?php echo add_query_arg( 'show_all_rev', 'true', menu_page_url( 'editcss', false ) ); ?>"><?php esc_html_e( 'Show more', 'jetpack' ); ?></a>
+ <?php
+ }
+ }
+
+ wp_reset_query();
+ }
+
+ /**
+ * Hook in init at priority 11 to disable custom CSS.
+ */
+ static function disable() {
+ remove_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
+ remove_filter( 'stylesheet_uri', array( 'Jetpack_Custom_CSS', 'style_filter' ) );
+ }
+
+ /**
+ * Reset all aspects of Custom CSS on a theme switch so that changing
+ * themes is a sure-fire way to get a clean start.
+ */
+ static function reset() {
+ $safecss_post_id = Jetpack_Custom_CSS::save_revision( '' );
+ $safecss_revision = Jetpack_Custom_CSS::get_current_revision();
+
+ update_option( 'safecss_rev', intval( get_option( 'safecss_rev' ) ) + 1 );
+
+ update_post_meta( $safecss_post_id, 'custom_css_add', 'yes' );
+ update_post_meta( $safecss_post_id, 'content_width', false );
+ update_post_meta( $safecss_post_id, 'custom_css_preprocessor', '' );
+ update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', 'yes' );
+ update_metadata( 'post', $safecss_revision['ID'], 'content_width', false );
+ update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', '' );
+ }
+
+ static function is_customizer_preview() {
+ if ( isset ( $GLOBALS['wp_customize'] ) )
+ return ! $GLOBALS['wp_customize']->is_theme_active();
+
+ return false;
+ }
+
+ static function minify( $css, $preprocessor = '' ) {
+ if ( ! $css )
+ return '';
+
+ if ( $preprocessor ) {
+ $preprocessors = apply_filters( 'jetpack_custom_css_preprocessors', array() );
+
+ if ( isset( $preprocessors[$preprocessor] ) ) {
+ $css = call_user_func( $preprocessors[$preprocessor]['callback'], $css );
+ }
+ }
+
+ safecss_class();
+ $csstidy = new csstidy();
+ $csstidy->optimise = new safecss( $csstidy );
+
+ $csstidy->set_cfg( 'remove_bslash', false );
+ $csstidy->set_cfg( 'compress_colors', true );
+ $csstidy->set_cfg( 'compress_font-weight', true );
+ $csstidy->set_cfg( 'remove_last_;', true );
+ $csstidy->set_cfg( 'case_properties', true );
+ $csstidy->set_cfg( 'discard_invalid_properties', true );
+ $csstidy->set_cfg( 'css_level', 'CSS3.0' );
+ $csstidy->set_cfg( 'template', 'highest');
+ $csstidy->parse( $css );
+
+ return $csstidy->print->plain();
+ }
+
+ /**
+ * When restoring a SafeCSS post revision, also copy over the
+ * content_width and custom_css_add post metadata.
+ */
+ static function restore_revision( $_post_id, $_revision_id ) {
+ $_post = get_post( $_post_id );
+
+ if ( 'safecss' != $_post->post_type )
+ return;
+
+ $safecss_revision = Jetpack_Custom_CSS::get_current_revision();
+
+ $content_width = get_post_meta( $_revision_id, 'content_width', true );
+ $custom_css_add = get_post_meta( $_revision_id, 'custom_css_add', true );
+ $preprocessor = get_post_meta( $_revision_id, 'custom_css_preprocessor', true );
+
+ update_metadata( 'post', $safecss_revision['ID'], 'content_width', $content_width );
+ update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', $custom_css_add );
+ update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', $preprocessor );
+ update_post_meta( $_post->ID, 'content_width', $content_width );
+ update_post_meta( $_post->ID, 'custom_css_add', $custom_css_add );
+ update_post_meta( $_post->ID, 'custom_css_preprocessor', $preprocessor );
+ }
+
+ /**
+ * Migration routine for moving safecss from wp_options to wp_posts to support revisions
+ *
+ * @return void
+ */
+ static function upgrade() {
+ $css = get_option( 'safecss' );
+
+ // Check if CSS is stored in wp_options
+ if ( $css ) {
+ // Remove the async actions from publish_post
+ remove_action( 'publish_post', 'queue_publish_post' );
+
+ $post = array();
+ $post['post_content'] = $css;
+ $post['post_title'] = 'safecss';
+ $post['post_status'] = 'publish';
+ $post['post_type'] = 'safecss';
+
+ // Insert the CSS into wp_posts
+ $post_id = wp_insert_post( $post );
+ // Check for errors
+ if ( !$post_id or is_wp_error( $post_id ) )
+ die( $post_id->get_error_message() );
+
+ // Delete safecss option
+ delete_option( 'safecss' );
+ }
+
+ unset( $css );
+
+ // Check if we have already done this
+ if ( !get_option( 'safecss_revision_migrated' ) ) {
+ define( 'DOING_MIGRATE', true );
+
+ // Get hashes of safecss post and current revision
+ $safecss_post = Jetpack_Custom_CSS::get_post();
+
+ if ( empty( $safecss_post ) )
+ return;
+
+ $safecss_post_hash = md5( $safecss_post['post_content'] );
+ $current_revision = Jetpack_Custom_CSS::get_current_revision();
+
+ if ( null == $current_revision )
+ return;
+
+ $current_revision_hash = md5( $current_revision['post_content'] );
+
+ // If hashes are not equal, set safecss post with content from current revision
+ if ( $safecss_post_hash !== $current_revision_hash ) {
+ Jetpack_Custom_CSS::save_revision( $current_revision['post_content'] );
+ // Reset post_content to display the migrated revsion
+ $safecss_post['post_content'] = $current_revision['post_content'];
+ }
+
+ // Set option so that we dont keep doing this
+ update_option( 'safecss_revision_migrated', time() );
+ }
+
+ $newest_safecss_post = Jetpack_Custom_CSS::get_current_revision();
+
+ if ( $newest_safecss_post ) {
+ if ( get_option( 'safecss_content_width' ) ) {
+ // Add the meta to the post and the latest revision.
+ update_post_meta( $newest_safecss_post['ID'], 'content_width', get_option( 'safecss_content_width' ) );
+ update_metadata( 'post', $newest_safecss_post['ID'], 'content_width', get_option( 'safecss_content_width' ) );
+
+ delete_option( 'safecss_content_width' );
+ }
+
+ if ( get_option( 'safecss_add' ) ) {
+ update_post_meta( $newest_safecss_post['ID'], 'custom_css_add', get_option( 'safecss_add' ) );
+ update_metadata( 'post', $newest_safecss_post['ID'], 'custom_css_add', get_option( 'safecss_add' ) );
+
+ delete_option( 'safecss_add' );
+ }
+ }
+ }
+
+ static function revision_redirect( $redirect ) {
+ global $post;
+
+ if ( 'safecss' == $post->post_type ) {
+ if ( strstr( $redirect, 'action=edit' ) ) {
+ return 'themes.php?page=editcss';
+ }
+
+ if ( 'edit.php' == $redirect ) {
+ return '';
+ }
+ }
+
+ return $redirect;
+ }
+
+ static function revision_post_link( $post_link, $post_id, $context ) {
+ if ( !$post_id = (int) $post_id ) {
+ return $post_link;
+ }
+
+ if ( !$post = get_post( $post_id ) ) {
+ return $post_link;
+ }
+
+ if ( 'safecss' != $post->post_type ) {
+ return $post_link;
+ }
+
+ $post_link = admin_url( 'themes.php?page=editcss' );
+
+ if ( 'display' == $context ) {
+ return esc_url( $post_link );
+ }
+
+ return esc_url_raw( $post_link );
+ }
+}
+
+class Jetpack_Safe_CSS {
+ static function filter_attr( $css, $element = 'div' ) {
+ safecss_class();
+
+ $css = $element . ' {' . $css . '}';
+
+ $csstidy = new csstidy();
+ $csstidy->optimise = new safecss( $csstidy );
+ $csstidy->set_cfg( 'remove_bslash', false );
+ $csstidy->set_cfg( 'compress_colors', false );
+ $csstidy->set_cfg( 'compress_font-weight', false );
+ $csstidy->set_cfg( 'discard_invalid_properties', true );
+ $csstidy->set_cfg( 'merge_selectors', false );
+ $csstidy->set_cfg( 'remove_last_;', false );
+ $csstidy->set_cfg( 'css_level', 'CSS3.0' );
+
+ $css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $css );
+ $css = wp_kses_split( $css, array(), array() );
+ $csstidy->parse( $css );
+
+ $css = $csstidy->print->plain();
+
+ $css = str_replace( array( "\n","\r","\t" ), '', $css );
+
+ preg_match( "/^{$element}\s*{(.*)}\s*$/", $css, $matches );
+
+ if ( empty( $matches[1] ) )
+ return '';
+
+ return $matches[1];
+ }
+}
+
+function migrate() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::upgrade()' );
+
+ return Jetpack_Custom_CSS::upgrade();
+}
+
+function safecss_revision_redirect( $redirect ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revision_redirect()' );
+
+ return Jetpack_Custom_CSS::revision_redirect( $redirect );
+}
+
+function safecss_revision_post_link( $post_link, $post_id, $context ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revision_post_link()' );
+
+ return Jetpack_Custom_CSS::revision_post_link( $post_link, $post_id, $context );
+}
+
+function get_safecss_post() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_post()' );
+
+ return Jetpack_Custom_CSS::get_post();
+}
+
+function custom_css_post_id() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::post_id()' );
+
+ return Jetpack_Custom_CSS::post_id();
+}
+
+function get_current_revision() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_current_revision()' );
+
+ return Jetpack_Custom_CSS::get_current_revision();
+}
+
+function save_revision( $css, $is_preview = false, $preprocessor = '' ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::save_revision()' );
+
+ return Jetpack_Custom_CSS::save_revision( $css, $is_preview, $preprocessor );
+}
+
+function safecss_skip_stylesheet() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::skip_stylesheet()' );
+
+ return Jetpack_Custom_CSS::skip_stylesheet();
+}
+
+function safecss_init() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::init()' );
+
+ return Jetpack_Custom_CSS::init();
+}
+
+function safecss_is_preview() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_preview()' );
+
+ return Jetpack_Custom_CSS::is_preview();
+}
+
+function safecss_is_freetrial() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_freetrial()' );
+
+ return Jetpack_Custom_CSS::is_freetrial();
+}
+
+function safecss( $compressed = false ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::get_css()' );
+
+ return Jetpack_Custom_CSS::get_css( $compressed );
+}
+
+function safecss_print() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::print_css()' );
+
+ return Jetpack_Custom_CSS::print_css();
+}
+
+function safecss_style() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::link_tag()' );
+
+ return Jetpack_Custom_CSS::link_tag();
+}
+
+function safecss_style_filter( $current ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::style_filter()' );
+
+ return Jetpack_Custom_CSS::style_filter( $current );
+}
+
+function safecss_buffer( $html ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::buffer()' );
+
+ return Jetpack_Custom_CSS::buffer( $html );
+}
+
+function safecss_preview_links( $matches ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::preview_links()' );
+
+ return Jetpack_Custom_CSS::preview_links( $matches );
+}
+
+function safecss_preview_flag() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::preview_flag()' );
+
+ return Jetpack_Custom_CSS::preview_flag();
+}
+
+function safecss_menu() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::menu()' );
+
+ return Jetpack_Custom_CSS::menu();
+}
+
+function update_title() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::update_title()' );
+
+ return Jetpack_Custom_CSS::update_title();
+}
+
+function safecss_prettify_post_revisions() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::prettify_post_revisions()' );
+
+ return Jetpack_Custom_CSS::prettify_post_revisions();
+}
+
+function safecss_remove_title_excerpt_from_revisions() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::remove_title_excerpt_from_revisions()' );
+
+ return Jetpack_Custom_CSS::remove_title_excerpt_from_revisions();
+}
+
+function safecss_post_title( $title, $post_id ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::post_title()' );
+
+ return Jetpack_Custom_CSS::post_title( $title, $post_id );
+}
+
+function safe_css_enqueue_scripts() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::enqueue_scripts()' );
+
+ return Jetpack_Custom_CSS::enqueue_scripts();
+}
+
+function safecss_admin_head() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::admin_head()' );
+
+ return Jetpack_Custom_CSS::admin_head();
+}
+
+function safecss_saved() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::saved_message()' );
+
+ return Jetpack_Custom_CSS::saved_message();
+}
+
+function safecss_admin() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::admin()' );
+
+ return Jetpack_Custom_CSS::admin();
+}
+
+function custom_css_meta_box() {
+ _deprecated_function( __FUNCTION__, '2.1', 'add_meta_box( $id, $title, $callback, \'editcss\', \'side\' )' );
+}
+
+function custom_css_post_revisions_meta_box( $safecss_post ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::revisions_meta_box()' );
+
+ return Jetpack_Custom_CSS::revisions_meta_box( $safecss_post );
+}
+
+function disable_safecss_style() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::disable()' );
+
+ return Jetpack_Custom_CSS::disable();
+}
+
+function custom_css_reset() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::reset()' );
+
+ return Jetpack_Custom_CSS::reset();
+}
+
+function custom_css_is_customizer_preview() {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::is_customizer_preview()' );
+
+ return Jetpack_Custom_CSS::is_customizer_preview();
+}
+
+function custom_css_minify( $css, $preprocessor = '' ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::minify()' );
+
+ return Jetpack_Custom_CSS::minify( $css, $preprocessor );
+}
+
+function custom_css_restore_revision( $_post_id, $_revision_id ) {
+ _deprecated_function( __FUNCTION__, '2.1', 'Jetpack_Custom_CSS::restore_revision()' );
+
+ return Jetpack_Custom_CSS::restore_revision( $_post_id, $_revision_id );;
+}
+
+function safecss_class() {
+ // Wrapped so we don't need the parent class just to load the plugin
+ if ( class_exists('safecss') )
+ return;
+
+ require_once( dirname( __FILE__ ) . '/csstidy/class.csstidy.php' );
+
+ class safecss extends csstidy_optimise {
+ function safecss( &$css ) {
+ return $this->csstidy_optimise( $css );
+ }
+
+ function postparse() {
+ do_action( 'csstidy_optimize_postparse', $this );
+
+ return parent::postparse();
+ }
+
+ function subvalue() {
+ do_action( 'csstidy_optimize_subvalue', $this );
+
+ return parent::subvalue();
+ }
+ }
+}
+
+if ( ! function_exists( 'safecss_filter_attr' ) ) {
+ function safecss_filter_attr( $css, $element = 'div' ) {
+ return Jetpack_Safe_CSS::filter_attr( $css, $element );
+ }
+}
+
+add_action( 'init', array( 'Jetpack_Custom_CSS', 'init' ) );
+
+include dirname( __FILE__ ) . '/custom-css/preprocessors.php'; \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/custom-css/blank.css b/plugins/jetpack/modules/custom-css/custom-css/blank.css
new file mode 100644
index 00000000..79a9626b
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/blank.css
@@ -0,0 +1 @@
+/* */
diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/ace/ace.js b/plugins/jetpack/modules/custom-css/custom-css/js/ace/ace.js
new file mode 100644
index 00000000..520b8fca
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/js/ace/ace.js
@@ -0,0 +1,11 @@
+(function(){function o(e){var i=function(e,t){return r("",e,t)},s=t;e&&(t[e]||(t[e]={}),s=t[e]);if(!s.define||!s.define.packaged)n.original=s.define,s.define=n,s.define.packaged=!0;if(!s.require||!s.require.packaged)r.original=s.require,s.require=i,s.require.packaged=!0}var e="ace",t=function(){return this}();if(!e&&typeof requirejs!="undefined")return;var n=function(e,t,r){if(typeof e!="string"){n.original?n.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(r=t),n.modules||(n.modules={}),n.modules[e]=r},r=function(e,t,n){if(Object.prototype.toString.call(t)==="[object Array]"){var i=[];for(var o=0,u=t.length;o<u;++o){var a=s(e,t[o]);if(!a&&r.original)return r.original.apply(window,arguments);i.push(a)}n&&n.apply(null,i)}else{if(typeof t=="string"){var f=s(e,t);return!f&&r.original?r.original.apply(window,arguments):(n&&n(),f)}if(r.original)return r.original.apply(window,arguments)}},i=function(e,t){if(t.indexOf("!")!==-1){var n=t.split("!");return i(e,n[0])+"!"+i(e,n[1])}if(t.charAt(0)=="."){var r=e.split("/").slice(0,-1).join("/");t=r+"/"+t;while(t.indexOf(".")!==-1&&s!=t){var s=t;t=t.replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return t},s=function(e,t){t=i(e,t);var s=n.modules[t];if(!s)return null;if(typeof s=="function"){var o={},u={id:t,uri:"",exports:o,packaged:!0},a=function(e,n){return r(t,e,n)},f=s(a,o,u);return o=f||u.exports,n.modules[t]=o,o}return s};o(e)})(),ace.define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/multi_select","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/mode/folding/fold_mode","ace/config"],function(e,t,n){e("./lib/fixoldbrowsers");var r=e("./lib/dom"),i=e("./lib/event"),s=e("./editor").Editor,o=e("./edit_session").EditSession,u=e("./undomanager").UndoManager,a=e("./virtual_renderer").VirtualRenderer,f=e("./multi_select").MultiSelect;e("./worker/worker_client"),e("./keyboard/hash_handler"),e("./placeholder"),e("./mode/folding/fold_mode"),t.config=e("./config"),t.require=e,t.edit=function(e){if(typeof e=="string"){var n=e,e=document.getElementById(n);if(!e)throw"ace.edit can't find div #"+n}if(e.env&&e.env.editor instanceof s)return e.env.editor;var o=t.createEditSession(r.getInnerText(e));e.innerHTML="";var u=new s(new a(e));new f(u),u.setSession(o);var l={document:o,editor:u,onResize:u.resize.bind(u)};return i.addListener(window,"resize",l.onResize),e.env=u.env=l,u},t.createEditSession=function(e,t){var n=new o(e,n);return n.setUndoManager(new u),n},t.EditSession=o,t.UndoManager=u}),ace.define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"],function(e,t,n){e("./regexp"),e("./es5-shim")}),ace.define("ace/lib/regexp",["require","exports","module"],function(e,t,n){function o(e){return(e.global?"g":"")+(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":"")}function u(e,t,n){if(Array.prototype.indexOf)return e.indexOf(t,n);for(var r=n||0;r<e.length;r++)if(e[r]===t)return r;return-1}var r={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},i=r.exec.call(/()??/,"")[1]===undefined,s=function(){var e=/^/g;return r.test.call(e,""),!e.lastIndex}();if(s&&i)return;RegExp.prototype.exec=function(e){var t=r.exec.apply(this,arguments),n,a;if(typeof e=="string"&&t){!i&&t.length>1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;e<arguments.length-2;e++)arguments[e]===undefined&&(t[e]=undefined)}));if(this._xregexp&&this._xregexp.captureNames)for(var f=1;f<t.length;f++)n=this._xregexp.captureNames[f-1],n&&(t[n]=t[f]);!s&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),ace.define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function m(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError;var r=o.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e,u=n.apply(s,r.concat(o.call(arguments)));return u!==null&&Object(u)===u?u:s}return n.apply(t,r.concat(o.call(arguments)))};return i});var r=Function.prototype.call,i=Array.prototype,s=Object.prototype,o=i.slice,u=r.bind(s.toString),a=r.bind(s.hasOwnProperty),f,l,c,h,p;if(p=a(s,"__defineGetter__"))f=r.bind(s.__defineGetter__),l=r.bind(s.__defineSetter__),c=r.bind(s.__lookupGetter__),h=r.bind(s.__lookupSetter__);Array.isArray||(Array.isArray=function(t){return u(t)=="[object Array]"}),Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=D(this),r=arguments[1],i=0,s=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;while(i<s)i in n&&t.call(r,n[i],i,n),i++}),Array.prototype.map||(Array.prototype.map=function(t){var n=D(this),r=n.length>>>0,i=Array(r),s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o<r;o++)o in n&&(i[o]=t.call(s,n[o],o,n));return i}),Array.prototype.filter||(Array.prototype.filter=function(t){var n=D(this),r=n.length>>>0,i=[],s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o<r;o++)o in n&&t.call(s,n[o],o,n)&&i.push(n[o]);return i}),Array.prototype.every||(Array.prototype.every=function(t){var n=D(this),r=n.length>>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s<r;s++)if(s in n&&!t.call(i,n[s],s,n))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(t){var n=D(this),r=n.length>>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s<r;s++)if(s in n&&t.call(i,n[s],s,n))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(t){var n=D(this),r=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i=0,s;if(arguments.length>=2)s=arguments[1];else do{if(i in n){s=n[i++];break}if(++i>=r)throw new TypeError}while(!0);for(;i<r;i++)i in n&&(s=t.call(void 0,s,n[i],i,n));return s}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(t){var n=D(this),r=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i,s=r-1;if(arguments.length>=2)i=arguments[1];else do{if(s in n){i=n[s--];break}if(--s<0)throw new TypeError}while(!0);do s in this&&(i=t.call(void 0,i,n[s],s,n));while(s--);return i}),Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var n=D(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=M(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i<r;i++)if(i in n&&n[i]===t)return i;return-1}),Array.prototype.lastIndexOf||(Array.prototype.lastIndexOf=function(t){var n=D(this),r=n.length>>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,M(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:s)});if(!Object.getOwnPropertyDescriptor){var d="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(d+t);if(!a(t,n))return;var r,i,o;r={enumerable:!0,configurable:!0};if(p){var u=t.__proto__;t.__proto__=s;var i=c(t,n),o=h(t,n);t.__proto__=u;if(i||o)return i&&(r.get=i),o&&(r.set=o),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var v;Object.prototype.__proto__===null?v=function(){return{__proto__:null}}:v=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=v();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var g=m({}),y=typeof document=="undefined"||m(document.createElement("div"));if(!g||!y)var b=Object.defineProperty}if(!Object.defineProperty||b){var w="Property description must be an object: ",E="Object.defineProperty called on non-object: ",S="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(E+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(w+r);if(b)try{return b.call(Object,t,n,r)}catch(i){}if(a(r,"value"))if(p&&(c(t,n)||h(t,n))){var o=t.__proto__;t.__proto__=s,delete t[n],t[n]=r.value,t.__proto__=o}else t[n]=r.value;else{if(!p)throw new TypeError(S);a(r,"get")&&f(t,n,r.get),a(r,"set")&&l(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)a(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(x){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(a(t,n))n+="?";t[n]=!0;var r=a(t,n);return delete t[n],r});if(!Object.keys){var T=!0,N=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],C=N.length;for(var k in{toString:null})T=!1;Object.keys=function P(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var P=[];for(var t in e)a(e,t)&&P.push(t);if(T)for(var n=0,r=C;n<r;n++){var i=N[n];a(e,i)&&P.push(i)}return P}}if(!Date.prototype.toISOString||(new Date(-621987552e5)).toISOString().indexOf("-000001")===-1)Date.prototype.toISOString=function(){var t,n,r,i;if(!isFinite(this))throw new RangeError;t=[this.getUTCMonth()+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()],i=this.getUTCFullYear(),i=(i<0?"-":i>9999?"+":"")+("00000"+Math.abs(i)).slice(0<=i&&i<=9999?-4:-6),n=t.length;while(n--)r=t[n],r<10&&(t[n]="0"+r);return i+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(t){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()}),Date.parse("+275760-09-13T00:00:00.000Z")!==864e13&&(Date=function(e){var t=function i(t,n,r,s,o,u,a){var f=arguments.length;if(this instanceof e){var l=f==1&&String(t)===t?new e(i.parse(t)):f>=7?new e(t,n,r,s,o,u,a):f>=6?new e(t,n,r,s,o,u):f>=5?new e(t,n,r,s,o):f>=4?new e(t,n,r,s):f>=3?new e(t,n,r):f>=2?new e(t,n):f>=1?new e(t):new e;return l.constructor=i,l}return e.apply(this,arguments)},n=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$");for(var r in e)t[r]=e[r];return t.now=e.now,t.UTC=e.UTC,t.prototype=e.prototype,t.prototype.constructor=t,t.parse=function(r){var i=n.exec(r);if(i){i.shift();for(var s=1;s<7;s++)i[s]=+(i[s]||(s<3?1:0)),s==1&&i[s]--;var o=+i.pop(),u=+i.pop(),a=i.pop(),f=0;if(a){if(u>23||o>59)return NaN;f=(u*60+o)*6e4*(a=="+"?-1:1)}var l=+i[0];return 0<=l&&l<=99?(i[0]=l+400,e.UTC.apply(this,i)+f-126227808e5):e.UTC.apply(this,i)+f}return e.parse.apply(this,arguments)},t}(Date));var L=" \n \f\r   ᠎ â€â€‚         âŸã€€\u2028\u2029";if(!String.prototype.trim||L.trim()){L="["+L+"]";var A=new RegExp("^"+L+L+"*"),O=new RegExp(L+L+"*$");String.prototype.trim=function(){return String(this).replace(A,"").replace(O,"")}}var M=function(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e},_="a"[0]!="a",D=function(e){if(e==null)throw new TypeError;return _&&typeof e=="string"&&e?e.split(""):Object(e)}}),ace.define("ace/lib/dom",["require","exports","module"],function(e,t,n){var r="http://www.w3.org/1999/xhtml";t.createElement=function(e,t){return document.createElementNS?document.createElementNS(t||r,e):document.createElement(e)},t.setText=function(e,t){e.innerText!==undefined&&(e.innerText=t),e.textContent!==undefined&&(e.textContent=t)},t.hasCssClass=function(e,t){var n=e.className.split(/\s+/g);return n.indexOf(t)!==-1},t.addCssClass=function(e,n){t.hasCssClass(e,n)||(e.className+=" "+n)},t.removeCssClass=function(e,t){var n=e.className.split(/\s+/g);for(;;){var r=n.indexOf(t);if(r==-1)break;n.splice(r,1)}e.className=n.join(" ")},t.toggleCssClass=function(e,t){var n=e.className.split(/\s+/g),r=!0;for(;;){var i=n.indexOf(t);if(i==-1)break;r=!1,n.splice(i,1)}return r&&n.push(t),e.className=n.join(" "),r},t.setCssClass=function(e,n,r){r?t.addCssClass(e,n):t.removeCssClass(e,n)},t.hasCssString=function(e,t){var n=0,r;t=t||document;if(t.createStyleSheet&&(r=t.styleSheets)){while(n<r.length)if(r[n++].owningElement.id===e)return!0}else if(r=t.getElementsByTagName("style"))while(n<r.length)if(r[n++].id===e)return!0;return!1},t.importCssString=function(n,i,s){s=s||document;if(i&&t.hasCssString(i,s))return null;var o;if(s.createStyleSheet)o=s.createStyleSheet(),o.cssText=n,i&&(o.owningElement.id=i);else{o=s.createElementNS?s.createElementNS(r,"style"):s.createElement("style"),o.appendChild(s.createTextNode(n)),i&&(o.id=i);var u=s.getElementsByTagName("head")[0]||s.documentElement;u.appendChild(o)}},t.importCssStylsheet=function(e,n){if(n.createStyleSheet)n.createStyleSheet(e);else{var r=t.createElement("link");r.rel="stylesheet",r.href=e;var i=n.getElementsByTagName("head")[0]||n.documentElement;i.appendChild(r)}},t.getInnerWidth=function(e){return parseInt(t.computedStyle(e,"paddingLeft"),10)+parseInt(t.computedStyle(e,"paddingRight"),10)+e.clientWidth},t.getInnerHeight=function(e){return parseInt(t.computedStyle(e,"paddingTop"),10)+parseInt(t.computedStyle(e,"paddingBottom"),10)+e.clientHeight},window.pageYOffset!==undefined?(t.getPageScrollTop=function(){return window.pageYOffset},t.getPageScrollLeft=function(){return window.pageXOffset}):(t.getPageScrollTop=function(){return document.body.scrollTop},t.getPageScrollLeft=function(){return document.body.scrollLeft}),window.getComputedStyle?t.computedStyle=function(e,t){return t?(window.getComputedStyle(e,"")||{})[t]||"":window.getComputedStyle(e,"")||{}}:t.computedStyle=function(e,t){return t?e.currentStyle[t]:e.currentStyle},t.scrollbarWidth=function(e){var n=t.createElement("p");n.style.width="100%",n.style.minWidth="0px",n.style.height="200px";var r=t.createElement("div"),i=r.style;i.position="absolute",i.left="-10000px",i.overflow="hidden",i.width="200px",i.minWidth="0px",i.height="150px",r.appendChild(n);var s=e.body||e.documentElement;s.appendChild(r);var o=n.offsetWidth;i.overflow="scroll";var u=n.offsetWidth;return o==u&&(u=r.clientWidth),s.removeChild(r),o-u},t.setInnerHtml=function(e,t){var n=e.cloneNode(!1);return n.innerHTML=t,e.parentNode.replaceChild(n,e),n},t.setInnerText=function(e,t){var n=e.ownerDocument;n.body&&"textContent"in n.body?e.textContent=t:e.innerText=t},t.getInnerText=function(e){var t=e.ownerDocument;return t.body&&"textContent"in t.body?e.textContent:e.innerText||e.textContent||""},t.getParentWindow=function(e){return e.defaultView||e.parentWindow}}),ace.define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent","ace/lib/dom"],function(e,t,n){function o(e,t,n){var s=0;!i.isOpera||"KeyboardEvent"in window||!i.isMac?s=0|(t.ctrlKey?1:0)|(t.altKey?2:0)|(t.shiftKey?4:0)|(t.metaKey?8:0):s=0|(t.metaKey?1:0)|(t.altKey?2:0)|(t.shiftKey?4:0)|(t.ctrlKey?8:0);if(n in r.MODIFIER_KEYS){switch(r.MODIFIER_KEYS[n]){case"Alt":s=2;break;case"Shift":s=4;break;case"Ctrl":s=1;break;default:s=8}n=0}return s&8&&(n==91||n==93)&&(n=0),!!s||n in r.FUNCTION_KEYS||n in r.PRINTABLE_KEYS?e(t,s,n):!1}var r=e("./keys"),i=e("./useragent"),s=e("./dom");t.addListener=function(e,t,n){if(e.addEventListener)return e.addEventListener(t,n,!1);if(e.attachEvent){var r=function(){n(window.event)};n._wrapper=r,e.attachEvent("on"+t,r)}},t.removeListener=function(e,t,n){if(e.removeEventListener)return e.removeEventListener(t,n,!1);e.detachEvent&&e.detachEvent("on"+t,n._wrapper||n)},t.stopEvent=function(e){return t.stopPropagation(e),t.preventDefault(e),!1},t.stopPropagation=function(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0},t.preventDefault=function(e){e.preventDefault?e.preventDefault():e.returnValue=!1},t.getButton=function(e){return e.type=="dblclick"?0:e.type=="contextmenu"||e.ctrlKey&&i.isMac?2:e.preventDefault?e.button:{1:0,2:2,4:1}[e.button]},document.documentElement.setCapture?t.capture=function(e,n,r){function s(o){n(o),i||(i=!0,r(o)),t.removeListener(e,"mousemove",n),t.removeListener(e,"mouseup",s),t.removeListener(e,"losecapture",s),e.releaseCapture()}var i=!1;t.addListener(e,"mousemove",n),t.addListener(e,"mouseup",s),t.addListener(e,"losecapture",s),e.setCapture()}:t.capture=function(e,t,n){function r(e){t&&t(e),n&&n(e),document.removeEventListener("mousemove",t,!0),document.removeEventListener("mouseup",r,!0),e.stopPropagation()}document.addEventListener("mousemove",t,!0),document.addEventListener("mouseup",r,!0)},t.addMouseWheelListener=function(e,n){var r=8,i=function(e){e.wheelDelta!==undefined?e.wheelDeltaX!==undefined?(e.wheelX=-e.wheelDeltaX/r,e.wheelY=-e.wheelDeltaY/r):(e.wheelX=0,e.wheelY=-e.wheelDelta/r):e.axis&&e.axis==e.HORIZONTAL_AXIS?(e.wheelX=(e.detail||0)*5,e.wheelY=0):(e.wheelX=0,e.wheelY=(e.detail||0)*5),n(e)};t.addListener(e,"DOMMouseScroll",i),t.addListener(e,"mousewheel",i)},t.addMultiMouseDownListener=function(e,n,r,s){var o=0,u,a,f,l={2:"dblclick",3:"tripleclick",4:"quadclick"};t.addListener(e,"mousedown",function(e){if(t.getButton(e)!=0)o=0;else{var i=Math.abs(e.clientX-u)>5||Math.abs(e.clientY-a)>5;if(!f||i)o=0;o+=1,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600)}o==1&&(u=e.clientX,a=e.clientY),r[s]("mousedown",e);if(o>4)o=0;else if(o>1)return r[s](l[o],e)}),i.isOldIE&&t.addListener(e,"dblclick",function(e){o=2,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),r[s]("mousedown",e),r[s](l[o],e)})},t.addCommandKeyListener=function(e,n){var r=t.addListener;if(i.isOldGecko||i.isOpera&&!("KeyboardEvent"in window)){var s=null;r(e,"keydown",function(e){s=e.keyCode}),r(e,"keypress",function(e){return o(n,e,s)})}else{var u=null;r(e,"keydown",function(e){return u=e.keyIdentifier||e.keyCode,o(n,e,e.keyCode)})}};if(window.postMessage&&!i.isOldIE){var u=1;t.nextTick=function(e,n){n=n||window;var r="zero-timeout-message-"+u;t.addListener(n,"message",function i(s){s.data==r&&(t.stopPropagation(s),t.removeListener(n,"message",i),e())}),n.postMessage(r,"*")}}t.nextFrame=window.requestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame,t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),ace.define("ace/lib/keys",["require","exports","module","ace/lib/oop"],function(e,t,n){var r=e("./oop"),i=function(){var e={MODIFIER_KEYS:{16:"Shift",17:"Ctrl",18:"Alt",224:"Meta"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,meta:8,command:8},FUNCTION_KEYS:{8:"Backspace",9:"Tab",13:"Return",19:"Pause",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"Print",45:"Insert",46:"Delete",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Numlock",145:"Scrolllock"},PRINTABLE_KEYS:{32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",107:"+",109:"-",110:".",188:",",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"}};for(var t in e.FUNCTION_KEYS){var n=e.FUNCTION_KEYS[t].toLowerCase();e[n]=parseInt(t,10)}return r.mixin(e,e.MODIFIER_KEYS),r.mixin(e,e.PRINTABLE_KEYS),r.mixin(e,e.FUNCTION_KEYS),e.enter=e["return"],e.escape=e.esc,e.del=e["delete"],e[173]="-",e}();r.mixin(t,i),t.keyCodeToString=function(e){return(i[e]||String.fromCharCode(e)).toLowerCase()}}),ace.define("ace/lib/oop",["require","exports","module"],function(e,t,n){t.inherits=function(){var e=function(){};return function(t,n){e.prototype=n.prototype,t.super_=n.prototype,t.prototype=new e,t.prototype.constructor=t}}(),t.mixin=function(e,t){for(var n in t)e[n]=t[n]},t.implement=function(e,n){t.mixin(e,n)}}),ace.define("ace/lib/useragent",["require","exports","module"],function(e,t,n){t.OS={LINUX:"LINUX",MAC:"MAC",WINDOWS:"WINDOWS"},t.getOS=function(){return t.isMac?t.OS.MAC:t.isLinux?t.OS.LINUX:t.OS.WINDOWS};if(typeof navigator!="object")return;var r=(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase(),i=navigator.userAgent;t.isWin=r=="win",t.isMac=r=="mac",t.isLinux=r=="linux",t.isIE=navigator.appName=="Microsoft Internet Explorer"&&parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=window.controllers&&window.navigator.product==="Gecko",t.isOldGecko=t.isGecko&&parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",t.isWebKit=parseFloat(i.split("WebKit/")[1])||undefined,t.isChrome=parseFloat(i.split(" Chrome/")[1])||undefined,t.isAIR=i.indexOf("AdobeAIR")>=0,t.isIPad=i.indexOf("iPad")>=0,t.isTouchPad=i.indexOf("TouchPad")>=0}),ace.define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands"],function(e,t,n){e("./lib/fixoldbrowsers");var r=e("./lib/oop"),i=e("./lib/lang"),s=e("./lib/useragent"),o=e("./keyboard/textinput").TextInput,u=e("./mouse/mouse_handler").MouseHandler,a=e("./mouse/fold_handler").FoldHandler,f=e("./keyboard/keybinding").KeyBinding,l=e("./edit_session").EditSession,c=e("./search").Search,h=e("./range").Range,p=e("./lib/event_emitter").EventEmitter,d=e("./commands/command_manager").CommandManager,v=e("./commands/default_commands").commands,m=function(e,t){var n=e.getContainerElement();this.container=n,this.renderer=e,this.commands=new d(s.isMac?"mac":"win",v),this.textInput=new o(e.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.keyBinding=new f(this),this.$mouseHandler=new u(this),new a(this),this.$blockScrolling=0,this.$search=(new c).set({wrap:!0}),this.setSession(t||new l(""))};(function(){r.implement(this,p),this.setKeyboardHandler=function(e){this.keyBinding.setKeyboardHandler(e)},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session==e)return;if(this.session){var t=this.session;this.session.removeEventListener("change",this.$onDocumentChange),this.session.removeEventListener("changeMode",this.$onChangeMode),this.session.removeEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.session.removeEventListener("changeTabSize",this.$onChangeTabSize),this.session.removeEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.session.removeEventListener("changeWrapMode",this.$onChangeWrapMode),this.session.removeEventListener("onChangeFold",this.$onChangeFold),this.session.removeEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.session.removeEventListener("changeBackMarker",this.$onChangeBackMarker),this.session.removeEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.session.removeEventListener("changeAnnotation",this.$onChangeAnnotation),this.session.removeEventListener("changeOverwrite",this.$onCursorChange),this.session.removeEventListener("changeScrollTop",this.$onScrollTopChange),this.session.removeEventListener("changeLeftTop",this.$onScrollLeftChange);var n=this.session.getSelection();n.removeEventListener("changeCursor",this.$onCursorChange),n.removeEventListener("changeSelection",this.$onSelectionChange)}this.session=e,this.$onDocumentChange=this.onDocumentChange.bind(this),e.addEventListener("change",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.addEventListener("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.addEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.addEventListener("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.addEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.addEventListener("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.addEventListener("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.addEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.addEventListener("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.addEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.addEventListener("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.addEventListener("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.addEventListener("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.addEventListener("changeScrollLeft",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.addEventListener("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.addEventListener("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull(),this._emit("changeSession",{session:e,oldSession:t})},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e){this.renderer.setTheme(e)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.setFontSize=function(e){this.container.style.fontSize=e,this.renderer.updateFontSize()},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session.findMatchingBracket(e.getCursorPosition());if(t){var n=new h(t.row,t.column,t.row,t.column+1);e.session.$bracketHighlight=e.session.addMarker(n,"ace_bracket","text")}},50)},this.focus=function(){var e=this;setTimeout(function(){e.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(){if(this.$isFocused)return;this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus")},this.onBlur=function(){if(!this.$isFocused)return;this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur")},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(e){var t=e.data,n=t.range,r;n.start.row==n.end.row&&t.action!="insertLines"&&t.action!="removeLines"?r=n.end.row:r=Infinity,this.renderer.updateLines(n.start.row,r),this._emit("change",e),this.$cursorChange()},this.onTokenizerUpdate=function(e){var t=e.data;this.renderer.updateLines(t.first,t.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||this.renderer.scrollCursorIntoView(),this.$highlightBrackets(),this.$updateHighlightActiveLine(),this._emit("changeSelection")},this.$updateHighlightActiveLine=function(){var e=this.getSession(),t;this.$highlightActiveLine&&(this.$selectionStyle!="line"||!this.selection.isMultiLine())&&(t=this.getCursorPosition()),e.$highlightLineMarker&&!t?(e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null):!e.$highlightLineMarker&&t?e.$highlightLineMarker=e.highlightLines(t.row,t.row,"ace_active-line"):t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e._emit("changeBackMarker"))},this.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,"ace_selection",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._emit("changeSelection")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column-1,r=t.end.column+1,i=e.getLine(t.start.row),s=i.length,o=i.substring(Math.max(n,0),Math.min(r,s));if(n>=0&&/^[\w\d]/.test(o)||r<=s&&/[\w\d]$/.test(o))return;o=i.substring(t.start.column,t.end.column);if(!/^[\w\d]+$/.test(o))return;var u=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:o});return u},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(){this.renderer.updateText()},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getCopyText=function(){var e="";return this.selection.isEmpty()||(e=this.session.getTextRange(this.getSelectionRange())),this._emit("copy",e),e},this.onCopy=function(){this.commands.exec("copy",this)},this.onCut=function(){this.commands.exec("cut",this)},this.onPaste=function(e){if(this.$readOnly)return;this._emit("paste",e),this.insert(e)},this.execCommand=function(e,t){this.commands.exec(e,this,t)},this.insert=function(e){var t=this.session,n=t.getMode(),r=this.getCursorPosition();if(this.getBehavioursEnabled()){var i=n.transformAction(t.getState(r.row),"insertion",this,t,e);i&&(e=i.text)}e=e.replace(" ",this.session.getTabString());if(!this.selection.isEmpty())r=this.session.remove(this.getSelectionRange()),this.clearSelection();else if(this.session.getOverwrite()){var s=new h.fromPoints(r,r);s.end.column+=e.length,this.session.remove(s)}this.clearSelection();var o=r.column,u=t.getState(r.row),a=t.getLine(r.row),f=n.checkOutdent(u,a,e),l=t.insert(r,e);i&&i.selection&&(i.selection.length==2?this.selection.setSelectionRange(new h(r.row,o+i.selection[0],r.row,o+i.selection[1])):this.selection.setSelectionRange(new h(r.row+i.selection[0],i.selection[1],r.row+i.selection[2],i.selection[3])));if(t.getDocument().isNewLine(e)){var c=n.getNextLineIndent(u,a.slice(0,r.column),t.getTabString());this.moveCursorTo(r.row+1,0);var p=t.getTabSize(),d=Number.MAX_VALUE;for(var v=r.row+1;v<=l.row;++v){var m=0;a=t.getLine(v);for(var g=0;g<a.length;++g)if(a.charAt(g)==" ")m+=p;else{if(a.charAt(g)!=" ")break;m+=1}/[^\s]/.test(a)&&(d=Math.min(m,d))}for(var v=r.row+1;v<=l.row;++v){var y=d;a=t.getLine(v);for(var g=0;g<a.length&&y>0;++g)a.charAt(g)==" "?y-=p:a.charAt(g)==" "&&(y-=1);t.remove(new h(v,0,v,g))}t.indentRows(r.row+1,l.row,c)}f&&n.autoOutdent(u,t,r.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.$mouseHandler.setScrollSpeed(e)},this.getScrollSpeed=function(){return this.$mouseHandler.getScrollSpeed()},this.setDragDelay=function(e){this.$mouseHandler.setDragDelay(e)},this.getDragDelay=function(){return this.$mouseHandler.getDragDelay()},this.$selectionStyle="line",this.setSelectionStyle=function(e){if(this.$selectionStyle==e)return;this.$selectionStyle=e,this.onSelectionChange(),this._emit("changeSelectionStyle",{data:e})},this.getSelectionStyle=function(){return this.$selectionStyle},this.$highlightActiveLine=!0,this.setHighlightActiveLine=function(e){if(this.$highlightActiveLine==e)return;this.$highlightActiveLine=e,this.$updateHighlightActiveLine()},this.getHighlightActiveLine=function(){return this.$highlightActiveLine},this.$highlightGutterLine=!0,this.setHighlightGutterLine=function(e){if(this.$highlightGutterLine==e)return;this.renderer.setHighlightGutterLine(e),this.$highlightGutterLine=e},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$highlightSelectedWord=!0,this.setHighlightSelectedWord=function(e){if(this.$highlightSelectedWord==e)return;this.$highlightSelectedWord=e,this.$onSelectionChange()},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.$readOnly=!1,this.setReadOnly=function(e){this.$readOnly=e},this.getReadOnly=function(){return this.$readOnly},this.$modeBehaviours=!0,this.setBehavioursEnabled=function(e){this.$modeBehaviours=e},this.getBehavioursEnabled=function(){return this.$modeBehaviours},this.$modeWrapBehaviours=!0,this.setWrapBehavioursEnabled=function(e){this.$modeWrapBehaviours=e},this.getWrapBehavioursEnabled=function(){return this.$modeWrapBehaviours},this.setShowFoldWidgets=function(e){var t=this.renderer.$gutterLayer;if(t.getShowFoldWidgets()==e)return;this.renderer.$gutterLayer.setShowFoldWidgets(e),this.$showFoldWidgets=e,this.renderer.updateFull()},this.getShowFoldWidgets=function(){return this.renderer.$gutterLayer.getShowFoldWidgets()},this.setFadeFoldWidgets=function(e){this.renderer.setFadeFoldWidgets(e)},this.getFadeFoldWidgets=function(){return this.renderer.getFadeFoldWidgets()},this.remove=function(e){this.selection.isEmpty()&&(e=="left"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,"deletion",this,n,t);i&&(t=i)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;t<n.length?(r=n.charAt(t)+n.charAt(t-1),i=new h(e.row,t-1,e.row,t+1)):(r=n.charAt(t-1)+n.charAt(t-2),i=new h(e.row,t-2,e.row,t)),this.session.replace(i,r)},this.toLowerCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toLowerCase()),this.selection.setSelectionRange(e)},this.toUpperCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toUpperCase()),this.selection.setSelectionRange(e)},this.indent=function(){var e=this.session,t=this.getSelectionRange();if(!(t.start.row<t.end.row||t.start.column<t.end.column)){var r;if(this.session.getUseSoftTabs()){var s=e.getTabSize(),o=this.getCursorPosition(),u=e.documentToScreenColumn(o.row,o.column),a=s-u%s;r=i.stringRepeat(" ",a)}else r=" ";return this.insert(r)}var n=this.$getSelectedRows();e.indentRows(n.first,n.last," ")},this.blockOutdent=function(){var e=this.session.getSelection();this.session.outdentRows(e.getRange())},this.sortLines=function(){var e=this.$getSelectedRows(),t=this.session,n=[];for(i=e.first;i<=e.last;i++)n.push(t.getLine(i));n.sort(function(e,t){return e.toLowerCase()<t.toLowerCase()?-1:e.toLowerCase()>t.toLowerCase()?1:0});var r=new h(0,0,0,0);for(var i=e.first;i<=e.last;i++){var s=t.getLine(i);r.start.row=i,r.end.row=i,r.end.column=s.length,t.replace(r,n[i-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.getNumberAt=function(e,t){var n=/[\-]?[0-9]+(?:\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex<t-1){var i=n.exec(r);if(i.index<=t&&i.index+i[0].length>=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new h(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(".")>=0?s.start+s.value.indexOf(".")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&n<o?e*=Math.pow(10,s.end-n-1):e*=Math.pow(10,s.end-n),a+=e,a/=Math.pow(10,u);var f=a.toFixed(u),l=new h(t,s.start,t,s.end);this.session.replace(l,f),this.moveCursorTo(t,Math.max(s.start+1,n+f.length-s.value.length))}}},this.removeLines=function(){var e=this.$getSelectedRows(),t;e.first===0||e.last+1<this.session.getLength()?t=new h(e.first,0,e.last+1,0):t=new h(e.first-1,this.session.getLine(e.first-1).length,e.last,this.session.getLine(e.last).length),this.session.remove(t),this.clearSelection()},this.duplicateSelection=function(){var e=this.selection,t=this.session,n=e.getRange();if(n.isEmpty()){var r=n.start.row;t.duplicateLines(r,r)}else{var i=e.isBackwards(),s=e.isBackwards()?n.start:n.end,o=t.insert(s,t.getTextRange(n),!1);n.start=s,n.end=o,e.setSelectionRange(n,i)}},this.moveLinesDown=function(){this.$moveLines(function(e,t){return this.session.moveLinesDown(e,t)})},this.moveLinesUp=function(){this.$moveLines(function(e,t){return this.session.moveLinesUp(e,t)})},this.moveText=function(e,t){return this.$readOnly?null:this.session.moveText(e,t)},this.copyLinesUp=function(){this.$moveLines(function(e,t){return this.session.duplicateLines(e,t),0})},this.copyLinesDown=function(){this.$moveLines(function(e,t){return this.session.duplicateLines(e,t)})},this.$moveLines=function(e){var t=this.$getSelectedRows(),n=this.selection;if(!n.isMultiLine())var r=n.getRange(),i=n.isBackwards();var s=e.call(this,t.first,t.last);r?(r.start.row+=s,r.end.row+=s,n.setSelectionRange(r,i)):(n.setSelectionAnchor(t.last+s+1,0),n.$moveSelection(function(){n.moveCursorTo(t.first+s,0)}))},this.$getSelectedRows=function(){var e=this.getSelectionRange().collapseRows();return{first:e.start.row,last:e.end.row}},this.onCompositionStart=function(e){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(e){this.renderer.setCompositionText(e)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(e){return e>=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);this.$blockScrolling++,t==1?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t==0&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection()),this.$blockScrolling--;var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e){var t=this.getCursorPosition(),n=this.session.getBracketRange(t);if(!n){n=this.find({needle:/[{}()\[\]]/g,preventScroll:!0,start:{row:t.row,column:t.column-1}});if(!n)return;var r=n.start;r.row==t.row&&Math.abs(r.column-t.column)<2&&(n=this.session.getBracketRange(r))}r=n&&n.cursor||r,r&&(e?n&&n.isEqual(this.getSelectionRange())?this.clearSelection():this.selection.selectTo(r.row,r.column):(this.clearSelection(),this.moveCursorTo(r.row,r.column)))},this.gotoLine=function(e,t,n){this.selection.clearSelection(),this.session.unfold({row:e-1,column:t||0}),this.$blockScrolling+=1,this.moveCursorTo(e-1,t||0),this.$blockScrolling-=1,this.isRowFullyVisible(e-1)||this.scrollToLine(e-1,!0,n)},this.navigateTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.navigateUp=function(e){this.selection.clearSelection(),e=e||1,this.selection.moveCursorBy(-e,0)},this.navigateDown=function(e){this.selection.clearSelection(),e=e||1,this.selection.moveCursorBy(e,0)},this.navigateLeft=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().start;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().end;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){var e=this.renderer.scrollTop;this.selection.moveCursorFileEnd(),this.clearSelection(),this.renderer.animateScrolling(e)},this.navigateFileStart=function(){var e=this.renderer.scrollTop;this.selection.moveCursorFileStart(),this.clearSelection(),this.renderer.animateScrolling(e)},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(e,t){t&&this.$search.set(t);var n=this.$search.find(this.session),r=0;return n?(this.$tryReplace(n,e)&&(r=1),n!==null&&(this.selection.setSelectionRange(n),this.renderer.scrollSelectionIntoView(n.start,n.end)),r):r},this.replaceAll=function(e,t){t&&this.$search.set(t);var n=this.$search.findAll(this.session),r=0;if(!n.length)return r;this.$blockScrolling+=1;var i=this.getSelectionRange();this.clearSelection(),this.selection.moveCursorTo(0,0);for(var s=n.length-1;s>=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),this.$blockScrolling-=1,r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,n){t||(t={}),typeof e=="string"||e instanceof RegExp?t.needle=e:typeof e=="object"&&r.mixin(t,e);var i=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(i)||this.$search.$options.needle,e||(i=this.session.getWordRange(i.start.row,i.start.column),e=this.session.getTextRange(i)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:i});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?i.start=i.end:i.end=i.start,this.selection.setRange(i)},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!=0&&this.renderer.animateScrolling(n)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy()}}).call(m.prototype),t.Editor=m}),ace.define("ace/lib/lang",["require","exports","module"],function(e,t,n){t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){return(new Array(t+1)).join(e)};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n<r;n++)e[n]&&typeof e[n]=="object"?t[n]=this.copyObject(e[n]):t[n]=e[n];return t},t.deepCopy=function(e){if(typeof e!="object")return e;var t=e.constructor();for(var n in e)typeof e[n]=="object"?t[n]=this.deepCopy(e[n]):t[n]=e[n];return t},t.arrayToMap=function(e){var t={};for(var n=0;n<e.length;n++)t[e[n]]=1;return t},t.createMap=function(e){var t=Object.create(null);for(var n in e)t[n]=e[n];return t},t.arrayRemove=function(e,t){for(var n=0;n<=e.length;n++)t===e[n]&&e.splice(n,1)},t.escapeRegExp=function(e){return e.replace(/([.*+?^${}()|[\]\/\\])/g,"\\$1")},t.escapeHTML=function(e){return e.replace(/&/g,"&#38;").replace(/"/g,"&#34;").replace(/'/g,"&#39;").replace(/</g,"&#60;")},t.getMatchOffsets=function(e,t){var n=[];return e.replace(t,function(e){n.push({offset:arguments[arguments.length-2],length:e.length})}),n},t.deferredCall=function(e){var t=null,n=function(){t=null,e()},r=function(e){return r.cancel(),t=setTimeout(n,e||0),r};return r.schedule=r,r.call=function(){return this.cancel(),e(),r},r.cancel=function(){return clearTimeout(t),t=null,r},r},t.delayedCall=function(e,t){var n=null,r=function(){n=null,e()},i=function(e){n&&clearTimeout(n),n=setTimeout(r,e||t)};return i.delay=i,i.schedule=function(e){n==null&&(n=setTimeout(r,e||0))},i.call=function(){this.cancel(),e()},i.cancel=function(){n&&clearTimeout(n),n=null},i.isPending=function(){return n},i}}),ace.define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom","ace/lib/lang"],function(e,t,n){var r=e("../lib/event"),i=e("../lib/useragent"),s=e("../lib/dom"),o=e("../lib/lang"),u=function(e,t){function g(e){if(c)return;var t=e?2:1,r=2;try{n.setSelectionRange(t,r)}catch(i){}}function y(){if(c)return;n.value=u,i.isWebKit&&m.schedule()}function D(){setTimeout(function(){h&&(n.style.cssText=h,h=""),t.renderer.$keepTextAreaAtCursor==null&&(t.renderer.$keepTextAreaAtCursor=!0,t.renderer.$moveTextAreaToCursor())},0)}var n=s.createElement("textarea");n.className="ace_text-input",i.isTouchPad&&n.setAttribute("x-palm-disable-auto-cap",!0),n.wrap="off",n.autocorrect="off",n.autocapitalize="off",n.spellcheck=!1,n.style.top="-2em",e.insertBefore(n,e.firstChild);var u="",a=!1,f=!1,l=!1,c=!1,h="",p=!0,d=document.activeElement===n;r.addListener(n,"blur",function(){t.onBlur(),d=!1}),r.addListener(n,"focus",function(){d=!0,t.onFocus(),g()}),this.focus=function(){n.focus()},this.blur=function(){n.blur()},this.isFocused=function(){return d};var v=o.delayedCall(function(){d&&g(p)}),m=o.delayedCall(function(){c||(n.value=u,d&&g())});i.isWebKit||t.addEventListener("changeSelection",function(){t.selection.isEmpty()!=p&&(p=!p,v.schedule())}),y(),d&&t.onFocus();var b=function(e){return e.selectionStart===0&&e.selectionEnd===e.value.length};!n.setSelectionRange&&n.createTextRange&&(n.setSelectionRange=function(e,t){var n=this.createTextRange();n.collapse(!0),n.moveStart("character",e),n.moveEnd("character",t),n.select()},b=function(e){try{var t=e.ownerDocument.selection.createRange()}catch(n){}return!t||t.parentElement()!=e?!1:t.text==e.value});if(i.isOldIE){var w=!1,E=function(e){if(w)return;var t=n.value;if(c||!t||t==u)return;if(e&&t==u[0])return S.schedule();N(t),w=!0,y(),w=!1},S=o.delayedCall(E);r.addListener(n,"propertychange",E);var x={13:1,27:1};r.addListener(n,"keyup",function(e){c&&(!n.value||x[e.keyCode])&&setTimeout(_,0);if((n.value.charCodeAt(0)||0)<129)return;c?M():O()})}var T=function(e){if(a){a=!1;return}if(f){f=!1;return}b(n)&&(t.selectAll(),g())},N=function(e){l?(g(),e&&t.onPaste(e),l=!1):e==u[0]?t.execCommand("del",{source:"ace"}):(e.substring(0,2)==u?e=e.substr(2):e[0]==u[0]?e=e.substr(1):e[e.length-1]==u[0]&&(e=e.slice(0,-1)),e[e.length-1]==u[0]&&(e=e.slice(0,-1)),e&&t.onTextInput(e))},C=function(e){if(c)return;var t=n.value;y(),N(t)},k=function(e){var i=t.getCopyText();if(!i){r.preventDefault(e);return}var s=e.clipboardData||window.clipboardData;if(s){var o=s.setData("Text",i);o&&(t.onCut(),r.preventDefault(e))}o||(a=!0,n.value=i,n.select(),setTimeout(function(){a=!1,y(),g(),t.onCut()}))},L=function(e){var i=t.getCopyText();if(!i){r.preventDefault(e);return}var s=e.clipboardData||window.clipboardData;if(s){var o=s.setData("Text",i);o&&(t.onCopy(),r.preventDefault(e))}o||(f=!0,n.value=i,n.select(),setTimeout(function(){f=!1,y(),g(),t.onCopy()}))},A=function(e){var s=e.clipboardData||window.clipboardData;if(s){var o=s.getData("Text");o&&t.onPaste(o),i.isIE&&setTimeout(g),r.preventDefault(e)}else n.value="",l=!0};r.addCommandKeyListener(n,t.onCommandKey.bind(t)),r.addListener(n,"select",T),r.addListener(n,"input",C),r.addListener(n,"cut",k),r.addListener(n,"copy",L),r.addListener(n,"paste",A),(!("oncut"in n)||!("oncopy"in n)||!("onpaste"in n))&&r.addListener(e,"keydown",function(e){if(i.isMac&&!e.metaKey||!e.ctrlKey)return;switch(e.keyCode){case 67:L(e);break;case 86:A(e);break;case 88:k(e)}});var O=function(e){c=!0,t.onCompositionStart(),setTimeout(M,0)},M=function(){if(!c)return;t.onCompositionUpdate(n.value)},_=function(e){c=!1,t.onCompositionEnd()};r.addListener(n,"compositionstart",O),i.isGecko?r.addListener(n,"text",M):r.addListener(n,"keyup",M),r.addListener(n,"compositionend",_),this.getElement=function(){return n},this.onContextMenu=function(e){h||(h=n.style.cssText),n.style.cssText="z-index:100000;"+(i.isIE?"opacity:0.1;":""),g(t.selection.isEmpty()),t._emit("nativecontextmenu",{target:t});var s=t.container.getBoundingClientRect(),o=function(e){n.style.left=e.clientX-s.left-2+"px",n.style.top=e.clientY-s.top-2+"px"};o(e);if(e.type!="mousedown")return;t.renderer.$keepTextAreaAtCursor&&(t.renderer.$keepTextAreaAtCursor=null),i.isWin&&r.capture(t.container,o,D)},this.onContextMenuClose=D,i.isGecko||r.addListener(n,"contextmenu",function(e){t.textInput.onContextMenu(e),D()})};t.TextInput=u}),ace.define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event","ace/mouse/dragdrop"],function(e,t,n){var r=e("../lib/event"),i=e("../lib/useragent"),s=e("./default_handlers").DefaultHandlers,o=e("./default_gutter_handler").GutterHandler,u=e("./mouse_event").MouseEvent,a=e("./dragdrop").DragdropHandler,f=function(e){this.editor=e,new s(this),new o(this),new a(this),r.addListener(e.container,"mousedown",function(t){return e.focus(),r.preventDefault(t)});var t=e.renderer.getMouseEventTarget();r.addListener(t,"click",this.onMouseEvent.bind(this,"click")),r.addListener(t,"mousemove",this.onMouseMove.bind(this,"mousemove")),r.addMultiMouseDownListener(t,[300,300,250],this,"onMouseEvent"),r.addMouseWheelListener(e.container,this.onMouseWheel.bind(this,"mousewheel"));var n=e.renderer.$gutter;r.addListener(n,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),r.addListener(n,"click",this.onMouseEvent.bind(this,"gutterclick")),r.addListener(n,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),r.addListener(n,"mousemove",this.onMouseEvent.bind(this,"guttermousemove"))};(function(){this.$scrollSpeed=1,this.setScrollSpeed=function(e){this.$scrollSpeed=e},this.getScrollSpeed=function(){return this.$scrollSpeed},this.onMouseEvent=function(e,t){this.editor._emit(e,new u(t,this.editor))},this.$dragDelay=250,this.setDragDelay=function(e){this.$dragDelay=e},this.getDragDelay=function(){return this.$dragDelay},this.onMouseMove=function(e,t){var n=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!n||!n.length)return;this.editor._emit(e,new u(t,this.editor))},this.onMouseWheel=function(e,t){var n=new u(t,this.editor);n.speed=this.$scrollSpeed*2,n.wheelX=t.wheelX,n.wheelY=t.wheelY,this.editor._emit(e,n)},this.setState=function(e){this.state=e},this.captureMouse=function(e,t){t&&this.setState(t),this.x=e.x,this.y=e.y,this.isMousePressed=!0;var n=this.editor.renderer;n.$keepTextAreaAtCursor&&(n.$keepTextAreaAtCursor=null);var s=this,o=function(e){s.x=e.clientX,s.y=e.clientY},u=function(e){clearInterval(f),s[s.state+"End"]&&s[s.state+"End"](e),s.$clickSelection=null,n.$keepTextAreaAtCursor==null&&(n.$keepTextAreaAtCursor=!0,n.$moveTextAreaToCursor()),s.isMousePressed=!1},a=function(){s[s.state]&&s[s.state]()};if(i.isOldIE&&e.domEvent.type=="dblclick"){setTimeout(function(){a(),u(e.domEvent)});return}r.capture(this.editor.container,o,u);var f=setInterval(a,20)}}).call(f.prototype),t.MouseHandler=f}),ace.define("ace/mouse/default_handlers",["require","exports","module","ace/lib/dom","ace/lib/useragent"],function(e,t,n){function o(e){e.$clickSelection=null;var t=e.editor;t.setDefaultHandler("mousedown",this.onMouseDown.bind(e)),t.setDefaultHandler("dblclick",this.onDoubleClick.bind(e)),t.setDefaultHandler("tripleclick",this.onTripleClick.bind(e)),t.setDefaultHandler("quadclick",this.onQuadClick.bind(e)),t.setDefaultHandler("mousewheel",this.onMouseWheel.bind(e));var n=["select","startSelect","drag","dragEnd","dragWait","dragWaitEnd","startDrag","focusWait"];n.forEach(function(t){e[t]=this[t]},this),e.selectByLines=this.extendSelectionBy.bind(e,"getLineRange"),e.selectByWords=this.extendSelectionBy.bind(e,"getWordRange"),e.$focusWaitTimout=250}function u(e,t,n,r){return Math.sqrt(Math.pow(n-e,2)+Math.pow(r-t,2))}function a(e,t){if(e.start.row==e.end.row)var n=2*t.column-e.start.column-e.end.column;else var n=2*t.row-e.start.row-e.end.row;return n<0?{cursor:e.start,anchor:e.end}:{cursor:e.end,anchor:e.start}}var r=e("../lib/dom"),i=e("../lib/useragent"),s=5;(function(){this.onMouseDown=function(e){var t=e.inSelection(),n=e.getDocumentPosition();this.mousedownEvent=e;var r=this.editor,i=e.getButton();if(i!==0){var s=r.getSelectionRange(),o=s.isEmpty();o&&(r.moveCursorToPosition(n),r.selection.clearSelection()),r.textInput.onContextMenu(e.domEvent);return}if(t&&!r.isFocused()){r.focus();if(this.$focusWaitTimout&&!this.$clickSelection)return this.setState("focusWait"),this.captureMouse(e),e.preventDefault()}return!t||this.$clickSelection||e.getShiftKey()?this.startSelect(n):t&&(this.mousedownEvent.time=(new Date).getTime(),this.setState("dragWait")),this.captureMouse(e),e.preventDefault()},this.startSelect=function(e){e=e||this.editor.renderer.screenToTextCoordinates(this.x,this.y),this.mousedownEvent.getShiftKey()?this.editor.selection.selectToPosition(e):this.$clickSelection||(this.editor.moveCursorToPosition(e),this.editor.selection.clearSelection()),this.setState("select")},this.select=function(){var e,t=this.editor,n=t.renderer.screenToTextCoordinates(this.x,this.y);if(this.$clickSelection){var r=this.$clickSelection.comparePoint(n);if(r==-1)e=this.$clickSelection.end;else if(r==1)e=this.$clickSelection.start;else{var i=a(this.$clickSelection,n);n=i.cursor,e=i.anchor}t.selection.setSelectionAnchor(e.row,e.column)}t.selection.selectToPosition(n),t.renderer.scrollCursorIntoView()},this.extendSelectionBy=function(e){var t,n=this.editor,r=n.renderer.screenToTextCoordinates(this.x,this.y),i=n.selection[e](r.row,r.column);if(this.$clickSelection){var s=this.$clickSelection.comparePoint(i.start),o=this.$clickSelection.comparePoint(i.end);if(s==-1&&o<=0){t=this.$clickSelection.end;if(i.end.row!=r.row||i.end.column!=r.column)r=i.start}else if(o==1&&s>=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=a(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.renderer.scrollCursorIntoView()},this.startDrag=function(){var e=this.editor;this.setState("drag"),this.dragRange=e.getSelectionRange();var t=e.getSelectionStyle();this.dragSelectionMarker=e.session.addMarker(this.dragRange,"ace_selection",t),e.clearSelection(),r.addCssClass(e.container,"ace_dragging"),this.$dragKeybinding||(this.$dragKeybinding={handleKeyboard:function(e,t,n,r){if(n=="esc")return{command:this.command}},command:{exec:function(e){var t=e.$mouseHandler;t.dragCursor=null,t.dragEnd(),t.startSelect()}}}),e.keyBinding.addKeyboardHandler(this.$dragKeybinding)},this.focusWait=function(){var e=u(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=(new Date).getTime();(e>s||t-this.mousedownEvent.time>this.$focusWaitTimout)&&this.startSelect()},this.dragWait=function(e){var t=u(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),n=(new Date).getTime(),r=this.editor;t>s?this.startSelect(this.mousedownEvent.getDocumentPosition()):n-this.mousedownEvent.time>r.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(e){this.mousedownEvent.domEvent=e,this.startSelect()},this.drag=function(){var e=this.editor;this.dragCursor=e.renderer.screenToTextCoordinates(this.x,this.y),e.moveCursorToPosition(this.dragCursor),e.renderer.scrollCursorIntoView()},this.dragEnd=function(e){var t=this.editor,n=this.dragCursor,i=this.dragRange;r.removeCssClass(t.container,"ace_dragging"),t.session.removeMarker(this.dragSelectionMarker),t.keyBinding.removeKeyboardHandler(this.$dragKeybinding);if(!n)return;t.clearSelection();if(e&&(e.ctrlKey||e.altKey)){var s=t.session,o=i;o.end=s.insert(n,s.getTextRange(i)),o.start=n}else{if(i.contains(n.row,n.column))return;var o=t.moveText(i,n)}if(!o)return;t.selection.setSelectionRange(o)},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);if(i){i.isEmpty()&&(i.start.column--,i.end.column++),this.$clickSelection=i,this.setState("select");return}this.$clickSelection=n.selection.getWordRange(t.row,t.column),this.setState("selectByWords")},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState("selectByLines"),this.$clickSelection=n.selection.getLineRange(t.row)},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("null")},this.onMouseWheel=function(e){if(e.getShiftKey()||e.getAccelKey())return;var t=this.editor,n=t.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);if(n)this.$passScrollEvent=!1;else{if(this.$passScrollEvent)return;if(!this.$scrollStopTimeout){var r=this;this.$scrollStopTimeout=setTimeout(function(){r.$passScrollEvent=!0,r.$scrollStopTimeout=null},200)}}return t.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.preventDefault()}}).call(o.prototype),t.DefaultHandlers=o}),ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/event"],function(e,t,n){function s(e){function f(){u=r.createElement("div"),u.className="ace_gutter-tooltip",u.style.maxWidth="500px",u.style.display="none",t.container.appendChild(u)}function l(){u||f();var e=o.getDocumentPosition().row,r=n.$annotations[e];if(!r)return c();var i=t.session.getLength();if(e==i){var s=t.renderer.pixelToScreenCoordinates(0,o.y).row,l=o.$pos;if(s>t.session.documentToScreenRow(l.row,l.column))return c()}if(a==r)return;a=r.text.join("<br/>"),u.style.display="block",u.innerHTML=a,t.on("mousewheel",c),h(o)}function c(){s&&(s=clearTimeout(s)),a&&(u.style.display="none",a=null,t.removeEventListener("mousewheel",c))}function h(e){var n=t.renderer.$gutter.getBoundingClientRect();u.style.left=e.x-n.left+15+"px",e.y+3*t.renderer.lineHeight+15<n.bottom?(u.style.bottom="",u.style.top=e.y-n.top+15+"px"):(u.style.top="",u.style.bottom=n.bottom-e.y+5+"px")}var t=e.editor,n=t.renderer.$gutterLayer;e.editor.setDefaultHandler("guttermousedown",function(r){if(!t.isFocused())return;var i=n.getRegion(r);if(i)return;var s=r.getDocumentPosition().row,o=t.session.selection;if(r.getShiftKey())o.selectTo(s,0);else{if(r.domEvent.detail==2)return t.selectAll(),r.preventDefault();e.$clickSelection=t.selection.getLineRange(s)}return e.captureMouse(r,"selectByLines"),r.preventDefault()});var s,o,u,a;e.editor.setDefaultHandler("guttermousemove",function(t){var n=t.domEvent.target||t.domEvent.srcElement;if(r.hasCssClass(n,"ace_fold-widget"))return c();a&&h(t),o=t;if(s)return;s=setTimeout(function(){s=null,o&&!e.isMousePressed?l():c()},50)}),i.addListener(t.renderer.$gutter,"mouseout",function(e){o=null;if(!a||s)return;s=setTimeout(function(){s=null,c()},50)})}var r=e("../lib/dom"),i=e("../lib/event");t.GutterHandler=s}),ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,t,n){var r=e("../lib/event"),i=e("../lib/useragent"),s=t.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){r.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){r.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos?this.$pos:(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var e=this.editor;if(e.getReadOnly())this.$inSelection=!1;else{var t=e.getSelectionRange();if(t.isEmpty())this.$inSelection=!1;else{var n=this.getDocumentPosition();this.$inSelection=t.contains(n.row,n.column)}}return this.$inSelection},this.getButton=function(){return r.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=i.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}).call(s.prototype)}),ace.define("ace/mouse/dragdrop",["require","exports","module","ace/lib/event"],function(e,t,n){var r=e("../lib/event"),i=function(e){var t=e.editor,n,i,s,o,u,a,f,l=0,c=t.container;r.addListener(c,"dragenter",function(e){l++;if(!n){u=t.getSelectionRange(),a=t.selection.isBackwards();var i=t.getSelectionStyle();n=t.session.addMarker(u,"ace_selection",i),t.clearSelection(),clearInterval(o),o=setInterval(h,20)}return r.preventDefault(e)}),r.addListener(c,"dragover",function(e){return i=e.clientX,s=e.clientY,r.preventDefault(e)});var h=function(){f=t.renderer.screenToTextCoordinates(i,s),t.moveCursorToPosition(f),t.renderer.scrollCursorIntoView()};r.addListener(c,"dragleave",function(e){l--;if(l>0)return;return console.log(e.type,l,e.target),clearInterval(o),t.session.removeMarker(n),n=null,t.selection.setSelectionRange(u,a),r.preventDefault(e)}),r.addListener(c,"drop",function(e){return console.log(e.type,l,e.target),l=0,clearInterval(o),t.session.removeMarker(n),n=null,u.end=t.session.insert(f,e.dataTransfer.getData("Text")),u.start=f,t.focus(),t.selection.setSelectionRange(u),r.preventDefault(e)})};t.DragdropHandler=i}),ace.define("ace/mouse/fold_handler",["require","exports","module"],function(e,t,n){function r(e){e.on("click",function(t){var n=t.getDocumentPosition(),r=e.session,i=r.getFoldAt(n.row,n.column,1);i&&(t.getAccelKey()?r.removeFold(i):r.expandFold(i),t.stop())}),e.on("guttermousedown",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),t.stop()}}),e.on("gutterdblclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session,s=i.foldWidgets;if(!s||s[r])return;var o=r-1,u;while(o>=0){var a=s[o];a==null&&(a=s[o]=i.getFoldWidget());if(a=="start"){var f=i.getFoldWidgetRange(o);u||(u=f);if(f&&f.end.row>=r)break}o--}o==-1&&(f=u);if(f){var r=f.start.row,l=i.getFoldAt(r,i.getLine(r).length,1);l?i.removeFold(l):(i.addFold("...",f),e.renderer.scrollCursorIntoView({row:f.start.row,column:0}))}t.stop()}})}t.FoldHandler=r}),ace.define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"],function(e,t,n){var r=e("../lib/keys"),i=e("../lib/event"),s=function(e){this.$editor=e,this.$data={},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0),this.$data={editor:this.$editor}},this.setKeyboardHandler=function(e){if(this.$handlers[this.$handlers.length-1]==e)return;while(this.$handlers[1])this.removeKeyboardHandler(this.$handlers[1]);this.addKeyboardHandler(e,1)},this.addKeyboardHandler=function(e,t){if(!e)return;var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.$callKeyboardHandlers=function(e,t,n,r){var s;for(var o=this.$handlers.length;o--;){s=this.$handlers[o].handleKeyboard(this.$data,e,t,n,r);if(s&&s.command)break}if(!s||!s.command)return!1;var u=!1,a=this.$editor.commands;return s.command!="null"?u=a.exec(s.command,this.$editor,s.args,r):u=s.passEvent!=1,u&&r&&e!=-1&&i.stopEvent(r),u},this.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);this.$callKeyboardHandlers(t,i,n,e)},this.onTextInput=function(e){var t=this.$callKeyboardHandlers(-1,e);t||this.$editor.commands.exec("insertstring",this.$editor,e)}}).call(s.prototype),t.KeyBinding=s}),ace.define("ace/edit_session",["require","exports","module","ace/config","ace/lib/oop","ace/lib/lang","ace/lib/net","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"],function(e,t,n){var r=e("./config"),i=e("./lib/oop"),s=e("./lib/lang"),o=e("./lib/net"),u=e("./lib/event_emitter").EventEmitter,a=e("./selection").Selection,f=e("./mode/text").Mode,l=e("./range").Range,c=e("./document").Document,h=e("./background_tokenizer").BackgroundTokenizer,p=e("./search_highlight").SearchHighlight,d=function(e,t){this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$undoSelect=!0,this.$foldData=[],this.$foldData.toString=function(){var e="";return this.forEach(function(t){e+="\n"+t.toString()}),e},this.on("changeFold",this.onChangeFold.bind(this)),this.$onChange=this.onChange.bind(this);if(typeof e!="object"||!e.getLine)e=new c(e);this.setDocument(e),this.selection=new a(this),this.setMode(t)};(function(){function y(e){return e<4352?!1:e>=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}i.implement(this,u),this.setDocument=function(e){this.doc&&this.doc.removeListener("change",this.$onChange),this.doc=e,e.on("change",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$getRowCacheIndex(this.$docRowCache,e)+1,n=this.$docRowCache.length;this.$docRowCache.splice(t,n),this.$screenRowCache.splice(t,n)},this.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t<s))return i;r=i-1}}return n-1},this.resetCaches=function(){this.$modified=!0,this.$wrapData=[],this.$rowLengthCache=[],this.$resetRowCache(0),this.bgTokenizer&&this.bgTokenizer.start(0)},this.onChangeFold=function(e){var t=e.data;this.$resetRowCache(t.start.row)},this.onChange=function(e){var t=e.data;this.$modified=!0,this.$resetRowCache(t.range.start.row);var n=this.$updateInternalDataOnChange(e);!this.$fromUndo&&this.$undoManager&&!t.ignore&&(this.$deltasDoc.push(t),n&&n.length!=0&&this.$deltasFold.push({action:"removeFolds",folds:n}),this.$informUndoManager.schedule()),this.bgTokenizer.$updateOnChange(t),this._emit("change",e)},this.setValue=function(e){this.doc.setValue(e),this.selection.moveCursorTo(0,0),this.selection.clearSelection(),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(e){return this.bgTokenizer.getState(e)},this.getTokens=function(e){return this.bgTokenizer.getTokens(e)},this.getTokenAt=function(e,t){var n=this.bgTokenizer.getTokens(e),r,i=0;if(t==null)s=n.length-1,i=this.getLine(e).length;else for(var s=0;s<n.length;s++){i+=n[s].value.length;if(i>=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},this.setUndoManager=function(e){this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:"fold",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:"doc",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:"aceupdate",args:[t.$deltas,t]}),t.$deltas=[]},this.$informUndoManager=s.deferredCall(this.$syncInformUndoManager)}},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?s.stringRepeat(" ",this.getTabSize()):" "},this.$useSoftTabs=!0,this.setUseSoftTabs=function(e){if(this.$useSoftTabs===e)return;this.$useSoftTabs=e},this.getUseSoftTabs=function(){return this.$useSoftTabs},this.$tabSize=4,this.setTabSize=function(e){if(isNaN(e)||this.$tabSize===e)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._emit("changeTabSize")},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize==0},this.$overwrite=!1,this.setOverwrite=function(e){if(this.$overwrite==e)return;this.$overwrite=e,this._emit("changeOverwrite")},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=""),this.$decorations[e]+=" "+t,this._emit("changeBreakpoint",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||"").replace(" "+t,""),this._emit("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t<e.length;t++)this.$breakpoints[e[t]]="ace_breakpoint";this._emit("changeBreakpoint",{})},this.clearBreakpoints=function(){this.$breakpoints=[],this._emit("changeBreakpoint",{})},this.setBreakpoint=function(e,t){t===undefined&&(t="ace_breakpoint"),t?this.$breakpoints[e]=t:delete this.$breakpoints[e],this._emit("changeBreakpoint",{})},this.clearBreakpoint=function(e){delete this.$breakpoints[e],this._emit("changeBreakpoint",{})},this.addMarker=function(e,t,n,r){var i=this.$markerId++,s={range:e,type:n||"line",renderer:typeof n=="function"?n:null,clazz:t,inFront:!!r,id:i};return r?(this.$frontMarkers[i]=s,this._emit("changeFrontMarker")):(this.$backMarkers[i]=s,this._emit("changeBackMarker")),i},this.addDynamicMarker=function(e,t){if(!e.update)return;var n=this.$markerId++;return e.id=n,e.inFront=!!t,t?(this.$frontMarkers[n]=e,this._emit("changeFrontMarker")):(this.$backMarkers[n]=e,this._emit("changeBackMarker")),e},this.removeMarker=function(e){var t=this.$frontMarkers[e]||this.$backMarkers[e];if(!t)return;var n=t.inFront?this.$frontMarkers:this.$backMarkers;t&&(delete n[e],this._emit(t.inFront?"changeFrontMarker":"changeBackMarker"))},this.getMarkers=function(e){return e?this.$frontMarkers:this.$backMarkers},this.highlight=function(e){if(!this.$searchHighlight){var t=new p(null,"ace_selected-word","text");this.$searchHighlight=this.addDynamicMarker(t)}this.$searchHighlight.setRegexp(e)},this.highlightLines=function(e,t,n,r){typeof t!="number"&&(n=t,t=e),n||(n="ace_step");var i=new l(e,0,t,Infinity),s=this.addMarker(i,n,"fullLine",r);return i.id=s,i},this.setAnnotations=function(e){this.$annotations=e,this._emit("changeAnnotation",{})},this.getAnnotations=function(){return this.$annotations||[]},this.clearAnnotations=function(){this.$annotations={},this._emit("changeAnnotation",{})},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r?\n)/m);t?this.$autoNewLine=t[1]:this.$autoNewLine="\n"},this.getWordRange=function(e,t){var n=this.getLine(e),r=!1;t>0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\s+$/.test(n.slice(t-1,t+1)))var i=/\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(o<n.length&&n.charAt(o).match(i))o++;return new l(e,s,e,o)},this.getAWordRange=function(e,t){var n=this.getWordRange(e,t),r=this.getLine(n.end.row);while(r.charAt(n.end.column).match(/[ \t]/))n.end.column+=1;return n},this.setNewLineMode=function(e){this.doc.setNewLineMode(e)},this.getNewLineMode=function(){return this.doc.getNewLineMode()},this.$useWorker=!0,this.setUseWorker=function(e){if(this.$useWorker==e)return;this.$useWorker=e,this.$stopWorker(),e&&this.$startWorker()},this.getUseWorker=function(){return this.$useWorker},this.onReloadTokenizer=function(e){var t=e.data;this.bgTokenizer.start(t.first),this._emit("tokenizerUpdate",e)},this.$modes={},this._loadMode=function(t,n){function a(e){if(i.$modes[t])return n(i.$modes[t]);i.$modes[t]=new e.Mode,i.$modes[t].$id=t,i._emit("loadmode",{name:t,mode:i.$modes[t]}),n(i.$modes[t])}function l(e,t){if(!r.get("packaged"))return t();o.loadScript(r.moduleUrl(e,"mode"),t)}this.$modes["null"]||(this.$modes["null"]=this.$modes["ace/mode/text"]=new f);if(this.$modes[t])return n(this.$modes[t]);var i=this,s;try{s=e(t)}catch(u){}if(s&&s.Mode)return a(s);this.$mode||this.$setModePlaceholder(),l(t,function(){e([t],a)})},this.$setModePlaceholder=function(){this.$mode=this.$modes["null"];var e=this.$mode.getTokenizer();if(!this.bgTokenizer){this.bgTokenizer=new h(e);var t=this;this.bgTokenizer.addEventListener("update",function(e){t._emit("tokenizerUpdate",e)})}else this.bgTokenizer.setTokenizer(e);this.bgTokenizer.setDocument(this.getDocument()),this.tokenRe=this.$mode.tokenRe,this.nonTokenRe=this.$mode.nonTokenRe},this.$mode=null,this.$modeId=null,this.setMode=function(e){e=e||"null";if(typeof e=="string"){if(this.$modeId==e)return;this.$modeId=e;var t=this;this._loadMode(e,function(n){if(t.$modeId!==e)return;t.setMode(n)});return}if(this.$mode===e)return;this.$mode=e,this.$modeId=e.$id,this.$stopWorker(),this.$useWorker&&this.$startWorker();var n=e.getTokenizer();if(n.addEventListener!==undefined){var r=this.onReloadTokenizer.bind(this);n.addEventListener("update",r)}if(!this.bgTokenizer){this.bgTokenizer=new h(n);var t=this;this.bgTokenizer.addEventListener("update",function(e){t._emit("tokenizerUpdate",e)})}else this.bgTokenizer.setTokenizer(n);this.bgTokenizer.setDocument(this.getDocument()),this.bgTokenizer.start(0),this.tokenRe=e.tokenRe,this.nonTokenRe=e.nonTokenRe,this.$setFolding(e.foldingRules),this._emit("changeMode")},this.$stopWorker=function(){this.$worker&&this.$worker.terminate(),this.$worker=null},this.$startWorker=function(){if(typeof Worker!="undefined"&&!e.noWorker)try{this.$worker=this.$mode.createWorker(this)}catch(t){console.log("Could not load worker"),console.log(t),this.$worker=null}else this.$worker=null},this.getMode=function(){return this.$mode},this.$scrollTop=0,this.setScrollTop=function(e){e=Math.round(Math.max(0,e));if(this.$scrollTop===e)return;this.$scrollTop=e,this._emit("changeScrollTop",e)},this.getScrollTop=function(){return this.$scrollTop},this.$scrollLeft=0,this.setScrollLeft=function(e){e=Math.round(Math.max(0,e));if(this.$scrollLeft===e)return;this.$scrollLeft=e,this._emit("changeScrollLeft",e)},this.getScrollLeft=function(){return this.$scrollLeft},this.getScreenWidth=function(){return this.$computeWidth(),this.screenWidth},this.$computeWidth=function(e){if(this.$modified||e){this.$modified=!1;if(this.$useWrapMode)return this.screenWidth=this.$wrapLimit;var t=this.doc.getAllLines(),n=this.$rowLengthCache,r=0,i=0,s=this.$foldData[i],o=s?s.start.row:Infinity,u=t.length;for(var a=0;a<u;a++){if(a>o){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=e.length-1;r!=-1;r--){var i=e[r];i.group=="doc"?(this.doc.revertDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!0,n)):i.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=0;r<e.length;r++){var i=e[r];i.group=="doc"&&(this.doc.applyDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!1,n))}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.setUndoSelect=function(e){this.$undoSelect=e},this.$getUndoSelection=function(e,t,n){function r(e){var n=e.action=="insertText"||e.action=="insertLines";return t?!n:n}var i=e[0],s,o,u=!1;r(i)?(s=i.range.clone(),u=!0):(s=l.fromPoints(i.range.start,i.range.start),u=!1);for(var a=1;a<e.length;a++)i=e[a],r(i)?(o=i.range.start,s.compare(o.row,o.column)==-1&&s.setStart(i.range.start),o=i.range.end,s.compare(o.row,o.column)==1&&s.setEnd(i.range.end),u=!0):(o=i.range.start,s.compare(o.row,o.column)==-1&&(s=l.fromPoints(i.range.start,i.range.start)),u=!1);if(n!=null){var f=n.compareRange(s);f==1?s.setStart(n.start):f==-1&&s.setEnd(n.end)}return s},this.replace=function(e,t){return this.doc.replace(e,t)},this.moveText=function(e,t){var n=this.getTextRange(e);this.remove(e);var r=t.row,i=t.column;!e.isMultiLine()&&e.start.row==r&&e.end.column<i&&(i-=n.length);if(e.isMultiLine()&&e.end.row<r){var s=this.doc.$split(n);r-=s.length-1}var o=r+e.end.row-e.start.row,u=e.isMultiLine()?e.end.column:i+e.end.column-e.start.column,a=new l(r,i,o,u);return this.insert(a.start,n),a},this.indentRows=function(e,t,n){n=n.replace(/\t/g,this.getTabString());for(var r=e;r<=t;r++)this.insert({row:r,column:0},n)},this.outdentRows=function(e){var t=e.collapseRows(),n=new l(0,0,0,0),r=this.getTabSize();for(var i=t.start.row;i<=t.end.row;++i){var s=this.getLine(i);n.start.row=i,n.end.row=i;for(var o=0;o<r;++o)if(s.charAt(o)!=" ")break;o<r&&s.charAt(o)==" "?(n.start.column=o,n.end.column=o+1):(n.start.column=0,n.end.column=o),this.remove(n)}},this.moveLinesUp=function(e,t){if(e<=0)return 0;var n=this.doc.removeLines(e,t);return this.doc.insertLines(e-1,n),-1},this.moveLinesDown=function(e,t){if(t>=this.doc.getLength()-1)return 0;var n=this.doc.removeLines(e,t);return this.doc.insertLines(e+1,n),1},this.duplicateLines=function(e,t){var e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t),n=this.getLines(e,t);this.doc.insertLines(e,n);var r=t-e+1;return r},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=[];for(var n=0;n<t;n++)this.$wrapData.push([]);this.$updateWrapData(0,t-1)}this._emit("changeWrapMode")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){if(this.$wrapLimitRange.min!==e||this.$wrapLimitRange.max!==t)this.$wrapLimitRange.min=e,this.$wrapLimitRange.max=t,this.$modified=!0,this._emit("changeWrapMode")},this.adjustWrapLimit=function(e){var t=this.$constrainWrapLimit(e);return t!=this.$wrapLimit&&t>0?(this.$wrapLimit=t,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._emit("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(e){var t=this.$wrapLimitRange.min;t&&(e=Math.max(t,e));var n=this.$wrapLimitRange.max;return n&&(e=Math.min(n,e)),Math.max(1,e)},this.getWrapLimit=function(){return this.$wrapLimit},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n,r=e.data.action,i=e.data.range.start.row,s=e.data.range.end.row,o=e.data.range.start,u=e.data.range.end,a=null;r.indexOf("Lines")!=-1?(r=="insertLines"?s=i+e.data.lines.length:s=i,n=e.data.lines?e.data.lines.length:s-i):n=s-i;if(n!=0)if(r.indexOf("remove")!=-1){this[t?"$wrapData":"$rowLengthCache"].splice(i,n);var f=this.$foldData;a=this.getFoldsInRange(e.data.range),this.removeFolds(a);var l=this.getFoldLine(u.row),c=0;if(l){l.addRemoveChars(u.row,u.column,o.column-u.column),l.shiftRow(-n);var h=this.getFoldLine(i);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c<f.length;c++){var l=f[c];l.start.row>=u.row&&l.shiftRow(-n)}s=i}else{var p;if(t){p=[i,0];for(var d=0;d<n;d++)p.push([]);this.$wrapData.splice.apply(this.$wrapData,p)}else p=Array(n),p.unshift(i,0),this.$rowLengthCache.splice.apply(this.$rowLengthCache,p);var f=this.$foldData,l=this.getFoldLine(i),c=0;if(l){var v=l.range.compareInside(o.row,o.column);v==0?(l=l.split(o.row,o.column),l.shiftRow(n),l.addRemoveChars(s,0,u.column-o.column)):v==-1&&(l.addRemoveChars(i,0,u.column-o.column),l.shiftRow(n)),c=f.indexOf(l)+1}for(c;c<f.length;c++){var l=f[c];l.start.row>=i&&l.shiftRow(n)}}else{n=Math.abs(e.data.range.start.column-e.data.range.end.column),r.indexOf("remove")!=-1&&(a=this.getFoldsInRange(e.data.range),this.removeFolds(a),n=-n);var l=this.getFoldLine(i);l&&l.addRemoveChars(i,o.column,n)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),t?this.$updateWrapData(i,s):this.$updateRowLengthCache(i,s),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var n=this.doc.getAllLines(),r=this.getTabSize(),i=this.$wrapData,o=this.$wrapLimit,u,f,l=e;t=Math.min(t,n.length-1);while(l<=t){f=this.getFoldLine(l,f);if(!f)u=this.$getDisplayTokens(s.stringTrimRight(n[l])),i[l]=this.$computeWrapSplits(u,o,r),l++;else{u=[],f.walk(function(e,t,r,i){var s;if(e!=null){s=this.$getDisplayTokens(e,u.length),s[0]=a;for(var o=1;o<s.length;o++)s[o]=c}else s=this.$getDisplayTokens(n[t].substring(i,r),u.length);u=u.concat(s)}.bind(this),f.end.row,n[f.end.row].length+1);while(u.length!=0&&u[u.length-1]>=v)u.pop();i[f.start.row]=this.$computeWrapSplits(u,o,r),l=f.end.row+1}}};var t=1,n=2,a=3,c=4,d=9,v=10,m=11,g=12;this.$computeWrapSplits=function(e,t){function o(t){var r=e.slice(i,t),o=r.length;r.join("").replace(/12/g,function(){o-=1}).replace(/2/g,function(){o-=1}),s+=o,n.push(s),i=t}if(e.length==0)return[];var n=[],r=e.length,i=0,s=0;while(r-i>t){var u=i+t;if(e[u]>=v){while(e[u]>=v)u++;o(u);continue}if(e[u]==a||e[u]==c){for(u;u!=i-1;u--)if(e[u]==a)break;if(u>i){o(u);continue}u=i+t;for(u;u<e.length;u++)if(e[u]!=c)break;if(u==e.length)break;o(u);continue}var f=Math.max(u-10,i-1);while(u>f&&e[u]<a)u--;while(u>f&&e[u]==d)u--;if(u>f){o(++u);continue}u=i+t,o(u)}return n},this.$getDisplayTokens=function(e,r){var i=[],s;r=r||0;for(var o=0;o<e.length;o++){var u=e.charCodeAt(o);if(u==9){s=this.getScreenTabSize(i.length+r),i.push(m);for(var a=1;a<s;a++)i.push(g)}else u==32?i.push(v):u>39&&u<48||u>57&&u<64?i.push(d):u>=4352&&y(u)?i.push(t,n):i.push(t)}return i},this.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i<e.length;i++){r=e.charCodeAt(i),r==9?n+=this.getScreenTabSize(n):r>=4352&&y(r)?n+=2:n+=1;if(n>t)break}return[n,i]},this.getRowLength=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},this.getScreenLastRowColumn=function(e){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE);return this.documentToScreenColumn(t.row,t.column)},this.getDocumentLastRowColumn=function(e,t){var n=this.documentToScreenRow(e,t);return this.getScreenLastRowColumn(n)},this.getDocumentLastRowColumnPosition=function(e,t){var n=this.documentToScreenRow(e,t);return this.screenToDocumentPosition(n,Number.MAX_VALUE/10)},this.getRowSplitData=function(e){return this.$useWrapMode?this.$wrapData[e]:undefined},this.getScreenTabSize=function(e){return this.$tabSize-e%this.$tabSize},this.screenToDocumentRow=function(e,t){return this.screenToDocumentPosition(e,t).row},this.screenToDocumentColumn=function(e,t){return this.screenToDocumentPosition(e,t).column},this.screenToDocumentPosition=function(e,t){if(e<0)return{row:0,column:0};var n,r=0,i=0,s,o=0,u=0,a=this.$screenRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var o=a[f],r=this.$docRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getLength()-1,p=this.getNextFoldLine(r),d=p?p.start.row:Infinity;while(o<=e){u=this.getRowLength(r);if(o+u-1>=e||r>=h)break;o+=u,r++,r>d&&(r=p.end.row+1,p=this.getNextFoldLine(r,p),d=p?p.start.row:Infinity),c&&(this.$docRowCache.push(r),this.$screenRowCache.push(o))}if(p&&p.start.row<=r)n=this.getFoldDisplayLine(p),r=p.start.row;else{if(o+u<=e||r>h)return{row:h,column:this.getLine(h).length};n=this.getLine(r),p=null}if(this.$useWrapMode){var v=this.$wrapData[r];v&&(s=v[e-o],e>o&&v.length&&(i=v[e-o-1]||v[v.length-1],n=n.substring(i)))}return i+=this.$getStringScreenWidth(n,t)[1],this.$useWrapMode&&i>=s&&(i=s-1),p?p.idxToPosition(i):{row:r,column:i}},this.documentToScreenPosition=function(e,t){if(typeof t=="undefined")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u<e){if(u>=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d="";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);if(this.$useWrapMode){var v=this.$wrapData[i],m=0;while(d.length>=v[m])r++,m++;d=d.substring(v[m-1]||0,d.length)}return{row:r,column:this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;r<n.length;r++)t=n[r],e-=t.end.row-t.start.row}else{var i=this.$wrapData.length,s=0,r=0,t=this.$foldData[r++],o=t?t.start.row:Infinity;while(s<i)e+=this.$wrapData[s].length+1,s++,s>o&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}return e}}).call(d.prototype),e("./edit_session/folding").Folding.call(d.prototype),e("./edit_session/bracket_match").BracketMatch.call(d.prototype),t.EditSession=d}),ace.define("ace/config",["require","exports","module","ace/lib/lang"],function(e,t,n){"no use strict";function o(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}var r=e("./lib/lang"),i=function(){return this}(),s={packaged:!1,workerPath:null,modePath:null,themePath:null,basePath:"",suffix:".js",$moduleUrls:{}};t.get=function(e){if(!s.hasOwnProperty(e))throw new Error("Unknown config key: "+e);return s[e]},t.set=function(e,t){if(!s.hasOwnProperty(e))throw new Error("Unknown config key: "+e);s[e]=t},t.all=function(){return r.copyObject(s)},t.moduleUrl=function(e,t){if(s.$moduleUrls[e])return s.$moduleUrls[e];var n=e.split("/");t=t||n[n.length-2]||"";var r=n[n.length-1].replace(t,"").replace(/(^[\-_])|([\-_]$)/,"");!r&&n.length>1&&(r=n[n.length-2]);var i=s[t+"Path"];return i==null&&(i=s.basePath),i&&i.slice(-1)!="/"&&(i+="/"),i+t+"-"+r+this.get("suffix")},t.setModuleUrl=function(e,t){return s.$moduleUrls[e]=t},t.init=function(){s.packaged=e.packaged||n.packaged||i.define&&define.packaged;if(!i.document)return"";var r={},u="",a=document.getElementsByTagName("script");for(var f=0;f<a.length;f++){var l=a[f],c=l.src||l.getAttribute("src");if(!c)continue;var h=l.attributes;for(var p=0,d=h.length;p<d;p++){var v=h[p];v.name.indexOf("data-ace-")===0&&(r[o(v.name.replace(/^data-ace-/,""))]=v.value)}var m=c.match(/^(.*)\/ace(\-\w+)?\.js(\?|$)/);m&&(u=m[1])}u&&(r.base=r.base||u,r.packaged=!0),r.workerPath=r.workerPath||r.base,r.modePath=r.modePath||r.base,r.themePath=r.themePath||r.base,delete r.base;for(var g in r)typeof r[g]!="undefined"&&t.set(g,r[g])}}),ace.define("ace/lib/net",["require","exports","module","ace/lib/useragent"],function(e,t,n){var r=e("./useragent");t.get=function(e,n){var r=t.createXhr();r.open("GET",e,!0),r.onreadystatechange=function(e){r.readyState===4&&n(r.responseText)},r.send(null)};var i=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];t.createXhr=function(){var e,t,n;if(typeof XMLHttpRequest!="undefined")return new XMLHttpRequest;for(t=0;t<3;t++){n=i[t];try{e=new ActiveXObject(n)}catch(r){}if(e){i=[n];break}}if(!e)throw new Error("createXhr(): XMLHttpRequest not available");return e},t.loadScript=function(e,t){var n=document.getElementsByTagName("head")[0],i=document.createElement("script");i.src=e,n.appendChild(i),r.isOldIE?i.onreadystatechange=function(){this.readyState=="loaded"&&t()}:i.onload=t}}),ace.define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){var r={};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry=this._eventRegistry||{},this._defaultHandlers=this._defaultHandlers||{};var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=function(){this.propagationStopped=!0}),t.preventDefault||(t.preventDefault=function(){this.defaultPrevented=!0});for(var i=0;i<n.length;i++){n[i](t);if(t.propagationStopped)break}if(r&&!t.defaultPrevented)return r(t)},r.setDefaultHandler=function(e,t){this._defaultHandlers=this._defaultHandlers||{};if(this._defaultHandlers[e])throw new Error("The default handler for '"+e+"' is already set");this._defaultHandlers[e]=t},r.on=r.addEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];n||(n=this._eventRegistry[e]=[]),n.indexOf(t)==-1&&n.push(t)},r.removeListener=r.removeEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];if(!n)return;var r=n.indexOf(t);r!==-1&&n.splice(r,1)},r.removeAllListeners=function(e){this._eventRegistry&&(this._eventRegistry[e]=[])},t.EventEmitter=r}),ace.define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/lang"),s=e("./lib/event_emitter").EventEmitter,o=e("./range").Range,u=function(e){this.session=e,this.doc=e.getDocument(),this.clearSelection(),this.lead=this.selectionLead=this.doc.createAnchor(0,0),this.anchor=this.selectionAnchor=this.doc.createAnchor(0,0);var t=this;this.lead.on("change",function(e){t._emit("changeCursor"),t.$isEmpty||t._emit("changeSelection"),!t.$keepDesiredColumnOnChange&&e.old.column!=e.value.column&&(t.$desiredColumn=null)}),this.selectionAnchor.on("change",function(){t.$isEmpty||t._emit("changeSelection")})};(function(){r.implement(this,s),this.isEmpty=function(){return this.$isEmpty||this.anchor.row==this.lead.row&&this.anchor.column==this.lead.column},this.isMultiLine=function(){return this.isEmpty()?!1:this.getRange().isMultiLine()},this.getCursor=function(){return this.lead.getPosition()},this.setSelectionAnchor=function(e,t){this.anchor.setPosition(e,t),this.$isEmpty&&(this.$isEmpty=!1,this._emit("changeSelection"))},this.getSelectionAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.anchor.getPosition()},this.getSelectionLead=function(){return this.lead.getPosition()},this.shiftSelection=function(e){if(this.$isEmpty){this.moveCursorTo(this.lead.row,this.lead.column+e);return}var t=this.getSelectionAnchor(),n=this.getSelectionLead(),r=this.isBackwards();(!r||t.column!==0)&&this.setSelectionAnchor(t.row,t.column+e),(r||n.column!==0)&&this.$moveSelection(function(){this.moveCursorTo(n.row,n.column+e)})},this.isBackwards=function(){var e=this.anchor,t=this.lead;return e.row>t.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t=="undefined"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e=="number"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column==0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(e.column-n,e.column).split(" ").length-1==n?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row<this.doc.getLength()-1&&this.moveCursorTo(this.lead.row+1,0);else{var n=this.session.getTabSize(),e=this.lead;this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(e.column,e.column+n).split(" ").length-1==n?this.moveCursorBy(0,n):this.moveCursorBy(0,1)}},this.moveCursorLineStart=function(){var e=this.lead.row,t=this.lead.column,n=this.session.documentToScreenRow(e,t),r=this.session.screenToDocumentPosition(n,0),i=this.session.getDisplayLine(e,null,r.row,r.column),s=i.match(/^\s*/);s[0].length==t?this.moveCursorTo(r.row,r.column):this.moveCursorTo(r.row,r.column+s[0].length)},this.moveCursorLineEnd=function(){var e=this.lead,t=this.session.getDocumentLastRowColumnPosition(e.row,e.column);if(this.lead.column==t.column){var n=this.session.getLine(t.row);if(t.column==n.length){var r=n.search(/\s+$/);r>0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var s=this.session.getFoldAt(e,t,1);if(s){this.moveCursorTo(s.end.row,s.end.column);return}if(i=this.session.nonTokenRe.exec(r))t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t);if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e<this.doc.getLength()-1&&this.moveCursorWordRight();return}if(i=this.session.tokenRe.exec(r))t+=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.moveCursorLongWordLeft=function(){var e=this.lead.row,t=this.lead.column,n;if(n=this.session.getFoldAt(e,t,-1)){this.moveCursorTo(n.start.row,n.start.column);return}var r=this.session.getFoldStringAt(e,t,-1);r==null&&(r=this.doc.getLine(e).substring(0,t));var s=i.stringReverse(r),o;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;if(o=this.session.nonTokenRe.exec(s))t-=this.session.nonTokenRe.lastIndex,s=s.slice(this.session.nonTokenRe.lastIndex),this.session.nonTokenRe.lastIndex=0;if(t<=0){this.moveCursorTo(e,0),this.moveCursorLeft(),e>0&&this.moveCursorWordLeft();return}if(o=this.session.tokenRe.exec(s))t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t,n=0,r,i=/\s/,s=this.session.tokenRe;s.lastIndex=0;if(t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{while((r=e[n])&&i.test(r))n++;if(n<=1){s.lastIndex=0;while((r=e[n])&&!s.test(r)){s.lastIndex=0,n++;if(i.test(r)){if(n>2){n--;break}while((r=e[n])&&i.test(r))n++;if(n>2)break}}}}return s.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e<s&&/^\s*$/.test(r));/^\s+/.test(r)||(r=""),t=0}var o=this.$shortWordEndIndex(r);this.moveCursorTo(e,t+o)},this.moveCursorShortWordLeft=function(){var e=this.lead.row,t=this.lead.column,n;if(n=this.session.getFoldAt(e,t,-1))return this.moveCursorTo(n.start.row,n.start.column);var r=this.session.getLine(e).substring(0,t);if(t==0){do e--,r=this.doc.getLine(e);while(e>0&&/^\s*$/.test(r));t=r.length,/\s+$/.test(r)||(r="")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column);t===0&&(this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);var r=this.session.screenToDocumentPosition(n.row+e,n.column);this.moveCursorTo(r.row,r.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e}}).call(u.prototype),t.Selection=u}),ace.define("ace/range",["require","exports","module"],function(e,t,n){var r=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row==e.start.row&&this.end.row==e.end.row&&this.start.column==e.start.column&&this.end.column==e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?t<this.start.column?-1:t>this.end.column?1:0:e<this.start.row?-1:e>this.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};if(this.start.row>t)var i={row:t+1,column:0};if(this.start.row<e)var i={row:e,column:0};if(this.end.row<e)var n={row:e,column:0};return r.fromPoints(i||this.start,n||this.end)},this.extend=function(e,t){var n=this.compare(e,t);if(n==0)return this;if(n==-1)var i={row:e,column:t};else var s={row:e,column:t};return r.fromPoints(i||this.start,s||this.end)},this.isEmpty=function(){return this.start.row==this.end.row&&this.start.column==this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return r.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new r(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new r(this.start.row,0,this.end.row,0)},this.toScreenRange=function(e){var t=e.documentToScreenPosition(this.start),n=e.documentToScreenPosition(this.end);return new r(t.row,t.column,n.row,n.column)}}).call(r.prototype),r.fromPoints=function(e,t){return new r(e.row,e.column,t.row,t.column)},t.Range=r}),ace.define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour","ace/unicode"],function(e,t,n){var r=e("../tokenizer").Tokenizer,i=e("./text_highlight_rules").TextHighlightRules,s=e("./behaviour").Behaviour,o=e("../unicode"),u=function(){this.$tokenizer=new r((new i).getRules()),this.$behaviour=new s};(function(){this.tokenRe=new RegExp("^["+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+"\\$_]+","g"),this.nonTokenRe=new RegExp("^(?:[^"+o.packages.L+o.packages.Mn+o.packages.Mc+o.packages.Nd+o.packages.Pc+"\\$_]|s])+","g"),this.getTokenizer=function(){return this.$tokenizer},this.toggleCommentLines=function(e,t,n,r){},this.getNextLineIndent=function(e,t,n){return""},this.checkOutdent=function(e,t,n){return!1},this.autoOutdent=function(e,t,n){},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""},this.createWorker=function(e){return null},this.createModeDelegates=function(e){if(!this.$embeds)return;this.$modes={};for(var t=0;t<this.$embeds.length;t++)e[this.$embeds[t]]&&(this.$modes[this.$embeds[t]]=new e[this.$embeds[t]]);var n=["toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction"];for(var t=0;t<n.length;t++)(function(e){var r=n[t],i=e[r];e[n[t]]=function(){return this.$delegator(r,arguments,i)}})(this)},this.$delegator=function(e,t,n){var r=t[0];for(var i=0;i<this.$embeds.length;i++){if(!this.$modes[this.$embeds[i]])continue;var s=r.split(this.$embeds[i]);if(!s[0]&&s[1]){t[0]=s[1];var o=this.$modes[this.$embeds[i]];return o[e].apply(o,t)}}var u=n.apply(this,t);return n?u:undefined},this.transformAction=function(e,t,n,r,i){if(this.$behaviour){var s=this.$behaviour.getBehaviours();for(var o in s)if(s[o][t]){var u=s[o][t].apply(this,arguments);if(u)return u}}}}).call(u.prototype),t.Mode=u}),ace.define("ace/tokenizer",["require","exports","module"],function(e,t,n){var r=function(e,t){t=t?"g"+t:"g",this.rules=e,this.regExps={},this.matchMappings={};for(var n in this.rules){var r=this.rules[n],i=r,s=[],o=0,u=this.matchMappings[n]={};for(var a=0;a<i.length;a++){i[a].regex instanceof RegExp&&(i[a].regex=i[a].regex.toString().slice(1,-1));var f=(new RegExp("(?:("+i[a].regex+")|(.))")).exec("a").length-2,l=i[a].regex.replace(/\\([0-9]+)/g,function(e,t){return"\\"+(parseInt(t,10)+o+1)});if(f>1&&i[a].token.length!==f-1)throw new Error("For "+i[a].regex+" the matching groups ("+(f-1)+") and length of the token array ("+i[a].token.length+") don't match (rule #"+a+" of state "+n+")");u[o]={rule:a,len:f},o+=f,s.push(l)}this.regExps[n]=new RegExp("(?:("+s.join(")|(")+")|(.))",t)}};(function(){this.getLineTokens=function(e,t){var n=t||"start",r=this.rules[n],i=this.matchMappings[n],s=this.regExps[n];s.lastIndex=0;var o,u=[],a=0,f={type:null,value:""};while(o=s.exec(e)){var l="text",c=null,h=[o[0]];for(var p=0;p<o.length-2;p++){if(o[p+1]===undefined)continue;c=r[i[p].rule],i[p].len>1&&(h=o.slice(p+2,p+1+i[p].len)),typeof c.token=="function"?l=c.token.apply(this,h):l=c.token;if(c.next){n=c.next,r=this.rules[n],i=this.matchMappings[n],a=s.lastIndex,s=this.regExps[n];if(s===undefined)throw new Error("You indicated a state of "+c.next+" to go to, but it doesn't exist!");s.lastIndex=a}break}if(h[0]){typeof l=="string"&&(h=[h.join("")],l=[l]);for(var p=0;p<h.length;p++){if(!h[p])continue;(!c||c.merge||l[p]==="text")&&f.type===l[p]?f.value+=h[p]:(f.type&&u.push(f),f={type:l[p],value:h[p]})}}if(a==e.length)break;a=s.lastIndex}return f.type&&u.push(f),{tokens:u,state:n}}}).call(r.prototype),t.Tokenizer=r}),ace.define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"],function(e,t,n){var r=e("../lib/lang"),i=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{token:"text",regex:".+"}]}};(function(){this.addRules=function(e,t){for(var n in e){var r=e[n];for(var i=0;i<r.length;i++){var s=r[i];s.next&&(s.next=t+s.next)}this.$rules[t+n]=r}},this.getRules=function(){return this.$rules},this.embedRules=function(e,t,n,i,s){var o=(new e).getRules();if(i)for(var u=0;u<i.length;u++)i[u]=t+i[u];else{i=[];for(var a in o)i.push(t+a)}this.addRules(o,t);var f=Array.prototype[s?"push":"unshift"];for(var u=0;u<i.length;u++)f.apply(this.$rules[i[u]],r.deepCopy(n));this.$embeds||(this.$embeds=[]),this.$embeds.push(t)},this.getEmbeds=function(){return this.$embeds},this.createKeywordMapper=function(e,t,n,r){var i=Object.create(null);return Object.keys(e).forEach(function(t){var s=e[t];n&&(s=s.toLowerCase());var o=s.split(r||"|");for(var u=o.length;u--;)i[o[u]]=t}),e=null,n?function(e){return i[e.toLowerCase()]||t}:function(e){return i[e]||t}},this.getKeywords=function(){return this.$keywords}}).call(i.prototype),t.TextHighlightRules=i}),ace.define("ace/mode/behaviour",["require","exports","module"],function(e,t,n){var r=function(){this.$behaviours={}};(function(){this.add=function(e,t,n){switch(undefined){case this.$behaviours:this.$behaviours={};case this.$behaviours[e]:this.$behaviours[e]={}}this.$behaviours[e][t]=n},this.addBehaviours=function(e){for(var t in e)for(var n in e[t])this.add(t,n,e[t][n])},this.remove=function(e){this.$behaviours&&this.$behaviours[e]&&delete this.$behaviours[e]},this.inherit=function(e,t){if(typeof e=="function")var n=(new e).getBehaviours(t);else var n=e.getBehaviours(t);this.addBehaviours(n)},this.getBehaviours=function(e){if(!e)return this.$behaviours;var t={};for(var n=0;n<e.length;n++)this.$behaviours[e[n]]&&(t[e[n]]=this.$behaviours[e[n]]);return t}}).call(r.prototype),t.Behaviour=r}),ace.define("ace/unicode",["require","exports","module"],function(e,t,n){function r(e){var n=/\w{4}/g;for(var r in e)t.packages[r]=e[r].replace(n,"\\u$&")}t.packages={},r({L:"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",Ll:"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A",Lu:"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A",Lt:"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC",Lm:"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F",Lo:"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",M:"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26",Mn:"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26",Mc:"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC",Me:"0488048906DE20DD-20E020E2-20E4A670-A672",N:"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nd:"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nl:"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF",No:"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835",P:"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",Pd:"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D",Ps:"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62",Pe:"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63",Pi:"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20",Pf:"00BB2019201D203A2E032E052E0A2E0D2E1D2E21",Pc:"005F203F20402054FE33FE34FE4D-FE4FFF3F",Po:"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65",S:"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",Sm:"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC",Sc:"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6",Sk:"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3",So:"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD",Z:"002000A01680180E2000-200A20282029202F205F3000",Zs:"002000A01680180E2000-200A202F205F3000",Zl:"2028",Zp:"2029",C:"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF",Cc:"0000-001F007F-009F",Cf:"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB",Co:"E000-F8FF",Cs:"D800-DFFF",Cn:"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF"})}),ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=e("./range").Range,o=e("./anchor").Anchor,u=function(e){this.$lines=[],e.length==0?this.$lines=[""]:Array.isArray(e)?this.insertLines(0,e):this.insert({row:0,column:0},e)};(function(){r.implement(this,i),this.setValue=function(e){var t=this.getLength();this.remove(new s(0,0,t,this.getLine(t-1).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new o(this,e,t)},"aaa".split(/a/).length==0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);t?this.$autoNewLine=t[1]:this.$autoNewLine="\n"},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";case"auto":return this.$autoNewLine}},this.$autoNewLine="\n",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){if(e.start.row==e.end.row)return this.$lines[e.start.row].substring(e.start.column,e.end.column);var t=this.getLines(e.start.row+1,e.end.row-1);return t.unshift((this.$lines[e.start.row]||"").substring(e.start.column)),t.push((this.$lines[e.end.row]||"").substring(0,e.end.column)),t.join(this.getNewLineCharacter())},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t&&(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length),e},this.insert=function(e,t){if(!t||t.length===0)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(t);var n=this.$split(t),r=n.splice(0,1)[0],i=n.length==0?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),i!==null&&(e=this.insertNewLine(e),e=this.insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){if(t.length==0)return{row:e,column:0};if(t.length>65535){var n=this.insertLines(e,t.slice(65535));t=t.slice(0,65535)}var r=[e,0];r.push.apply(r,t),this.$lines.splice.apply(this.$lines,r);var i=new s(e,0,e+t.length,0),o={action:"insertLines",range:i,lines:t};return this._emit("change",{data:o}),n||i.end},this.insertNewLine=function(e){e=this.$clipPosition(e);var t=this.$lines[e.row]||"";this.$lines[e.row]=t.substring(0,e.column),this.$lines.splice(e.row+1,0,t.substring(e.column,t.length));var n={row:e.row+1,column:0},r={action:"insertText",range:s.fromPoints(e,n),text:this.getNewLineCharacter()};return this._emit("change",{data:r}),n},this.insertInLine=function(e,t){if(t.length==0)return e;var n=this.$lines[e.row]||"";this.$lines[e.row]=n.substring(0,e.column)+t+n.substring(e.column);var r={row:e.row,column:e.column+t.length},i={action:"insertText",range:s.fromPoints(e,r),text:t};return this._emit("change",{data:i}),r},this.remove=function(e){e.start=this.$clipPosition(e.start),e.end=this.$clipPosition(e.end);if(e.isEmpty())return e.start;var t=e.start.row,n=e.end.row;if(e.isMultiLine()){var r=e.start.column==0?t:t+1,i=n-1;e.end.column>0&&this.removeInLine(n,0,e.end.column),i>=r&&this.removeLines(r,i),r!=t&&(this.removeInLine(t,e.start.column,this.getLine(t).length),this.removeNewLine(e.start.row))}else this.removeInLine(t,e.start.column,e.end.column);return e.start},this.removeInLine=function(e,t,n){if(t==n)return;var r=new s(e,t,e,n),i=this.getLine(e),o=i.substring(t,n),u=i.substring(0,t)+i.substring(n,i.length);this.$lines.splice(e,1,u);var a={action:"removeText",range:r,text:o};return this._emit("change",{data:a}),r.start},this.removeLines=function(e,t){var n=new s(e,0,t+1,0),r=this.$lines.splice(e,t-e+1),i={action:"removeLines",range:n,nl:this.getNewLineCharacter(),lines:r};return this._emit("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),r=new s(e,t.length,e+1,0),i=t+n;this.$lines.splice(e,2,i);var o={action:"removeText",range:r,text:this.getNewLineCharacter()};this._emit("change",{data:o})},this.replace=function(e,t){if(t.length==0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);if(t)var n=this.insert(e.start,t);else n=e.start;return n},this.applyDeltas=function(e){for(var t=0;t<e.length;t++){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.insertLines(r.start.row,n.lines):n.action=="insertText"?this.insert(r.start,n.text):n.action=="removeLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="removeText"&&this.remove(r)}},this.revertDeltas=function(e){for(var t=e.length-1;t>=0;t--){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="insertText"?this.remove(r):n.action=="removeLines"?this.insertLines(r.start.row,n.lines):n.action=="removeText"&&this.insert(r.start,n.text)}}}).call(u.prototype),t.Document=u}),ace.define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=t.Anchor=function(e,t,n){this.document=e,typeof n=="undefined"?this.setPosition(t.row,t.column):this.setPosition(t,n),this.$onChange=this.onChange.bind(this),e.on("change",this.$onChange)};(function(){r.implement(this,i),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.onChange=function(e){var t=e.data,n=t.range;if(n.start.row==n.end.row&&n.start.row!=this.row)return;if(n.start.row>this.row)return;if(n.start.row==this.row&&n.start.column>this.column)return;var r=this.row,i=this.column;t.action==="insertText"?n.start.row===r&&n.start.column<=i?n.start.row===n.end.row?i+=n.end.column-n.start.column:(i-=n.start.column,r+=n.end.row-n.start.row):n.start.row!==n.end.row&&n.start.row<r&&(r+=n.end.row-n.start.row):t.action==="insertLines"?n.start.row<=r&&(r+=n.end.row-n.start.row):t.action=="removeText"?n.start.row==r&&n.start.column<i?n.end.column>=i?i=n.start.column:i=Math.max(0,i-(n.end.column-n.start.column)):n.start.row!==n.end.row&&n.start.row<r?(n.end.row==r&&(i=Math.max(0,i-n.end.column)+n.start.column),r-=n.end.row-n.start.row):n.end.row==r&&(r-=n.end.row-n.start.row,i=Math.max(0,i-n.end.column)+n.start.column):t.action=="removeLines"&&n.start.row<=r&&(n.end.row<=r?r-=n.end.row-n.start.row:(r=n.start.row,i=0)),this.setPosition(r,i,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._emit("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=5e3,o=function(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var n=this;this.$worker=function(){if(!n.running)return;var e=new Date,t=n.currentLine,r=n.doc,i=0,s=r.getLength();while(n.currentLine<s){n.$tokenizeRow(n.currentLine);while(n.lines[n.currentLine])n.currentLine++;i++;if(i%5==0&&new Date-e>20){n.fireUpdateEvent(t,n.currentLine-1),n.running=setTimeout(n.$worker,20);return}}n.running=!1,n.fireUpdateEvent(t,s-1)}};(function(){r.implement(this,i),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._emit("update",{data:n})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.$updateOnChange=function(e){var t=e.range,n=t.start.row,r=t.end.row-n;if(r===0)this.lines[n]=null;else if(e.action=="removeText"||e.action=="removeLines")this.lines.splice(n,r+1,null),this.states.splice(n,r+1,null);else{var i=Array(r+1);i.unshift(n,1),this.lines.splice.apply(this.lines,i),this.states.splice.apply(this.states,i)}this.currentLine=Math.min(n,this.currentLine,this.doc.getLength()),this.stop(),this.running=setTimeout(this.$worker,700)},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||"start"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1];if(t.length>s){var r={value:t.substr(s),type:"text"};t=t.slice(0,s)}var i=this.tokenizer.getLineTokens(t,n);return r&&(i.tokens.push(r),i.state="start"),this.states[e]!==i.state?(this.states[e]=i.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=i.tokens}}).call(o.prototype),t.BackgroundTokenizer=o}),ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){if(this.regExp+""==e+"")return;this.regExp=e,this.cache=[]},this.update=function(e,t,n,i){if(!this.regExp)return;var o=i.firstRow,u=i.lastRow;for(var a=o;a<=u;a++){var f=this.cache[a];f==null&&(f=r.getMatchOffsets(n.getLine(a),this.regExp),f.length>this.MAX_RANGES&&(f=f.slice(0,this.MAX_RANGES)),f=f.map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:"");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i,null,this.type)}}}).call(o.prototype),t.SearchHighlight=o}),ace.define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"],function(e,t,n){function u(){this.getFoldAt=function(e,t,n){var r=this.getFoldLine(e);if(!r)return null;var i=r.folds;for(var s=0;s<i.length;s++){var o=i[s];if(o.range.contains(e,t)){if(n==1&&o.range.isEnd(e,t))continue;if(n==-1&&o.range.isStart(e,t))continue;return o}}},this.getFoldsInRange=function(e){e=e.clone();var t=e.start,n=e.end,r=this.$foldData,i=[];t.column+=1,n.column-=1;for(var s=0;s<r.length;s++){var o=r[s].range.compareRange(e);if(o==2)continue;if(o==-2)break;var u=r[s].folds;for(var a=0;a<u.length;a++){var f=u[a];o=f.range.compareRange(e);if(o==-2)break;if(o==2)continue;if(o==42)break;i.push(f)}}return i},this.getAllFolds=function(){function n(t){e.push(t);if(!t.subFolds)return;for(var r=0;r<t.subFolds.length;r++)n(t.subFolds[r])}var e=[],t=this.$foldData;for(var r=0;r<t.length;r++)for(var i=0;i<t[r].folds.length;i++)n(t[r].folds[i]);return e},this.getFoldStringAt=function(e,t,n,r){r=r||this.getFoldLine(e);if(!r)return null;var i={end:{column:0}},s,o;for(var u=0;u<r.folds.length;u++){o=r.folds[u];var a=o.range.compareEnd(e,t);if(a==-1){s=this.getLine(o.start.row).substring(i.end.column,o.start.column);break}if(a===0)return null;i=o}return s||(s=this.getLine(o.start.row).substring(i.end.column)),n==-1?s.substring(0,t-i.end.column):n==1?s.substring(t-i.end.column):s},this.getFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r<n.length;r++){var i=n[r];if(i.start.row<=e&&i.end.row>=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r<n.length;r++){var i=n[r];if(i.end.row>=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i<n.length;i++){var s=n[i],o=s.end.row,u=s.start.row;if(o>=t){u<t&&(u>=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:o=new s(t,e),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column;if(u==f&&l-a<2)throw"The range has to be at least 2 characters width";var c=this.getFoldAt(u,a,1),h=this.getFoldAt(f,l,-1);if(c&&h==c)return c.addSubFold(o);if(c&&!c.range.isStart(u,a)||h&&!h.range.isEnd(f,l))throw"A fold can't intersect already existing fold"+o.range+c.range;var p=this.getFoldsInRange(o.range);p.length>0&&(this.removeFolds(p),o.subFolds=p);for(var d=0;d<n.length;d++){var v=n[d];if(f==v.start.row){v.addFold(o),r=!0;break}if(u==v.end.row){v.addFold(o),r=!0;if(!o.sameRow){var m=n[d+1];if(m&&m.start.row==f){v.merge(m);break}}break}if(f<=v.start.row)break}return r||(v=this.$addFoldLine(new i(this.$foldData,o))),this.$useWrapMode?this.$updateWrapData(v.start.row,v.start.row):this.$updateRowLengthCache(v.start.row,v.start.row),this.$modified=!0,this._emit("changeFold",{data:o}),o},this.addFolds=function(e){e.forEach(function(e){this.addFold(e)},this)},this.removeFold=function(e){var t=e.foldLine,n=t.start.row,r=t.end.row,i=this.$foldData,s=t.folds;if(s.length==1)i.splice(i.indexOf(t),1);else if(t.range.isEnd(e.end.row,e.end.column))s.pop(),t.end.row=s[s.length-1].end.row,t.end.column=s[s.length-1].end.column;else if(t.range.isStart(e.start.row,e.start.column))s.shift(),t.start.row=s[0].start.row,t.start.column=s[0].start.column;else if(e.sameRow)s.splice(s.indexOf(e),1);else{var o=t.split(e.start.row,e.start.column);s=o.folds,s.shift(),o.start.row=s[0].start.row,o.start.column=s[0].start.column}this.$useWrapMode?this.$updateWrapData(n,r):this.$updateRowLengthCache(n,r),this.$modified=!0,this._emit("changeFold",{data:e})},this.removeFolds=function(e){var t=[];for(var n=0;n<e.length;n++)t.push(e[n]);t.forEach(function(e){this.removeFold(e)},this),this.$modified=!0},this.expandFold=function(e){this.removeFold(e),e.subFolds.forEach(function(e){this.addFold(e)},this),e.subFolds=[]},this.expandFolds=function(e){e.forEach(function(e){this.expandFold(e)},this)},this.unfold=function(e,t){var n,i;e==null?n=new r(0,0,this.getLength(),0):typeof e=="number"?n=new r(e,0,e,this.getLine(e).length):"row"in e?n=r.fromPoints(e,e):n=e,i=this.getFoldsInRange(n);if(t)this.removeFolds(i);else while(i.length)this.expandFolds(i),i=this.getFoldsInRange(n)},this.isRowFolded=function(e,t){return!!this.getFoldLine(e,t)},this.getRowFoldEnd=function(e,t){var n=this.getFoldLine(e,t);return n?n.end.row:e},this.getFoldDisplayLine=function(e,t,n,r,i){r==null&&(r=e.start.row,i=0),t==null&&(t=e.end.row,n=this.getLine(t).length);var s=this.doc,o="";return e.walk(function(e,t,n,u){if(t<r)return;if(t==r){if(n<i)return;u=Math.max(i,u)}e!=null?o+=e:o+=s.getLine(t).substring(u,n)}.bind(this),t,n),o},this.getDisplayLine=function(e,t,n,r){var i=this.getFoldLine(e);if(!i){var s;return s=this.doc.getLine(e),s.substring(r||0,t||s.length)}return this.getFoldDisplayLine(i,e,t,n,r)},this.$cloneFoldData=function(){var e=[];return e=this.$foldData.map(function(t){var n=t.folds.map(function(e){return e.clone()});return new i(e,n)}),e},this.toggleFold=function(e){var t=this.selection,n=t.getRange(),r,i;if(n.isEmpty()){var s=n.start;r=this.getFoldAt(s.row,s.column);if(r){this.expandFold(r);return}(i=this.findMatchingBracket(s))?n.comparePoint(i)==1?n.end=i:(n.start=i,n.start.column++,n.end.column--):(i=this.findMatchingBracket({row:s.row,column:s.column+1}))?(n.comparePoint(i)==1?n.end=i:n.start=i,n.start.column++):n=this.getCommentFoldRange(s.row,s.column)||n}else{var o=this.getFoldsInRange(n);if(e&&o.length){this.expandFolds(o);return}o.length==1&&(r=o[0])}r||(r=this.getFoldAt(n.start.row,n.start.column));if(r&&r.range.toString()==n.toString()){this.expandFold(r);return}var u="...";if(!n.isMultiLine()){u=this.getTextRange(n);if(u.length<4)return;u=u.trim().substring(0,2)+".."}this.addFold(u,n)},this.getCommentFoldRange=function(e,t,n){var i=new o(this,e,t),s=i.getCurrentToken();if(s&&/^comment|string/.test(s.type)){var u=new r,a=new RegExp(s.type.replace(/\..*/,"\\."));if(n!=1){do s=i.stepBackward();while(s&&a.test(s.type));i.stepForward()}u.start.row=i.getCurrentTokenRow(),u.start.column=i.getCurrentTokenColumn()+2,i=new o(this,e,t);if(n!=-1){do s=i.stepForward();while(s&&a.test(s.type));s=i.stepBackward()}else s=i.getCurrentToken();return u.end.row=i.getCurrentTokenRow(),u.end.column=i.getCurrentTokenColumn()+s.value.length-2,u}},this.foldAll=function(e,t){var n=this.foldWidgets;t=t||this.getLength();for(var r=e||0;r<t;r++){n[r]==null&&(n[r]=this.getFoldWidget(r));if(n[r]!="start")continue;var i=this.getFoldWidgetRange(r);if(i&&i.end.row<=t)try{this.addFold("...",i)}catch(s){}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(e){if(!this.$foldStyles[e])throw new Error("invalid fold style: "+e+"["+Object.keys(this.$foldStyles).join(", ")+"]");if(this.$foldStyle==e)return;this.$foldStyle=e,e=="manual"&&this.unfold();var t=this.$foldMode;this.$setFolding(null),this.$setFolding(t)},this.$setFolding=function(e){if(this.$foldMode==e)return;this.$foldMode=e,this.removeListener("change",this.$updateFoldWidgets),this._emit("changeAnnotation");if(!e||this.$foldStyle=="manual"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets)},this.onFoldWidgetClick=function(e,t){t=t.domEvent;var n=this.getFoldWidget(e),r=this.getLine(e),i=t.shiftKey,s=i||t.ctrlKey||t.altKey||t.metaKey,o;n=="end"?o=this.getFoldAt(e,0,-1):o=this.getFoldAt(e,r.length,1);if(o){s?this.removeFold(o):this.expandFold(o);return}var u=this.getFoldWidgetRange(e);if(u){if(!u.isMultiLine()){o=this.getFoldAt(u.start.row,u.start.column,1);if(o&&u.isEqual(o.range)){this.removeFold(o);return}}i||this.addFold("...",u),s&&this.foldAll(u.start.row+1,u.end.row)}else s&&this.foldAll(e+1,this.getLength()),(t.target||t.srcElement).className+=" ace_invalid"},this.updateFoldWidgets=function(e){var t=e.data,n=t.range,r=n.start.row,i=n.end.row-r;if(i===0)this.foldWidgets[r]=null;else if(t.action=="removeText"||t.action=="removeLines")this.foldWidgets.splice(r,i+1,null);else{var s=Array(i+1);s.unshift(r,1),this.foldWidgets.splice.apply(this.foldWidgets,s)}}}var r=e("../range").Range,i=e("./fold_line").FoldLine,s=e("./fold").Fold,o=e("../token_iterator").TokenIterator;t.Folding=u}),ace.define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(e,t,n){function i(e,t){this.foldData=e,Array.isArray(t)?this.folds=t:t=this.folds=[t];var n=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,n.end.row,n.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e("../range").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.row<this.startRow||e.endRow>this.endRow)throw"Can't add a fold to this FoldLine as it has no connection";this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw"Trying to add fold to FoldRow that doesn't have a matching row";this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f<i.length;f++){s=i[f],o=s.range.compareStart(t,n);if(o==-1){e(null,t,n,r,a);return}u=e(null,s.start.row,s.start.column,r,a),u=!u&&e(s.placeholder,s.start.row,s.start.column,r);if(u||o==0)return;a=!s.sameRow,r=s.end.column}e(null,t,n,r,a)},this.getNextFoldTo=function(e,t){var n,r;for(var i=0;i<this.folds.length;i++){n=this.folds[i],r=n.range.compareEnd(e,t);if(r==-1)return{fold:n,kind:"after"};if(r==0)return{fold:n,kind:"inside"}}return null},this.addRemoveChars=function(e,t,n){var r=this.getNextFoldTo(e,t),i,s;if(r){i=r.fold;if(r.kind=="inside"&&i.start.column!=t&&i.start.row!=e)window.console&&window.console.log(e,t,i);else if(i.start.row==e){s=this.folds;var o=s.indexOf(i);o==0&&(this.start.column+=n);for(o;o<s.length;o++){i=s[o],i.start.column+=n;if(!i.sameRow)return;i.end.column+=n}this.end.column+=n}}},this.split=function(e,t){var n=this.getNextFoldTo(e,t).fold,r=this.folds,s=this.foldData;if(!n)return null;var o=r.indexOf(n),u=r[o-1];this.end.row=u.end.row,this.end.column=u.end.column,r=r.splice(o,r.length-o);var a=new i(s,r);return s.splice(s.indexOf(this)+1,0,a),a},this.merge=function(e){var t=e.folds;for(var n=0;n<t.length;n++)this.addFold(t[n]);var r=this.foldData;r.splice(r.indexOf(e),1)},this.toString=function(){var e=[this.range.toString()+": ["];return this.folds.forEach(function(t){e.push(" "+t.toString())}),e.push("]"),e.join("\n")},this.idxToPosition=function(e){var t=0,n;for(var r=0;r<this.folds.length;r++){var n=this.folds[r];e-=n.start.column-t;if(e<0)return{row:n.start.row,column:n.start.column+e};e-=n.placeholder.length;if(e<0)return n.start;t=n.end.column}return{row:this.end.row,column:this.end.column+e}}}).call(i.prototype),t.FoldLine=i}),ace.define("ace/edit_session/fold",["require","exports","module"],function(e,t,n){var r=t.Fold=function(e,t){this.foldLine=null,this.placeholder=t,this.range=e,this.start=e.start,this.end=e.end,this.sameRow=e.start.row==e.end.row,this.subFolds=[]};(function(){this.toString=function(){return'"'+this.placeholder+'" '+this.range.toString()},this.setFoldLine=function(e){this.foldLine=e,this.subFolds.forEach(function(t){t.setFoldLine(e)})},this.clone=function(){var e=this.range.clone(),t=new r(e,this.placeholder);return this.subFolds.forEach(function(e){t.subFolds.push(e.clone())}),t},this.addSubFold=function(e){if(this.range.isEqual(e))return this;if(!this.range.containsRange(e))throw"A fold can't intersect already existing fold"+e.range+this.range;var t=e.range.start.row,n=e.range.start.column;for(var r=0,i=-1;r<this.subFolds.length;r++){i=this.subFolds[r].range.compare(t,n);if(i!=1)break}var s=this.subFolds[r];if(i==0)return s.addSubFold(e);var t=e.range.end.row,n=e.range.end.column;for(var o=r,i=-1;o<this.subFolds.length;o++){i=this.subFolds[o].range.compare(t,n);if(i!=1)break}var u=this.subFolds[o];if(i==0)throw"A fold can't intersect already existing fold"+e.range+this.range;var a=this.subFolds.splice(r,o-r,e);return e.setFoldLine(this.foldLine),e}}).call(r.prototype)}),ace.define("ace/token_iterator",["require","exports","module"],function(e,t,n){var r=function(e,t,n){this.$session=e,this.$row=t,this.$rowTokens=e.getTokens(t);var r=e.getTokenAt(t,n);this.$tokenIndex=r?r.index:-1};(function(){this.stepBackward=function(){this.$tokenIndex-=1;while(this.$tokenIndex<0){this.$row-=1;if(this.$row<0)return this.$row=0,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=this.$rowTokens.length-1}return this.$rowTokens[this.$tokenIndex]},this.stepForward=function(){var e=this.$session.getLength();this.$tokenIndex+=1;while(this.$tokenIndex>=this.$rowTokens.length){this.$row+=1;if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n}}).call(r.prototype),t.TokenIterator=r}),ace.define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,t,n){function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n=="")return null;var r=n.match(/([\(\[\{])|([\)\]\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\(\[\{])|([\)\]\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\(\[\{])|([\)\]\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("rparen",".paren")+")+"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("lparen",".paren")+")+"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(a<l){var c=f.charAt(a);if(c==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else c==e&&(s+=1);a+=1}do u=o.stepForward();while(u&&!n.test(u.type));if(u==null)break;a=0}return null}}var r=e("../token_iterator").TokenIterator,i=e("../range").Range;t.BracketMatch=s}),ace.define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(){this.$options={}};(function(){this.set=function(e){return i.mixin(this.$options,e),this},this.getOptions=function(){return r.copyObject(this.$options)},this.setOptions=function(e){this.$options=e},this.find=function(e){var t=this.$matchIterator(e,this.$options);if(!t)return!1;var n=null;return t.forEach(function(e,t,r){if(!e.start){var i=e.offset+(r||0);n=new s(t,i,t,i+e.length)}else n=e;return!0}),n},this.findAll=function(e){var t=this.$options;if(!t.needle)return[];this.$assembleRegExp(t);var n=t.range,i=n?e.getLines(n.start.row,n.end.row):e.doc.getAllLines(),o=[],u=t.re;if(t.$isMultiLine){var a=u.length,f=i.length-a;for(var l=u.offset||0;l<=f;l++){for(var c=0;c<a;c++)if(i[l+c].search(u[c])==-1)break;var h=i[l],p=i[l+a-1],d=h.match(u[0])[0].length,v=p.match(u[a-1])[0].length;o.push(new s(l,h.length-d,l+a-1,v))}}else for(var m=0;m<i.length;m++){var g=r.getMatchOffsets(i[m],u);for(var c=0;c<g.length;c++){var y=g[c];o.push(new s(m,y.offset,m,y.offset+y.length))}}if(n){var b=n.start.column,w=n.start.column,m=0,c=o.length-1;while(m<c&&o[m].start.column<b&&o[m].start.row==n.start.row)m++;while(m<c&&o[c].end.column>w&&o[c].end.row==n.end.row)c--;return o.slice(m,c+1)}return o},this.replace=function(e,t){var n=this.$options,r=this.$assembleRegExp(n);if(n.$isMultiLine)return t;if(!r)return;var i=r.exec(e);if(!i||i[0].length!=e.length)return null;t=e.replace(r,t);if(n.preserveCase){t=t.split("");for(var s=Math.min(e.length,e.length);s--;){var o=e[s];o&&o.toLowerCase()!=o?t[s]=t[s].toUpperCase():t[s]=t[s].toLowerCase()}t=t.join("")}return t},this.$matchIterator=function(e,t){var n=this.$assembleRegExp(t);if(!n)return!1;var i=this,o,u=t.backwards;if(t.$isMultiLine)var a=n.length,f=function(t,r,i){var u=t.search(n[0]);if(u==-1)return;for(var f=1;f<a;f++){t=e.getLine(r+f);if(t.search(n[f])==-1)return}var l=t.match(n[a-1])[0].length,c=new s(r,u,r+a-1,l);n.offset==1?(c.start.row--,c.start.column=Number.MAX_VALUE):i&&(c.start.column+=i);if(o(c))return!0};else if(u)var f=function(e,t,i){var s=r.getMatchOffsets(e,n);for(var u=s.length-1;u>=0;u--)if(o(s[u],t,i))return!0};else var f=function(e,t,i){var s=r.getMatchOffsets(e,n);for(var u=0;u<s.length;u++)if(o(s[u],t,i))return!0};return{forEach:function(n){o=n,i.$lineIterator(e,t).forEach(f)}}},this.$assembleRegExp=function(e){if(e.needle instanceof RegExp)return e.re=e.needle;var t=e.needle;if(!e.needle)return e.re=!1;e.regExp||(t=r.escapeRegExp(t)),e.wholeWord&&(t="\\b"+t+"\\b");var n=e.caseSensitive?"g":"gi";e.$isMultiLine=/[\n\r]/.test(t);if(e.$isMultiLine)return e.re=this.$assembleMultilineRegExp(t,n);try{var i=new RegExp(t,n)}catch(s){i=!1}return e.re=i},this.$assembleMultilineRegExp=function(e,t){var n=e.replace(/\r\n|\r|\n/g,"$\n^").split("\n"),r=[];for(var i=0;i<n.length;i++)try{r.push(new RegExp(n[i],t))}catch(s){return!1}return n[0]==""?(r.shift(),r.offset=1):r.offset=0,r},this.$lineIterator=function(e,t){var n=t.backwards==1,r=t.skipCurrent!=0,i=t.range,s=t.start;s||(s=i?i[n?"end":"start"]:e.selection.getRange()),s.start&&(s=s[r!=n?"end":"start"]);var o=i?i.start.row:0,u=i?i.end.row:e.getLength()-1,a=n?function(n){var r=s.row,i=e.getLine(r).substring(0,s.column);if(n(i,r))return;for(r--;r>=o;r--)if(n(e.getLine(r),r))return;if(t.wrap==0)return;for(r=u,o=s.row;r>=o;r--)if(n(e.getLine(r),r))return}:function(n){var r=s.row,i=e.getLine(r).substr(s.column);if(n(i,r,s.column))return;for(r+=1;r<=u;r++)if(n(e.getLine(r),r))return;if(t.wrap==0)return;for(r=o,u=s.row;r<=u;r++)if(n(e.getLine(r),r))return};return{forEach:a}}}).call(o.prototype),t.Search=o}),ace.define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../keyboard/hash_handler").HashHandler,s=e("../lib/event_emitter").EventEmitter,o=function(e,t){this.platform=e,this.commands=this.byName={},this.commmandKeyBinding={},this.addCommands(t),this.setDefaultHandler("exec",function(e){return e.command.exec(e.editor,e.args||{})})};r.inherits(o,i),function(){r.implement(this,s),this.exec=function(e,t,n){typeof e=="string"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;var r=this._emit("exec",{editor:t,command:e,args:n});return r===!1?!1:!0},this.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit("changeStatus"),this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0)},this.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t=="string"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(e){return e.map(function(e){return typeof e[0]!="string"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(o.prototype),t.CommandManager=o}),ace.define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys"],function(e,t,n){function i(e,t){this.platform=t,this.commands={},this.commmandKeyBinding={},this.addCommands(e)}var r=e("../lib/keys");(function(){this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e){var t=typeof e=="string"?e:e.name;e=this.commands[t],delete this.commands[t];var n=this.commmandKeyBinding;for(var r in n)for(var i in n[r])n[r][i]==e&&delete n[r][i]},this.bindKey=function(e,t){if(!e)return;if(typeof t=="function"){this.addCommand({exec:t,bindKey:e,name:e});return}var n=this.commmandKeyBinding;e.split("|").forEach(function(e){var r=this.parseKeys(e,t),i=r.hashId;(n[i]||(n[i]={}))[r.key]=t},this)},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(typeof n=="string")return this.bindKey(n,t);typeof n=="function"&&(n={exec:n}),n.name||(n.name=t),this.addCommand(n)},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){var t=e.bindKey;if(!t)return;var n=typeof t=="string"?t:t[this.platform];this.bindKey(n,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(e){return e}),n=t.pop(),i=r[n];if(r.FUNCTION_KEYS[i])n=r.FUNCTION_KEYS[i].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]=="shift")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=r.KEY_MODS[t[o]];if(u==null)throw"invalid modifier "+t[o]+" in "+e;s|=u}return{key:n,hashId:s}},this.findKeyCommand=function(t,n){var r=this.commmandKeyBinding;return r[t]&&r[t][n]},this.handleKeyboard=function(e,t,n,r){return{command:this.findKeyCommand(t,n)}}}).call(i.prototype),t.HashHandler=i}),ace.define("ace/commands/default_commands",["require","exports","module","ace/lib/lang"],function(e,t,n){function i(e,t){return{win:e,mac:t}}var r=e("../lib/lang");t.commands=[{name:"selectall",bindKey:i("Ctrl-A","Command-A"),exec:function(e){e.selectAll()},readOnly:!0},{name:"centerselection",bindKey:i(null,"Ctrl-L"),exec:function(e){e.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:i("Ctrl-L","Command-L"),exec:function(e){var t=parseInt(prompt("Enter line number:"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:"fold",bindKey:i("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(e){e.session.toggleFold(!1)},readOnly:!0},{name:"unfold",bindKey:i("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(e){e.session.toggleFold(!0)},readOnly:!0},{name:"foldall",bindKey:i("Alt-0","Command-Option-0"),exec:function(e){e.session.foldAll()},readOnly:!0},{name:"unfoldall",bindKey:i("Alt-Shift-0","Command-Option-Shift-0"),exec:function(e){e.session.unfold()},readOnly:!0},{name:"findnext",bindKey:i("Ctrl-K","Command-G"),exec:function(e){e.findNext()},readOnly:!0},{name:"findprevious",bindKey:i("Ctrl-Shift-K","Command-Shift-G"),exec:function(e){e.findPrevious()},readOnly:!0},{name:"find",bindKey:i("Ctrl-F","Command-F"),exec:function(e){var t=prompt("Find:",e.getCopyText());e.find(t)},readOnly:!0},{name:"overwrite",bindKey:"Insert",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:i("Ctrl-Shift-Home","Command-Shift-Up"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0},{name:"gotostart",bindKey:i("Ctrl-Home","Command-Home|Command-Up"),exec:function(e){e.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectup",bindKey:i("Shift-Up","Shift-Up"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:"forEach",readOnly:!0},{name:"golineup",bindKey:i("Up","Up|Ctrl-P"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selecttoend",bindKey:i("Ctrl-Shift-End","Command-Shift-Down"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoend",bindKey:i("Ctrl-End","Command-End|Command-Down"),exec:function(e){e.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"selectdown",bindKey:i("Shift-Down","Shift-Down"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:"forEach",readOnly:!0},{name:"golinedown",bindKey:i("Down","Down|Ctrl-N"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectwordleft",bindKey:i("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"gotowordleft",bindKey:i("Ctrl-Left","Option-Left"),exec:function(e){e.navigateWordLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttolinestart",bindKey:i("Alt-Shift-Left","Command-Shift-Left"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"gotolinestart",bindKey:i("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(e){e.navigateLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectleft",bindKey:i("Shift-Left","Shift-Left"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoleft",bindKey:i("Left","Left|Ctrl-B"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectwordright",bindKey:i("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:"forEach",readOnly:!0},{name:"gotowordright",bindKey:i("Ctrl-Right","Option-Right"),exec:function(e){e.navigateWordRight()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttolineend",bindKey:i("Alt-Shift-Right","Command-Shift-Right"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"gotolineend",bindKey:i("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(e){e.navigateLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"selectright",bindKey:i("Shift-Right","Shift-Right"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoright",bindKey:i("Right","Right|Ctrl-F"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectpagedown",bindKey:"Shift-PageDown",exec:function(e){e.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:i(null,"Option-PageDown"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:i("PageDown","PageDown|Ctrl-V"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:"Shift-PageUp",exec:function(e){e.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:i(null,"Option-PageUp"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:"PageUp",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:"scrollup",bindKey:i("Ctrl-Up",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",bindKey:i("Ctrl-Down",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",bindKey:"Shift-Home",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectlineend",bindKey:"Shift-End",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"togglerecording",bindKey:i("Ctrl-Alt-E","Command-Option-E"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:"replaymacro",bindKey:i("Ctrl-Shift-E","Command-Shift-E"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:"jumptomatching",bindKey:i("Ctrl-P","Ctrl-Shift-P"),exec:function(e){e.jumpToMatching()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttomatching",bindKey:i("Ctrl-Shift-P",null),exec:function(e){e.jumpToMatching(!0)},readOnly:!0},{name:"cut",exec:function(e){var t=e.getSelectionRange();e._emit("cut",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},multiSelectAction:"forEach"},{name:"removeline",bindKey:i("Ctrl-D","Command-D"),exec:function(e){e.removeLines()},multiSelectAction:"forEach"},{name:"duplicateSelection",bindKey:i("Ctrl-Shift-D","Command-Shift-D"),exec:function(e){e.duplicateSelection()},multiSelectAction:"forEach"},{name:"sortlines",bindKey:i("Ctrl-Alt-S","Command-Alt-S"),exec:function(e){e.sortLines()},multiSelectAction:"forEach"},{name:"togglecomment",bindKey:i("Ctrl-/","Command-/"),exec:function(e){e.toggleCommentLines()},multiSelectAction:"forEach"},{name:"modifyNumberUp",bindKey:i("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(e){e.modifyNumber(1)},multiSelectAction:"forEach"},{name:"modifyNumberDown",bindKey:i("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(e){e.modifyNumber(-1)},multiSelectAction:"forEach"},{name:"replace",bindKey:i("Ctrl-R","Command-Option-F"),exec:function(e){var t=prompt("Find:",e.getCopyText());if(!t)return;var n=prompt("Replacement:");if(!n)return;e.replace(n,{needle:t})}},{name:"replaceall",bindKey:i("Ctrl-Shift-R","Command-Shift-Option-F"),exec:function(e){var t=prompt("Find:");if(!t)return;var n=prompt("Replacement:");if(!n)return;e.replaceAll(n,{needle:t})}},{name:"undo",bindKey:i("Ctrl-Z","Command-Z"),exec:function(e){e.undo()}},{name:"redo",bindKey:i("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(e){e.redo()}},{name:"copylinesup",bindKey:i("Alt-Shift-Up","Command-Option-Up"),exec:function(e){e.copyLinesUp()}},{name:"movelinesup",bindKey:i("Alt-Up","Option-Up"),exec:function(e){e.moveLinesUp()}},{name:"copylinesdown",bindKey:i("Alt-Shift-Down","Command-Option-Down"),exec:function(e){e.copyLinesDown()}},{name:"movelinesdown",bindKey:i("Alt-Down","Option-Down"),exec:function(e){e.moveLinesDown()}},{name:"del",bindKey:i("Delete","Delete|Ctrl-D"),exec:function(e){e.remove("right")},multiSelectAction:"forEach"},{name:"backspace",bindKey:i("Command-Backspace|Option-Backspace|Shift-Backspace|Backspace","Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(e){e.remove("left")},multiSelectAction:"forEach"},{name:"removetolinestart",bindKey:i("Alt-Backspace","Command-Backspace"),exec:function(e){e.removeToLineStart()},multiSelectAction:"forEach"},{name:"removetolineend",bindKey:i("Alt-Delete","Ctrl-K"),exec:function(e){e.removeToLineEnd()},multiSelectAction:"forEach"},{name:"removewordleft",bindKey:i("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(e){e.removeWordLeft()},multiSelectAction:"forEach"},{name:"removewordright",bindKey:i("Ctrl-Delete","Alt-Delete"),exec:function(e){e.removeWordRight()},multiSelectAction:"forEach"},{name:"outdent",bindKey:i("Shift-Tab","Shift-Tab"),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach"},{name:"indent",bindKey:i("Tab","Tab"),exec:function(e){e.indent()},multiSelectAction:"forEach"},{name:"insertstring",exec:function(e,t){e.insert(t)},multiSelectAction:"forEach"},{name:"inserttext",exec:function(e,t){e.insert(r.stringRepeat(t.text||"",t.times||1))},multiSelectAction:"forEach"},{name:"splitline",bindKey:i(null,"Ctrl-O"),exec:function(e){e.splitLine()},multiSelectAction:"forEach"},{name:"transposeletters",bindKey:i("Ctrl-T","Ctrl-T"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)}},{name:"touppercase",bindKey:i("Ctrl-U","Ctrl-U"),exec:function(e){e.toUpperCase()},multiSelectAction:"forEach"},{name:"tolowercase",bindKey:i("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(e){e.toLowerCase()},multiSelectAction:"forEach"}]}),ace.define("ace/undomanager",["require","exports","module"],function(e,t,n){var r=function(){this.reset()};(function(){this.execute=function(e){var t=e.args[0];this.$doc=e.args[1],this.$undoStack.push(t),this.$redoStack=[]},this.undo=function(e){var t=this.$undoStack.pop(),n=null;return t&&(n=this.$doc.undoChanges(t,e),this.$redoStack.push(t)),n},this.redo=function(e){var t=this.$redoStack.pop(),n=null;return t&&(n=this.$doc.redoChanges(t,e),this.$undoStack.push(t)),n},this.reset=function(){this.$undoStack=[],this.$redoStack=[]},this.hasUndo=function(){return this.$undoStack.length>0},this.hasRedo=function(){return this.$redoStack.length>0}}).call(r.prototype),t.UndoManager=r}),ace.define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/useragent","ace/config","ace/lib/net","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/renderloop","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/useragent"),u=e("./config"),a=e("./lib/net"),f=e("./layer/gutter").Gutter,l=e("./layer/marker").Marker,c=e("./layer/text").Text,h=e("./layer/cursor").Cursor,p=e("./scrollbar").ScrollBar,d=e("./renderloop").RenderLoop,v=e("./lib/event_emitter").EventEmitter,m=".ace_editor {position: absolute;overflow: hidden;font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;font-size: 12px;}.ace_scroller {position: absolute;overflow: hidden;}.ace_content {position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: text;}.ace_gutter {position: absolute;overflow : hidden;height: 100%;width: auto;cursor: default;z-index: 4;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTQ4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTU4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBMjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBMzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkgXxbAAAAJbSURBVHjapFNNaBNBFH4zs5vdZLP5sQmNpT82QY209heh1ioWisaDRcSKF0WKJ0GQnrzrxasHsR6EnlrwD0TagxJabaVEpFYxLWlLSS822tr87m66ccfd2GKyVhA6MMybgfe97/vmPUQphd0sZjto9XIn9OOsvlu2nkqRzVU+6vvlzPf8W6bk8dxQ0NPbxAALgCgg2JkaQuhzQau/El0zbmUA7U0Es8v2CiYmKQJHGO1QICCLoqilMhkmurDAyapKgqItezi/USRdJqEYY4D5jCy03ht2yMkkvL91jTTX10qzyyu2hruPRN7jgbH+EOsXcMLgYiThEgAMhABW85oqy1DXdRIdvP1AHJ2acQXvDIrVHcdQNrEKNYSVMSZGMjEzIIAwDXIo+6G/FxcGnzkC3T2oMhLjre49sBB+RRcHLqdafK6sYdE/GGBwU1VpFNj0aN8pJbe+BkZyevUrvLl6Xmm0W9IuTc0DxrDNAJd5oEvI/KRsNC3bQyNjPO9yQ1YHcfj2QvfQc/5TUhJTBc2iM0U7AWDQtc1nJHvD/cfO2s7jaGkiTEfa/Ep8coLu7zmNmh8+dc5lZDuUeFAGUNA/OY6JVaypQ0vjr7XYjUvJM37vt+j1vuTK5DgVfVUoTjVe+y3/LxMxY2GgU+CSLy4cpfsYorRXuXIOi0Vt40h67uZFTdIo6nLaZcwUJWAzwNS0tBnqqKzQDnjdG/iPyZxo46HaKUpbvYkj8qYRTZsBhge+JHhZyh0x9b95JqjVJkT084kZIPwu/mPWqPgfQ5jXh2+92Ay7HedfAgwA6KDWafb4w3cAAAAASUVORK5CYII=\");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTg4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTk4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBNjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBNzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pgd7PfIAAAGmSURBVHjaYvr//z8DJZiJgUIANoCRkREb9gLiSVAaQx4OQM7AAkwd7XU2/v++/rOttdYGEB9dASEvOMydGKfH8Gv/p4XTkvRBfLxeQAP+1cUhXopyvzhP7P/IoSj7g7Mw09cNKO6J1QQ0L4gICPIv/veg/8W+JdFvQNLHVsW9/nmn9zk7B+cCkDwhL7gt6knSZnx9/LuCEOcvkIAMP+cvto9nfqyZmmUAksfnBUtbM60gX/3/kgyv3/xSFOL5DZT+L8vP+Yfh5cvfPvp/xUHyQHXGyAYwgpwBjZYFT3Y1OEl/OfCH4ffv3wzc4iwMvNIsDJ+f/mH4+vIPAxsb631WW0Yln6ZpQLXdMK/DXGDflh+sIv37EivD5x//Gb7+YWT4y86sl7BCCkSD+Z++/1dkvsFRl+HnD1Rvje4F8whjMXmGj58YGf5zsDMwcnAwfPvKcml62DsQDeaDxN+/Y0qwlpEHqrdB94IRNIDUgfgfKJChGK4OikEW3gTiXUB950ASLFAF54AC94A0G9QAfOnmF9DCDzABFqS08IHYDIScdijOjQABBgC+/9awBH96jwAAAABJRU5ErkJggg==\");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRTk5MTVGREIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRTk5MTVGRUIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZFOTkxNUZCQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFOTkxNUZDQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SIDkjAAAAJ1JREFUeNpi/P//PwMlgImBQkB7A6qrq/+DMC55FkIGKCoq4pVnpFkgTp069f/+/fv/r1u37r+tre1/kg0A+ptn9uzZYLaRkRHpLvjw4cNXWVlZhufPnzOcO3eOdAO0tbVPAjHDmzdvGA4fPsxIsgGSkpJmv379Ynj37h2DjIyMCMkG3LhxQ/T27dsMampqDHZ2dq/pH41DxwCAAAMAFdc68dUsFZgAAAAASUVORK5CYII=\");}.ace_scrollbar {position: absolute;overflow-x: hidden;overflow-y: scroll;right: 0;}.ace_scrollbar-inner {position: absolute;width: 1px;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;}.ace_text-input.ace_composition {background: #fff;color: #000;z-index: 1000;opacity: 1;border: solid lightgray 1px;margin: -1px}.ace_layer {z-index: 1;position: absolute;overflow: hidden;white-space: nowrap;height: 100%;width: 100%;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;/* setting pointer-events: auto; on node under the mouse, which changesduring scroll, will break mouse wheel scrolling in Safari */pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;}.ace_text-layer {color: black;font: inherit !important;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {-moz-transition: opacity 0.18s;-webkit-transition: opacity 0.18s;-o-transition: opacity 0.18s;-ms-transition: opacity 0.18s;transition: opacity 0.18s;}.ace_cursor[style*=\"opacity: 0\"]{-ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)\";}.ace_editor.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_line {white-space: nowrap;}.ace_marker-layer .ace_step {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_line .ace_fold {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;-moz-border-radius: 2px;-webkit-border-radius: 2px;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat, repeat-x;background-position: center center, top left;}.ace_editor.ace_dragging .ace_content {cursor: move;}.ace_gutter-tooltip {background-color: #FFFFD5;border: 1px solid gray;box-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);color: black;display: inline-block;padding: 4px;position: absolute;z-index: 300;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: default;white-space: pre-line;word-wrap: break-word;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0 -12px 0 1px;display: inline-block;width: 11px;vertical-align: top;background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;}.ace_fold-widget.ace_end {background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\");}.ace_fold-widget.ace_closed {background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}/*** Dark version for fold widgets*/.ace_dark .ace_fold-widget {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");}.ace_dark .ace_fold-widget.ace_end {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget.ace_closed {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {-moz-transition: opacity 0.4s ease 0.05s;-webkit-transition: opacity 0.4s ease 0.05s;-o-transition: opacity 0.4s ease 0.05s;-ms-transition: opacity 0.4s ease 0.05s;transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {-moz-transition: opacity 0.05s ease 0.05s;-webkit-transition: opacity 0.05s ease 0.05s;-o-transition: opacity 0.05s ease 0.05s;-ms-transition: opacity 0.05s ease 0.05s;transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}";i.importCssString(m,"ace_editor");var g=function(e,t){var n=this;this.container=e,this.$keepTextAreaAtCursor=!o.isIE,i.addCssClass(e,"ace_editor"),this.setTheme(t),this.$gutter=i.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=i.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=i.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.setHighlightGutterLine(!0),this.$gutterLayer=new f(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new l(this.content);var r=this.$textLayer=new c(this.content);this.canvas=r.element,this.$markerFront=new l(this.content),this.$cursorLayer=new h(this.content),this.$horizScroll=!1,this.$horizScrollAlwaysVisible=!1,this.$animatedScroll=!1,this.scrollBar=new p(e),this.scrollBar.addEventListener("scroll",function(e){n.$inScrollAnimation||n.session.setScrollTop(e.data)}),this.scrollTop=0,this.scrollLeft=0,s.addListener(this.scroller,"scroll",function(){var e=n.scroller.scrollLeft;n.scrollLeft=e,n.session.setScrollLeft(e)}),this.cursorPos={row:0,column:0},this.$textLayer.addEventListener("changeCharacterSize",function(){n.updateCharacterSize(),n.onResize(!0)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:1,characterWidth:1,minHeight:1,maxHeight:1,offset:0,height:1},this.$loop=new d(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4)};(function(){this.showGutter=!0,this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,v),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.characterWidth=this.$textLayer.getCharacterWidth(),this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session=e,this.scroller.className="ace_scroller",this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e),this.$loop.schedule(this.CHANGE_FULL)},this.updateLines=function(e,t){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRow<t&&(this.$changedLines.lastRow=t)):this.$changedLines={firstRow:e,lastRow:t};if(this.$changedLines.firstRow>this.layerConfig.lastRow||this.$changedLines.lastRow<this.layerConfig.firstRow)return;this.$loop.schedule(this.CHANGE_LINES)},this.onChangeTabSize=function(){this.$loop.schedule(this.CHANGE_TEXT|this.CHANGE_MARKER),this.$textLayer.onChangeTabSize()},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(e){e?this.$renderChanges(this.CHANGE_FULL,!0):this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.onResize=function(e,t,n,r){var s=this.CHANGE_SIZE,o=this.$size;if(this.resizing>2)return;this.resizing>1?this.resizing++:this.resizing=e?1:0,r||(r=i.getInnerHeight(this.container));if(e||o.height!=r)o.height=r,this.scroller.style.height=r+"px",o.scrollerHeight=this.scroller.clientHeight,this.scrollBar.setHeight(o.scrollerHeight),this.session&&(this.session.setScrollTop(this.getScrollTop()),s|=this.CHANGE_FULL);n||(n=i.getInnerWidth(this.container));if(e||this.resizing>1||o.width!=n){o.width=n;var t=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=t+"px",o.scrollerWidth=Math.max(0,n-t-this.scrollBar.getWidth()),this.scroller.style.right=this.scrollBar.getWidth()+"px";if(this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)s|=this.CHANGE_FULL}e?this.$renderChanges(s,!0):this.$loop.schedule(s),e&&delete this.resizing},this.onGutterResize=function(){var e=this.$size.width,t=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=t+"px",this.$size.scrollerWidth=Math.max(0,e-t-this.scrollBar.getWidth()),this.session.getUseWrapMode()&&this.adjustWrapLimit()&&this.$loop.schedule(this.CHANGE_FULL)},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t)},this.setAnimatedScroll=function(e){this.$animatedScroll=e},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},this.getShowInvisibles=function(){return this.$textLayer.showInvisibles},this.getDisplayIndentGuides=function(){return this.$textLayer.displayIndentGuides},this.setDisplayIndentGuides=function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},this.$showPrintMargin=!0,this.setShowPrintMargin=function(e){this.$showPrintMargin=e,this.$updatePrintMargin()},this.getShowPrintMargin=function(){return this.$showPrintMargin},this.$printMarginColumn=80,this.setPrintMarginColumn=function(e){this.$printMarginColumn=e,this.$updatePrintMargin()},this.getPrintMarginColumn=function(){return this.$printMarginColumn},this.getShowGutter=function(){return this.showGutter},this.setShowGutter=function(e){if(this.showGutter===e)return;this.$gutter.style.display=e?"block":"none",this.showGutter=e,this.onResize(!0)},this.getFadeFoldWidgets=function(){return i.hasCssClass(this.$gutter,"ace_fade-fold-widgets")},this.setFadeFoldWidgets=function(e){e?i.addCssClass(this.$gutter,"ace_fade-fold-widgets"):i.removeCssClass(this.$gutter,"ace_fade-fold-widgets")},this.$highlightGutterLine=!1,this.setHighlightGutterLine=function(e){if(this.$highlightGutterLine==e)return;this.$highlightGutterLine=e;if(!this.$gutterLineHighlight){this.$gutterLineHighlight=i.createElement("div"),this.$gutterLineHighlight.className="ace_gutter-active-line",this.$gutter.appendChild(this.$gutterLineHighlight);return}this.$gutterLineHighlight.style.display=e?"":"none",this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight()},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$updateGutterLineHighlight=function(){this.$gutterLineHighlight.style.top=this.$cursorLayer.$pixelPos.top-this.layerConfig.offset+"px",this.$gutterLineHighlight.style.height=this.layerConfig.lineHeight+"px"},this.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement("div");e.className="ace_layer ace_print-margin-layer",this.$printMarginEl=i.createElement("div"),this.$printMarginEl.className="ace_print-margin",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",t.visibility=this.$showPrintMargin?"visible":"hidden"},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.content},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(!this.$keepTextAreaAtCursor)return;var e=this.$cursorLayer.$pixelPos.top,t=this.$cursorLayer.$pixelPos.left;e-=this.layerConfig.offset;if(e<0||e>this.layerConfig.height-this.lineHeight)return;var n=this.characterWidth;this.$composition&&(n+=this.textarea.scrollWidth),t-=this.scrollLeft,t>this.$size.scrollerWidth-n&&(t=this.$size.scrollerWidth-n),this.showGutter&&(t+=this.$gutterLayer.gutterWidth),this.textarea.style.height=this.lineHeight+"px",this.textarea.style.width=n+"px",this.textarea.style.left=t+"px",this.textarea.style.top=e-1+"px"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var e=Math.floor((this.layerConfig.height+this.layerConfig.offset)/this.layerConfig.lineHeight);return this.layerConfig.firstRow-1+e},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.getHScrollBarAlwaysVisible=function(){return this.$horizScrollAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.$horizScrollAlwaysVisible!=e&&(this.$horizScrollAlwaysVisible=e,(!this.$horizScrollAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL))},this.$updateScrollBar=function(){this.scrollBar.setInnerHeight(this.layerConfig.maxHeight),this.scrollBar.setScrollTop(this.scrollTop)},this.$renderChanges=function(e,t){if(!t&&(!e||!this.session||!this.container.offsetWidth))return;(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL)&&this.$computeLayerConfig();if(e&this.CHANGE_H_SCROLL){this.scroller.scrollLeft=this.scrollLeft;var n=this.scroller.scrollLeft;this.scrollLeft=n,this.session.setScrollLeft(n),this.scroller.className=this.scrollLeft==0?"ace_scroller":"ace_scroller ace_scroll-left"}if(e&this.CHANGE_FULL){this.$textLayer.checkForSizeChanges(),this.$updateScrollBar(),this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight();return}if(e&this.CHANGE_SCROLL){this.$updateScrollBar(),e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(this.layerConfig):this.$textLayer.scrollLines(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight();return}e&this.CHANGE_TEXT?(this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.showGutter)&&this.$gutterLayer.update(this.layerConfig):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.showGutter&&this.$gutterLayer.update(this.layerConfig),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(this.layerConfig),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(this.layerConfig),e&this.CHANGE_SIZE&&this.$updateScrollBar()},this.$computeLayerConfig=function(){var e=this.session,t=this.scrollTop%this.lineHeight,n=this.$size.scrollerHeight+this.lineHeight,r=this.$getLongestLine(),i=this.$horizScrollAlwaysVisible||this.$size.scrollerWidth-r<0,s=this.$horizScroll!==i;this.$horizScroll=i,s&&(this.scroller.style.overflowX=i?"scroll":"hidden",i||this.session.setScrollLeft(0));var o=this.session.getScreenLength()*this.lineHeight;this.session.setScrollTop(Math.max(0,Math.min(this.scrollTop,o-this.$size.scrollerHeight)));var u=Math.ceil(n/this.lineHeight)-1,a=Math.max(0,Math.round((this.scrollTop-t)/this.lineHeight)),f=a+u,l,c,h=this.lineHeight;a=e.screenToDocumentRow(a,0);var p=e.getFoldLine(a);p&&(a=p.start.row),l=e.documentToScreenRow(a,0),c=e.getRowLength(a)*h,f=Math.min(e.screenToDocumentRow(f,0),e.getLength()-1),n=this.$size.scrollerHeight+e.getRowLength(f)*h+c,t=this.scrollTop-l*h,this.layerConfig={width:r,padding:this.$padding,firstRow:a,firstRowScreen:l,lastRow:f,lineHeight:h,characterWidth:this.characterWidth,minHeight:n,maxHeight:o,offset:t,height:this.$size.scrollerHeight},this.$gutterLayer.element.style.marginTop=-t+"px",this.content.style.marginTop=-t+"px",this.content.style.width=r+2*this.$padding+"px",this.content.style.height=n+"px",s&&this.onResize(!0)},this.$updateLines=function(){var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(t<n.firstRow)return;if(t===Infinity){this.showGutter&&this.$gutterLayer.update(n),this.$textLayer.update(n);return}return this.$textLayer.updateLines(n,e,t),!0},this.$getLongestLine=function(){var e=this.session.getScreenWidth();return this.$textLayer.showInvisibles&&(e+=1),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(e*this.characterWidth))},this.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},this.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},this.addGutterDecoration=function(e,t){this.$gutterLayer.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){this.$gutterLayer.removeGutterDecoration(e,t)},this.updateBreakpoints=function(e){this.$loop.schedule(this.CHANGE_GUTTER)},this.setAnnotations=function(e){this.$gutterLayer.setAnnotations(e),this.$loop.schedule(this.CHANGE_GUTTER)},this.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},this.hideCursor=function(){this.$cursorLayer.hideCursor()},this.showCursor=function(){this.$cursorLayer.showCursor()},this.scrollSelectionIntoView=function(e,t,n){this.scrollCursorIntoView(e,n),this.scrollCursorIntoView(t,n)},this.scrollCursorIntoView=function(e,t){if(this.$size.scrollerHeight===0)return;var n=this.$cursorLayer.getPixelPosition(e),r=n.left,i=n.top;this.scrollTop>i?(t&&(i-=t*this.$size.scrollerHeight),this.session.setScrollTop(i)):this.scrollTop+this.$size.scrollerHeight<i+this.lineHeight&&(t&&(i+=t*this.$size.scrollerHeight),this.session.setScrollTop(i+this.lineHeight-this.$size.scrollerHeight));var s=this.scrollLeft;s>r?(r<this.$padding+2*this.layerConfig.characterWidth&&(r=0),this.session.setScrollLeft(r)):s+this.$size.scrollerWidth<r+this.characterWidth&&this.session.setScrollLeft(Math.round(r+this.characterWidth-this.$size.scrollerWidth))},this.getScrollTop=function(){return this.session.getScrollTop()},this.getScrollLeft=function(){return this.session.getScrollLeft()},this.getScrollTopRow=function(){return this.scrollTop/this.lineHeight},this.getScrollBottomRow=function(){return Math.max(0,Math.floor((this.scrollTop+this.$size.scrollerHeight)/this.lineHeight)-1)},this.scrollToRow=function(e){this.session.setScrollTop(e*this.lineHeight)},this.alignCursor=function(e,t){typeof e=="number"&&(e={row:e,column:0});var n=this.$cursorLayer.getPixelPosition(e),r=this.$size.scrollerHeight-this.lineHeight,i=n.top-r*(t||0);return this.session.setScrollTop(i),i},this.STEPS=8,this.$calcSteps=function(e,t){var n=0,r=this.STEPS,i=[],s=function(e,t,n){return n*(Math.pow(e-1,3)+1)+t};for(n=0;n<r;++n)i.push(s(n/this.STEPS,e,t-e));return i},this.scrollToLine=function(e,t,n,r){var i=this.$cursorLayer.getPixelPosition({row:e,column:0}),s=i.top;t&&(s-=this.$size.scrollerHeight/2);var o=this.scrollTop;this.session.setScrollTop(s),n!==!1&&this.animateScrolling(o,r)},this.animateScrolling=function(e,t){var n=this.scrollTop;if(this.$animatedScroll&&Math.abs(e-n)<1e5){var r=this,i=r.$calcSteps(e,n);this.$inScrollAnimation=!0,clearInterval(this.$timer),r.session.setScrollTop(i.shift()),this.$timer=setInterval(function(){i.length?(r.session.setScrollTop(i.shift()),r.session.$scrollTop=n):n!=null?(r.session.$scrollTop=-1,r.session.setScrollTop(n),n=null):(r.$timer=clearInterval(r.$timer),r.$inScrollAnimation=!1,t&&t())},10)}},this.scrollToY=function(e){this.scrollTop!==e&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=e)},this.scrollToX=function(e){e<0&&(e=0),this.scrollLeft!==e&&(this.scrollLeft=e),this.$loop.schedule(this.CHANGE_H_SCROLL)},this.scrollBy=function(e,t){t&&this.session.setScrollTop(this.session.getScrollTop()+t),e&&this.session.setScrollLeft(this.session.getScrollLeft()+e)},this.isScrollableBy=function(e,t){if(t<0&&this.session.getScrollTop()>0)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight<this.layerConfig.maxHeight)return!0},this.pixelToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=(e+this.scrollLeft-n.left-this.$padding)/this.characterWidth,i=Math.floor((t+this.scrollTop-n.top)/this.lineHeight),s=Math.round(r);return{row:i,column:s,side:r-s>0?1:-1}},this.screenToTextCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=Math.round((e+this.scrollLeft-n.left-this.$padding)/this.characterWidth),i=Math.floor((t+this.scrollTop-n.top)/this.lineHeight);return this.session.screenToDocumentPosition(i,Math.max(r,0))},this.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+Math.round(r.column*this.characterWidth),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},this.visualizeFocus=function(){i.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){i.removeCssClass(this.container,"ace_focus")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,i.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;i.removeCssClass(this.textarea,"ace_composition"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null},this._loadTheme=function(e,t){if(!u.get("packaged"))return t();a.loadScript(u.moduleUrl(e,"theme"),t)},this.setTheme=function(t){function u(e){i.importCssString(e.cssText,e.cssClass,n.container.ownerDocument),n.theme&&i.removeCssClass(n.container,n.theme.cssClass),n.$theme=e.cssClass,n.theme=e,i.addCssClass(n.container,e.cssClass),i.setCssClass(n.container,"ace_dark",e.isDark);var t=e.padding||4;n.$padding&&t!=n.$padding&&n.setPadding(t),n.$size&&(n.$size.width=0,n.onResize()),n._dispatchEvent("themeLoaded",{theme:e})}var n=this;this.$themeValue=t,n._dispatchEvent("themeChange",{theme:t});if(!t||typeof t=="string"){var r=t||"ace/theme/textmate",s;try{s=e(r)}catch(o){}if(s)return u(s);n._loadTheme(r,function(){e([r],function(e){if(n.$themeValue!==t)return;u(e)})})}else u(t)},this.getTheme=function(){return this.$themeValue},this.setStyle=function(t,n){i.setCssClass(this.container,t,n!=0)},this.unsetStyle=function(t){i.removeCssClass(this.container,t)},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(g.prototype),t.VirtualRenderer=g}),ace.define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/lang"),o=e("../lib/event_emitter").EventEmitter,u=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_gutter-layer",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this)};(function(){i.implement(this,o),this.setSession=function(e){this.session&&this.session.removeEventListener("change",this.$updateAnnotations),this.session=e,e.on("change",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.addGutterDecoration"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.removeGutterDecoration"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];var t,n;for(var r=0;r<e.length;r++){var i=e[r],n=i.row,t=this.$annotations[n];t||(t=this.$annotations[n]={text:[]});var o=i.text;o=o?s.escapeHTML(o):i.html||"",t.text.indexOf(o)===-1&&t.text.push(o);var u=i.type;u=="error"?t.className=" ace_error":u=="warning"&&t.className!=" ace_error"?t.className=" ace_warning":u=="info"&&!t.className&&(t.className=" ace_info")}},this.$updateAnnotations=function(e){if(!this.$annotations.length)return;var t=e.data,n=t.range,r=n.start.row,i=n.end.row-r;if(i!==0)if(t.action=="removeText"||t.action=="removeLines")this.$annotations.splice(r,i+1,null);else{var s=Array(i+1);s.unshift(r,1),this.$annotations.splice.apply(this.$annotations,s)}},this.update=function(e){var t={className:""},n=[],i=e.firstRow,s=e.lastRow,o=this.session.getNextFoldLine(i),u=o?o.start.row:Infinity,a=this.$showFoldWidgets&&this.session.foldWidgets,f=this.session.$breakpoints,l=this.session.$decorations,c=0;for(;;){i>u&&(i=o.end.row+1,o=this.session.getNextFoldLine(i,o),u=o?o.start.row:Infinity);if(i>s)break;var h=this.$annotations[i]||t;n.push("<div class='ace_gutter-cell ",f[i]||"",l[i]||"",h.className,"' style='height:",this.session.getRowLength(i)*e.lineHeight,"px;'>",c=i+1);if(a){var p=a[i];p==null&&(p=a[i]=this.session.getFoldWidget(i)),p&&n.push("<span class='ace_fold-widget ace_",p,p=="start"&&i==u&&i<o.end.row?" ace_closed":" ace_open","' style='height:",e.lineHeight,"px","'></span>")}n.push("</div>"),i++}this.element=r.setInnerHtml(this.element,n.join("")),this.element.style.height=e.minHeight+"px",this.session.$useWrapMode&&(c=this.session.getLength());var d=(""+c).length*e.characterWidth,v=this.$padding||this.$computePadding();d+=v.left+v.right,d!==this.gutterWidth&&(this.gutterWidth=d,this.element.style.width=Math.ceil(this.gutterWidth)+"px",this._emit("changeGutterWidth",d))},this.$showFoldWidgets=!0,this.setShowFoldWidgets=function(e){e?r.addCssClass(this.element,"ace_folding-enabled"):r.removeCssClass(this.element,"ace_folding-enabled"),this.$showFoldWidgets=e,this.$padding=null},this.getShowFoldWidgets=function(){return this.$showFoldWidgets},this.$computePadding=function(){if(!this.element.firstChild)return{left:0,right:0};var e=r.computedStyle(this.element.firstChild);return this.$padding={},this.$padding.left=parseInt(e.paddingLeft)+1,this.$padding.right=parseInt(e.paddingRight),this.$padding},this.getRegion=function(e){var t=this.$padding||this.$computePadding(),n=this.element.getBoundingClientRect();if(e.x<t.left+n.left)return"markers";if(this.$showFoldWidgets&&e.x>n.right-t.right)return"foldWidgets"}}).call(u.prototype),t.Gutter=u}),ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,t,n){var r=e("../range").Range,i=e("../lib/dom"),s=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){var e=e||this.config;if(!e)return;this.config=e;var t=[];for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var s=r.range.clipRows(e.firstRow,e.lastRow);if(s.isEmpty())continue;s=s.toScreenRange(this.session);if(r.renderer){var o=this.$getTop(s.start.row,e),u=this.$padding+s.start.column*e.characterWidth;r.renderer(t,s,u,o,e)}else r.type=="fullLine"?this.drawFullLineMarker(t,s,r.clazz,e):s.isMultiLine()?r.type=="text"?this.drawTextMarker(t,s,r.clazz,e):this.drawMultiLineMarker(t,s,r.clazz,e):this.drawSingleLineMarker(t,s,r.clazz+" ace_start",e)}this.element=i.setInnerHtml(this.element,t.join(""))},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(e,t,n,i){var s=t.start.row,o=new r(s,t.start.column,s,this.session.getScreenLastRowColumn(s));this.drawSingleLineMarker(e,o,n+" ace_start",i,1,"text"),s=t.end.row,o=new r(s,0,s,t.end.column),this.drawSingleLineMarker(e,o,n,i,0,"text");for(s=t.start.row+1;s<t.end.row;s++)o.start.row=s,o.end.row=s,o.end.column=this.session.getScreenLastRowColumn(s),this.drawSingleLineMarker(e,o,n,i,1,"text")},this.drawMultiLineMarker=function(e,t,n,r,i){var s=this.$padding,o=r.lineHeight,u=this.$getTop(t.start.row,r),a=s+t.start.column*r.characterWidth;e.push("<div class='",n," ace_start' style='","height:",o,"px;","right:0;","top:",u,"px;","left:",a,"px;'></div>"),u=this.$getTop(t.end.row,r);var f=t.end.column*r.characterWidth;e.push("<div class='",n,"' style='","height:",o,"px;","width:",f,"px;","top:",u,"px;","left:",s,"px;'></div>"),o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<0)return;u=this.$getTop(t.start.row+1,r),e.push("<div class='",n,"' style='","height:",o,"px;","right:0;","top:",u,"px;","left:",s,"px;'></div>")},this.drawSingleLineMarker=function(e,t,n,r,i){var s=r.lineHeight,o=(t.end.column+(i||0)-t.start.column)*r.characterWidth,u=this.$getTop(t.start.row,r),a=this.$padding+t.start.column*r.characterWidth;e.push("<div class='",n,"' style='","height:",s,"px;","width:",o,"px;","top:",u,"px;","left:",a,"px;'></div>")},this.drawFullLineMarker=function(e,t,n,r){var i=this.$getTop(t.start.row,r),s=r.lineHeight;t.start.row!=t.end.row&&(s+=this.$getTop(t.end.row,r)-i),e.push("<div class='",n,"' style='","height:",s,"px;","top:",i,"px;","left:0;right:0;'></div>")}}).call(s.prototype),t.Marker=s}),ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/useragent"),u=e("../lib/event_emitter").EventEmitter,a=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$characterSize={width:0,height:0},this.checkForSizeChanges(),this.$pollSizeChanges()};(function(){r.implement(this,u),this.EOF_CHAR="¶",this.EOL_CHAR="¬",this.TAB_CHAR="→",this.SPACE_CHAR="·",this.$padding=0,this.setPadding=function(e){this.$padding=e,this.element.style.padding="0 "+e+"px"},this.getLineHeight=function(){return this.$characterSize.height||1},this.getCharacterWidth=function(){return this.$characterSize.width||1},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight="bold";var t=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=e,this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit("changeCharacterSize",{data:e})}},this.$pollSizeChanges=function(){var e=this;this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.$fontStyles={fontFamily:1,fontSize:1,fontWeight:1,fontStyle:1,lineHeight:1},this.$measureSizes=o.isIE||o.isOldGecko?function(){var e=1e3;if(!this.$measureNode){var t=this.$measureNode=i.createElement("div"),n=t.style;n.width=n.height="auto",n.left=n.top=-e*40+"px",n.visibility="hidden",n.position="fixed",n.overflow="visible",n.whiteSpace="nowrap",t.innerHTML=s.stringRepeat("Xy",e);if(this.element.ownerDocument.body)this.element.ownerDocument.body.appendChild(t);else{var r=this.element.parentNode;while(!i.hasCssClass(r,"ace_editor"))r=r.parentNode;r.appendChild(t)}}if(!this.element.offsetWidth)return null;var n=this.$measureNode.style,o=i.computedStyle(this.element);for(var u in this.$fontStyles)n[u]=o[u];var a={height:this.$measureNode.offsetHeight,width:this.$measureNode.offsetWidth/(e*2)};return a.width==0||a.height==0?null:a}:function(){if(!this.$measureNode){var e=this.$measureNode=i.createElement("div"),t=e.style;t.width=t.height="auto",t.left=t.top="-100px",t.visibility="hidden",t.position="fixed",t.overflow="visible",t.whiteSpace="nowrap",e.innerHTML="X";var n=this.element.parentNode;while(n&&!i.hasCssClass(n,"ace_editor"))n=n.parentNode;if(!n)return this.$measureNode=null;n.appendChild(e)}var r=this.$measureNode.getBoundingClientRect(),s={height:r.height,width:r.width};return s.width==0||s.height==0?null:s},this.setSession=function(e){this.session=e,this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;n<e+1;n++)this.showInvisibles?t.push("<span class='ace_invisible'>"+this.TAB_CHAR+Array(n).join("&#160;")+"</span>"):t.push((new Array(n+1)).join("&#160;"));if(this.displayIndentGuides){this.$indentGuideRe=/\s\S| \t|\t |\s$/;var r="ace_indent-guide",i=Array(this.tabSize+1).join("&#160;"),s=i;this.showInvisibles&&(r+=" ace_invisible",s=this.TAB_CHAR+i.substr(6)),this.$tabStrings[" "]="<span class='"+r+"'>"+i+"</span>",this.$tabStrings[" "]="<span class='"+r+"'>"+s+"</span>"}},this.updateLines=function(e,t,n){(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)&&this.scrollLines(e),this.config=e;var r=Math.max(t,e.firstRow),s=Math.min(n,e.lastRow),o=this.element.childNodes,u=0;for(var a=e.firstRow;a<r;a++){var f=this.session.getFoldLine(a);if(f){if(f.containsRow(r)){r=f.start.row;break}a=f.end.row}u++}var a=r,f=this.session.getNextFoldLine(a),l=f?f.start.row:Infinity;for(;;){a>l&&(a=f.end.row+1,f=this.session.getNextFoldLine(a,f),l=f?f.start.row:Infinity);if(a>s)break;var c=o[u++];if(c){var h=[];this.$renderLine(h,a,!this.$useLineGroups(),a==l?f:!1),i.setInnerHtml(c,h.join(""))}a++}},this.scrollLines=function(e){var t=this.config;this.config=e;if(!t||t.lastRow<e.firstRow)return this.update(e);if(e.lastRow<t.firstRow)return this.update(e);var n=this.element;if(t.firstRow<e.firstRow)for(var r=this.session.getFoldedRowCount(t.firstRow,e.firstRow-1);r>0;r--)n.removeChild(n.firstChild);if(t.lastRow>e.lastRow)for(var r=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);r>0;r--)n.removeChild(n.lastChild);if(e.firstRow<t.firstRow){var i=this.$renderLinesFragment(e,e.firstRow,t.firstRow-1);n.firstChild?n.insertBefore(i,n.firstChild):n.appendChild(i)}if(e.lastRow>t.lastRow){var i=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);n.appendChild(i)}},this.$renderLinesFragment=function(e,t,n){var r=this.element.ownerDocument.createDocumentFragment(),s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=i.createElement("div"),f=[];this.$renderLine(f,s,!1,s==u?o:!1),a.innerHTML=f.join("");if(this.$useLineGroups())a.className="ace_line_group",r.appendChild(a);else{var l=a.childNodes;while(l.length)r.appendChild(l[0])}s++}return r},this.update=function(e){this.config=e;var t=[],n=e.firstRow,r=e.lastRow,s=n,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>r)break;this.$useLineGroups()&&t.push("<div class='ace_line_group'>"),this.$renderLine(t,s,!1,s==u?o:!1),this.$useLineGroups()&&t.push("</div>"),s++}this.element=i.setInnerHtml(this.element,t.join(""))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var i=this,s=/\t|&|<|( +)|([\x00-\x1f\x80-\xa0\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g,o=function(e,n,r,s,o){if(n)return(new Array(e.length+1)).join("&#160;");if(e=="&")return"&#38;";if(e=="<")return"&#60;";if(e==" "){var u=i.session.getScreenTabSize(t+s);return t+=u-1,i.$tabStrings[u]}if(e==" "){var a=i.showInvisibles?"ace_cjk ace_invisible":"ace_cjk",f=i.showInvisibles?i.SPACE_CHAR:"";return t+=1,"<span class='"+a+"' style='width:"+i.config.characterWidth*2+"px'>"+f+"</span>"}return r?"<span class='ace_invisible ace_invalid'>"+i.SPACE_CHAR+"</span>":(t+=1,"<span class='ace_cjk' style='width:"+i.config.characterWidth*2+"px'>"+e+"</span>")},u=r.replace(s,o);if(!this.$textToken[n.type]){var a="ace_"+n.type.replace(/\./g," ace_"),f="";n.type=="fold"&&(f=" style='width:"+n.value.length*this.config.characterWidth+"px;' "),e.push("<span class='",a,"'",f,">",u,"</span>")}else e.push(u);return t+r.length},this.renderIndentGuide=function(e,t){var n=t.search(this.$indentGuideRe);return n<=0?t:t[0]==" "?(n-=n%this.tabSize,e.push(Array(n/this.tabSize+1).join(this.$tabStrings[" "])),t.substr(n)):t[0]==" "?(e.push(Array(n+1).join(this.$tabStrings[" "])),t.substr(n)):t},this.$renderWrappedLine=function(e,t,n,r){var i=0,s=0,o=n[0],u=0;for(var a=0;a<t.length;a++){var f=t[a],l=f.value;if(a==0&&this.displayIndentGuides){i=l.length,l=this.renderIndentGuide(e,l);if(!l)continue;i-=l.length}if(i+l.length<o)u=this.$renderToken(e,u,f,l),i+=l.length;else{while(i+l.length>=o)u=this.$renderToken(e,u,f,l.substring(0,o-i)),l=l.substring(o-i),i=o,r||e.push("</div>","<div class='ace_line' style='height:",this.config.lineHeight,"px'>"),s++,u=0,o=n[s]||Number.MAX_VALUE;l.length!=0&&(i+=l.length,u=this.$renderToken(e,u,f,l))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;this.displayIndentGuides&&(i=this.renderIndentGuide(e,i)),i&&(n=this.$renderToken(e,n,r,i));for(var s=1;s<t.length;s++)r=t[s],i=r.value,n=this.$renderToken(e,n,r,i)},this.$renderLine=function(e,t,n,r){!r&&r!=0&&(r=this.session.getFoldLine(t));if(r)var i=this.$getFoldLineTokens(t,r);else var i=this.session.getTokens(t);n||e.push("<div class='ace_line' style='height:",this.config.lineHeight,"px'>");if(i.length){var s=this.session.getRowSplitData(t);s&&s.length?this.$renderWrappedLine(e,i,s,n):this.$renderSimpleLine(e,i)}this.showInvisibles&&(r&&(t=r.end.row),e.push("<span class='ace_invisible'>",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,"</span>")),n||e.push("</div>")},this.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.length<t){s+=e[i].value.length,i++;if(i==e.length)return}if(s!=t){var o=e[i].value.substring(t-s);o.length>n-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(s<n&&i<e.length){var o=e[i].value;o.length+s>n?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:"fold",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,t,n){var r=e("../lib/dom"),i=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors")};(function(){this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e!=this.smoothBlinking&&(this.smoothBlinking=e,e?r.addCssClass(this.element,"ace_smooth-blinking"):r.removeCssClass(this.element,"ace_smooth-blinking"),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.restartTimer=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,"ace_smooth-blinking");for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity="";if(!this.isBlinking||!this.blinkInterval||!this.isVisible)return;this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,"ace_smooth-blinking")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity=0}.bind(this),.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity="";t()}.bind(this),this.blinkInterval),t()},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+n.column*this.config.characterWidth,i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,n=0,r=0;if(t===undefined||t.length===0)t=[{cursor:null}];for(var n=t.length;n--;){var i=this.getPixelPosition(t[n].cursor,!0);if((i.top>e.height+e.offset||i.top<-e.offset)&&n>1)continue;var s=(this.cursors[r++]||this.addCursor()).style;s.left=i.left+"px",s.top=i.top+"px",s.width=e.characterWidth+"px",s.height=e.lineHeight+"px"}while(this.cursors.length>r)this.removeCursor();var o=this.session.getOverwrite();this.$setOverwrite(o),this.$pixelPos=i,this.restartTimer()},this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(i.prototype),t.Cursor=i}),ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/event_emitter").EventEmitter,u=function(e){this.element=i.createElement("div"),this.element.className="ace_scrollbar",this.inner=i.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.width=i.scrollbarWidth(e.ownerDocument),this.element.style.width=(this.width||15)+5+"px",s.addListener(this.element,"scroll",this.onScroll.bind(this))};(function(){r.implement(this,o),this.onScroll=function(){this.skipEvent||(this.scrollTop=this.element.scrollTop,this._emit("scroll",{data:this.scrollTop})),this.skipEvent=!1},this.getWidth=function(){return this.width},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=function(e){this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=this.element.scrollTop=e)}}).call(u.prototype),t.ScrollBar=u}),ace.define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,t,n){var r=e("./lib/event"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){this.changes=this.changes|e;if(!this.pending){this.pending=!0;var t=this;r.nextFrame(function(){t.pending=!1;var e;while(e=t.changes)t.changes=0,t.onRender(e)},this.window)}}}).call(i.prototype),t.RenderLoop=i}),ace.define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor"],function(e,t,n){function h(e,t,n){return c.$options.wrap=!0,c.$options.needle=t,c.$options.backwards=n==-1,c.find(e)}function v(e,t){return e.row==t.row&&e.column==t.column}function m(e){e.$onAddRange=e.$onAddRange.bind(e),e.$onRemoveRange=e.$onRemoveRange.bind(e),e.$onMultiSelect=e.$onMultiSelect.bind(e),e.$onSingleSelect=e.$onSingleSelect.bind(e),t.onSessionChange.call(e,e),e.on("changeSession",t.onSessionChange.bind(e)),e.on("mousedown",o),e.commands.addCommands(f.defaultCommands),g(e)}function g(e){function i(){n&&(r.style.cursor="",n=!1)}var t=e.textInput.getElement(),n=!1,r=e.renderer.content;u.addListener(t,"keydown",function(e){e.keyCode==18&&!(e.ctrlKey||e.shiftKey||e.metaKey)?n||(r.style.cursor="crosshair",n=!0):n&&(r.style.cursor="")}),u.addListener(t,"keyup",i),u.addListener(t,"blur",i)}var r=e("./range_list").RangeList,i=e("./range").Range,s=e("./selection").Selection,o=e("./mouse/multi_select_handler").onMouseDown,u=e("./lib/event"),a=e("./lib/lang"),f=e("./commands/multi_select_commands");t.commands=f.defaultCommands.concat(f.multiSelectCommands);var l=e("./search").Search,c=new l,p=e("./edit_session").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(p.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(e,t){if(!e)return;if(!this.inMultiSelectMode&&this.rangeCount==0){var n=this.toOrientedRange();if(e.intersects(n))return t||this.fromOrientedRange(e);this.rangeList.add(n),this.$onAddRange(n)}e.cursor||(e.cursor=e.end);var r=this.rangeList.add(e);return this.$onAddRange(e),r.length&&this.$onRemoveRange(r),this.rangeCount>1&&!this.inMultiSelectMode&&(this._emit("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._emit("addRange",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._emit("removeRange",{ranges:e}),this.rangeCount==0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._emit("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeList.ranges.concat()},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var n=this.getRange(),r=this.isBackwards(),s=n.start.row,o=n.end.row;if(s==o){if(r)var u=n.end,a=n.start;else var u=n.start,a=n.end;this.addRange(i.fromPoints(a,a)),this.addRange(i.fromPoints(u,u));return}var f=[],l=this.getLineRange(s,!0);l.start.column=n.start.column,f.push(l);for(var c=s+1;c<o;c++)f.push(this.getLineRange(c,!0));l=this.getLineRange(o,!0),l.end.column=n.end.column,f.push(l),f.forEach(this.addRange,this)}},this.toggleBlockSelection=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.selectionLead),s=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column<t.column;if(s)var o=e.column,u=t.column;else var o=t.column,u=e.column;var a=e.row<t.row;if(a)var f=e.row,l=t.row;else var f=t.row,l=e.row;o<0&&(o=0),f<0&&(f=0),f==l&&(n=!0);for(var c=f;c<=l;c++){var h=i.fromPoints(this.session.screenToDocumentPosition(c,o),this.session.screenToDocumentPosition(c,u));if(h.isEmpty()){if(p&&v(h.end,p))break;var p=h.end}h.cursor=s?h.start:h.end,r.push(h)}a&&r.reverse();if(!n){var d=r.length-1;while(r[d].isEmpty()&&d>0)d--;if(d>0){var m=0;while(r[m].isEmpty())m++}for(var g=d;g>=m;g--)r[g].isEmpty()&&r.splice(g,1)}return r}}.call(s.prototype);var d=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,"ace_selection",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.on("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeEventListener("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;t.multiSelectAction?t.multiSelectAction=="forEach"?n.forEachSelection(t,e.args):t.multiSelectAction=="single"?(n.exitMultiSelectMode(),t.exec(n,e.args||{})):t.multiSelectAction(n,e.args||{}):(t.exec(n,e.args||{}),n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()),e.preventDefault()},this.forEachSelection=function(e,t){if(this.inVirtualSelectionMode)return;var n=this.session,r=this.selection,i=r.rangeList,o=r._eventRegistry;r._eventRegistry={};var u=new s(n);this.inVirtualSelectionMode=!0;for(var a=i.ranges.length;a--;)u.fromOrientedRange(i.ranges[a]),this.selection=n.selection=u,e.exec(this,t||{}),u.toOrientedRange(i.ranges[a]);u.detach(),this.selection=n.selection=r,this.inVirtualSelectionMode=!1,r._eventRegistry=o,r.mergeOverlappingRanges(),this.onCursorChange(),this.onSelectionChange()},this.exitMultiSelectMode=function(){if(this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getCopyText=function(){var e="";if(this.inMultiSelectMode){var t=this.multiSelect.rangeList.ranges;e=[];for(var n=0;n<t.length;n++)e.push(this.session.getTextRange(t[n]));e=e.join(this.session.getDocument().getNewLineCharacter())}else this.selection.isEmpty()||(e=this.session.getTextRange(this.getSelectionRange()));return e},this.onPaste=function(e){if(this.$readOnly)return;this._emit("paste",e);if(!this.inMultiSelectMode)return this.insert(e);var t=e.split(/\r\n|\r|\n/),n=this.selection.rangeList.ranges;if(t.length>n.length||t.length<=2||!t[1])return this.commands.exec("insertstring",this,e);for(var r=n.length;r--;){var i=n[r];i.isEmpty()||this.session.remove(i),this.session.insert(i.start,t[r])}},this.findAll=function(e,t,n){t=t||{},t.needle=e||t.needle,this.$search.set(t);var r=this.$search.findAll(this.session);if(!r.length)return 0;this.$blockScrolling+=1;var i=this.multiSelect;n||i.toSingleRange(r[0]);for(var s=r.length;s--;)i.addRange(r[s],!0);return this.$blockScrolling-=1,r.length},this.selectMoreLines=function(e,t){var n=this.selection.toOrientedRange(),r=n.cursor==n.end,s=this.session.documentToScreenPosition(n.cursor);this.selection.$desiredColumn&&(s.column=this.selection.$desiredColumn);var o=this.session.screenToDocumentPosition(s.row+e,s.column);if(!n.isEmpty())var u=this.session.documentToScreenPosition(r?n.end:n.start),a=this.session.screenToDocumentPosition(u.row+e,u.column);else var a=o;if(r){var f=i.fromPoints(o,a);f.cursor=f.start}else{var f=i.fromPoints(a,o);f.cursor=f.end}f.desiredColumn=s.column;if(!this.selection.inMultiSelectMode)this.selection.addRange(n);else if(t)var l=n.cursor;this.selection.addRange(f),l&&this.selection.substractPoint(l)},this.transposeSelections=function(e){var t=this.session,n=t.multiSelect,r=n.ranges;for(var i=r.length;i--;){var s=r[i];if(s.isEmpty()){var o=t.getWordRange(s.start.row,s.start.column);s.start.row=o.start.row,s.start.column=o.start.column,s.end.row=o.end.row,s.end.column=o.end.column}}n.mergeOverlappingRanges();var u=[];for(var i=r.length;i--;){var s=r[i];u.unshift(t.getTextRange(s))}e<0?u.unshift(u.pop()):u.push(u.shift());for(var i=r.length;i--;){var s=r[i],o=s.clone();t.replace(s,u[i]),s.start.row=o.start.row,s.start.column=o.start.column}},this.selectMore=function(e,t){var n=this.session,r=n.multiSelect,i=r.toOrientedRange();if(i.isEmpty()){var i=n.getWordRange(i.start.row,i.start.column);i.cursor=i.end,this.multiSelect.addRange(i)}var s=n.getTextRange(i),o=h(n,s,e);o&&(o.cursor=e==-1?o.start:o.end,this.multiSelect.addRange(o)),t&&this.multiSelect.substractPoint(i.cursor)},this.alignCursors=function(){var e=this.session,t=e.multiSelect,n=t.ranges;if(!n.length){var r=this.selection.getRange(),s=r.start.row,o=r.end.row,u=this.session.doc.removeLines(s,o);u=this.$reAlignText(u),this.session.doc.insertLines(s,u),r.start.column=0,r.end.column=u[u.length-1].length,this.selection.setRange(r)}else{var f=-1,l=n.filter(function(e){if(e.cursor.row==f)return!0;f=e.cursor.row});t.$onRemoveRange(l);var c=0,h=Infinity,p=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\S/g);return i==-1&&(i=0),n.column>c&&(c=n.column),i<h&&(h=i),i});n.forEach(function(t,n){var r=t.cursor,s=c-r.column,o=p[n]-h;s>o?e.insert(r,a.stringRepeat(" ",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=c,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e){function o(e,t){return Array(e+1).join(t)}function u(e){return e[2]?o(r," ")+e[2]+o(i-e[2].length+s," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function a(e){return e[2]?o(r+i-e[2].length," ")+e[2]+o(s," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function f(e){return e[2]?o(r," ")+e[2]+o(s," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}var t=!0,n=!0,r,i,s;return e.map(function(e){var o=e.match(/(\s*)(.*?)(\s*)([=:].*)/);return o?r==null?(r=o[1].length,i=o[2].length,s=o[3].length,o):(r+i+s!=o[1].length+o[2].length+o[3].length&&(n=!1),r!=o[1].length&&(t=!1),r>o[1].length&&(r=o[1].length),i<o[2].length&&(i=o[2].length),s>o[3].length&&(s=o[3].length),o):[e]}).map(t?n?a:u:f)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t.multiSelect||(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t.multiSelect;var n=e.oldSession;n&&(n.multiSelect&&n.multiSelect.editor==this&&(n.multiSelect.editor=null),t.multiSelect.removeEventListener("addRange",this.$onAddRange),t.multiSelect.removeEventListener("removeRange",this.$onRemoveRange),t.multiSelect.removeEventListener("multiSelect",this.$onMultiSelect),t.multiSelect.removeEventListener("singleSelect",this.$onSingleSelect)),t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m}),ace.define("ace/range_list",["require","exports","module"],function(e,t,n){var r=function(){this.ranges=[]};(function(){this.comparePoints=function(e,t){return e.row-t.row||e.column-t.column},this.pointIndex=function(e,t){var n=this.ranges;for(var r=t||0;r<n.length;r++){var i=n[r],s=this.comparePoints(e,i.end);if(s>0)continue;return s==0?r:(s=this.comparePoints(e,i.start),s>=0?r:-r-1)}return-r-1},this.add=function(e){var t=this.pointIndex(e.start);t<0&&(t=-t-1);var n=this.pointIndex(e.end,t);return n<0?n=-n-1:n++,this.ranges.splice(t,n-t,e)},this.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.call(t,this.add(e[n]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},this.merge=function(){var e=[],t=this.ranges,n=t[0],r;for(var i=1;i<t.length;i++){r=n,n=t[i];var s=this.comparePoints(r.end,n.start);if(s<0)continue;if(s==0&&!r.isEmpty()&&!n.isEmpty())continue;this.comparePoints(r.end,n.end)<0&&(r.end.row=n.end.row,r.end.column=n.end.column),t.splice(i,1),e.push(n),n=r,i--}return e},this.contains=function(e,t){return this.pointIndex({row:e,column:t})>=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},this.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.row<e)return[];var r=this.pointIndex({row:e,column:0});r<0&&(r=-r-1);var i=this.pointIndex({row:t,column:0},r);i<0&&(i=-i-1);var s=[];for(var o=r;o<i;o++)s.push(n[o]);return s},this.removeAll=function(){return this.ranges.splice(0,this.ranges.length)},this.attach=function(e){this.session&&this.detach(),this.session=e,this.onChange=this.$onChange.bind(this),this.session.on("change",this.onChange)},this.detach=function(){if(!this.session)return;this.session.removeListener("change",this.onChange),this.session=null},this.$onChange=function(e){var t=e.data.range;if(e.data.action[0]=="i")var n=t.start,r=t.end;else var r=t.start,n=t.end;var i=n.row,s=r.row,o=s-i,u=-n.column+r.column,a=this.ranges;for(var f=0,l=a.length;f<l;f++){var c=a[f];if(c.end.row<i)continue;if(c.start.row>i)break;c.start.row==i&&c.start.column>=n.column&&(c.start.column+=u,c.start.row+=o),c.end.row==i&&c.end.column>=n.column&&(c.end.column+=u,c.end.row+=o)}if(o!=0&&f<l)for(;f<l;f++){var c=a[f];c.start.row+=o,c.end.row+=o}}}).call(r.prototype),t.RangeList=r}),ace.define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event"],function(e,t,n){function i(e,t){return e.row==t.row&&e.column==t.column}function s(e){var t=e.domEvent,n=t.altKey,s=t.shiftKey,o=e.getAccelKey(),u=e.getButton();if(e.editor.inMultiSelectMode&&u==2){e.editor.textInput.onContextMenu(e.domEvent);return}if(!o&&!n){u==0&&e.editor.inMultiSelectMode&&e.editor.exitMultiSelectMode();return}var a=e.editor,f=a.selection,l=a.inMultiSelectMode,c=e.getDocumentPosition(),h=f.getCursor(),p=e.inSelection()||f.isEmpty()&&i(c,h),d=e.x,v=e.y,m=function(e){d=e.clientX,v=e.clientY},g=function(){var e=a.renderer.pixelToScreenCoordinates(d,v),t=y.screenToDocumentPosition(e.row,e.column);if(i(w,e)&&i(t,f.selectionLead))return;w=e,a.selection.moveCursorToPosition(t),a.selection.clearSelection(),a.renderer.scrollCursorIntoView(),a.removeSelectionMarkers(x),x=f.rectangularRangeBlock(w,b),x.forEach(a.addSelectionMarker,a),a.updateSelectionMarkers()},y=a.session,b=a.renderer.pixelToScreenCoordinates(d,v),w=b;if(o&&!s&&!n&&u==0){if(!l&&p)return;if(!l){var E=f.toOrientedRange();a.addSelectionMarker(E)}var S=f.rangeList.rangeAtPoint(c);r.capture(a.container,function(){},function(){var e=f.toOrientedRange();S&&e.isEmpty()&&i(S.cursor,e.cursor)?f.substractPoint(e.cursor):(E&&(a.removeSelectionMarker(E),f.addRange(E)),f.addRange(e))})}else if(!s&&n&&u==0){e.stop(),l&&!o?f.toSingleRange():!l&&o&&f.addRange(),f.moveCursorToPosition(c),f.clearSelection();var x=[],T=function(e){clearInterval(C),a.removeSelectionMarkers(x);for(var t=0;t<x.length;t++)f.addRange(x[t])},N=g;r.capture(a.container,m,T);var C=setInterval(function(){N()},20);return e.preventDefault()}}var r=e("../lib/event");t.onMouseDown=s}),ace.define("ace/commands/multi_select_commands",["require","exports","module","ace/keyboard/hash_handler"],function(e,t,n){t.defaultCommands=[{name:"addCursorAbove",exec:function(e){e.selectMoreLines(-1)},bindKey:{win:"Ctrl-Alt-Up",mac:"Ctrl-Alt-Up"},readonly:!0},{name:"addCursorBelow",exec:function(e){e.selectMoreLines(1)},bindKey:{win:"Ctrl-Alt-Down",mac:"Ctrl-Alt-Down"},readonly:!0},{name:"addCursorAboveSkipCurrent",exec:function(e){e.selectMoreLines(-1,!0)},bindKey:{win:"Ctrl-Alt-Shift-Up",mac:"Ctrl-Alt-Shift-Up"},readonly:!0},{name:"addCursorBelowSkipCurrent",exec:function(e){e.selectMoreLines(1,!0)},bindKey:{win:"Ctrl-Alt-Shift-Down",mac:"Ctrl-Alt-Shift-Down"},readonly:!0},{name:"selectMoreBefore",exec:function(e){e.selectMore(-1)},bindKey:{win:"Ctrl-Alt-Left",mac:"Ctrl-Alt-Left"},readonly:!0},{name:"selectMoreAfter",exec:function(e){e.selectMore(1)},bindKey:{win:"Ctrl-Alt-Right",mac:"Ctrl-Alt-Right"},readonly:!0},{name:"selectNextBefore",exec:function(e){e.selectMore(-1,!0)},bindKey:{win:"Ctrl-Alt-Shift-Left",mac:"Ctrl-Alt-Shift-Left"},readonly:!0},{name:"selectNextAfter",exec:function(e){e.selectMore(1,!0)},bindKey:{win:"Ctrl-Alt-Shift-Right",mac:"Ctrl-Alt-Shift-Right"},readonly:!0},{name:"splitIntoLines",exec:function(e){e.multiSelect.splitIntoLines()},bindKey:{win:"Ctrl-Alt-L",mac:"Ctrl-Alt-L"},readonly:!0},{name:"alignCursors",exec:function(e){e.alignCursors()},bindKey:{win:"Ctrl-Alt-A",mac:"Ctrl-Alt-A"}}],t.multiSelectCommands=[{name:"singleSelection",bindKey:"esc",exec:function(e){e.exitMultiSelectMode()},readonly:!0,isAvailable:function(e){return e&&e.inMultiSelectMode}}];var r=e("../keyboard/hash_handler").HashHandler;t.keyboardHandler=new r(t.multiSelectCommands)}),ace.define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/config"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/event_emitter").EventEmitter,s=e("../config"),o=function(t,n,r){this.changeListener=this.changeListener.bind(this),this.onMessage=this.onMessage.bind(this),this.onError=this.onError.bind(this);var i;if(s.get("packaged"))i=s.moduleUrl(n,"worker");else{var o=this.$normalizePath;typeof e.supports!="undefined"&&e.supports.indexOf("ucjs2-pinf-0")>=0?i=e.nameToUrl("ace/worker/worker_sourcemint"):(e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl),i=o(e.toUrl("ace/worker/worker",null,"_")));var u={};t.forEach(function(t){u[t]=o(e.toUrl(t,null,"_").replace(/.js(\?.*)?$/,""))})}this.$worker=new Worker(i),this.$worker.postMessage({init:!0,tlns:u,module:n,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onerror=this.onError,this.$worker.onmessage=this.onMessage};(function(){r.implement(this,i),this.onError=function(e){throw window.console&&console.log&&console.log(e),e},this.onMessage=function(e){var t=e.data;switch(t.type){case"log":window.console&&console.log&&console.log.apply(console,t.data);break;case"event":this._emit(t.name,{data:t.data});break;case"call":var n=this.callbacks[t.id];n&&(n(t.data),delete this.callbacks[t.id])}},this.$normalizePath=function(e){return location.host?(e=e.replace(/^[a-z]+:\/\/[^\/]+/,""),e=location.protocol+"//"+location.host+(e.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+e.replace(/^[\/]+/,""),e):e},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,n){if(n){var r=this.callbackId++;this.callbacks[r]=n,t.push(r)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(n){}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call("setValue",[e.getValue()]),e.on("change",this.changeListener)},this.changeListener=function(e){e.range={start:e.data.range.start,end:e.data.range.end},this.emit("change",e)}}).call(o.prototype);var u=function(t,n,r){this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var s=null,o=Object.create(i),u=this;this.$worker={},this.$worker.postMessage=function(e){u.messageBuffer.push(e),s&&setTimeout(a)};var a=function(){var e=u.messageBuffer.shift();e.command?s[e.command].apply(s,e.args):e.event&&o._emit(e.event,e.data)};o.postMessage=function(e){u.onMessage({data:e})},o.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},o.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},e([n],function(e){s=new e[r](o);while(u.messageBuffer.length)a()})};u.prototype=o.prototype,t.UIWorkerClient=u,t.WorkerClient=o}),ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,t,n){var r=e("./range").Range,i=e("./lib/event_emitter").EventEmitter,s=e("./lib/oop"),o=function(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session,i=this.$pos;this.pos=t.createAnchor(i.row,i.column),this.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.pos.on("change",function(t){n.removeMarker(e.markerId),e.markerId=n.addMarker(new r(t.value.row,t.value.column,t.value.row,t.value.column+e.length),e.mainClass,null,!1)}),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1),n.on("change",function(i){e.removeMarker(n.markerId),n.markerId=e.addMarker(new r(i.value.row,i.value.column,i.value.row,i.value.column+t.length),t.othersClass,null,!1)})})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e<this.others.length;e++)this.session.removeMarker(this.others[e].markerId)},this.onUpdate=function(e){var t=e.data,n=t.range;if(n.start.row!==n.end.row)return;if(n.start.row!==this.pos.row)return;if(this.$updating)return;this.$updating=!0;var i=t.action==="insertText"?n.end.column-n.start.column:n.start.column-n.end.column;if(n.start.column>=this.pos.column&&n.start.column<=this.pos.column+this.length+1){var s=n.start.column-this.pos.column;this.length+=i;if(!this.session.$fromUndo){if(t.action==="insertText")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};u.row===n.start.row&&n.start.column<u.column&&(a.column+=i),this.doc.insert(a,t.text)}else if(t.action==="removeText")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};u.row===n.start.row&&n.start.column<u.column&&(a.column+=i),this.doc.remove(new r(a.row,a.column,a.row,a.column-i))}n.start.column===this.pos.column&&t.action==="insertText"?setTimeout(function(){this.pos.setPosition(this.pos.row,this.pos.column-i);for(var e=0;e<this.others.length;e++){var t=this.others[e],r={row:t.row,column:t.column-i};t.row===n.start.row&&n.start.column<t.column&&(r.column+=i),t.setPosition(r.row,r.column)}}.bind(this),0):n.start.column===this.pos.column&&t.action==="removeText"&&setTimeout(function(){for(var e=0;e<this.others.length;e++){var t=this.others[e];t.row===n.start.row&&n.start.column<t.column&&t.setPosition(t.row,t.column-i)}}.bind(this),0)}this.pos._emit("change",{value:this.pos});for(var o=0;o<this.others.length;o++)this.others[o]._emit("change",{value:this.others[o]})}this.$updating=!1},this.onCursorChange=function(e){if(this.$updating)return;var t=this.session.selection.getCursor();t.row===this.pos.row&&t.column>=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e))},this.detach=function(){this.session.removeMarker(this.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.pos.detach();for(var e=0;e<this.others.length;e++)this.others[e].detach();this.session.setUndoSelect(!0)},this.cancel=function(){if(this.$undoStackDepth===-1)throw Error("Canceling placeholders only supported with undo manager attached to session.");var e=this.session.getUndoManager(),t=(e.$undoStack||e.$undostack).length-this.$undoStackDepth;for(var n=0;n<t;n++)e.undo(!0)}}).call(o.prototype),t.PlaceHolder=o}),ace.define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(e,t,n){var r=e("../../range").Range,i=t.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(e,t,n){var r=e.getLine(n);return this.foldingStartMarker.test(r)?"start":t=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(r)?"end":""},this.getFoldWidgetRange=function(e,t,n){return null},this.indentationBlock=function(e,t,n){var i=/\S/,s=e.getLine(t),o=s.search(i);if(o==-1)return;var u=n||s.length,a=e.getLength(),f=t,l=t;while(++t<a){var c=e.getLine(t).search(i);if(c==-1)continue;if(c<=o)break;l=t}if(l>f){var h=e.getLine(l).length;return new r(f,u,l,h)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=this.getFoldWidget(e,u.row)),a=="start"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)});
+ (function() {
+ ace.require(["ace/ace"], function(a) {
+ a && a.config.init();
+ if (!window.ace)
+ window.ace = {};
+ for (var key in a) if (a.hasOwnProperty(key))
+ ace[key] = a[key];
+ });
+ })();
+ \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-css.js b/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-css.js
new file mode 100644
index 00000000..20155551
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-css.js
@@ -0,0 +1 @@
+ace.define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./css_highlight_rules").CssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("../worker/worker_client").WorkerClient,f=e("./behaviour/cstyle").CstyleBehaviour,l=e("./folding/cstyle").FoldMode,c=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.$behaviour=new f,this.foldingRules=new l};r.inherits(c,i),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new a(["ace"],"ace/mode/css_worker","Worker");return t.attachToDocument(e.getDocument()),t.on("csslint",function(t){e.setAnnotations(t.data)}),t.on("terminate",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),ace.define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=t.supportType="animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index",u=t.supportFunction="rgb|rgba|url|attr|counter|counters",a=t.supportConstant="absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero",f=t.supportConstantColor="aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow",l=t.supportConstantFonts="arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace",c=t.numRe="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h=t.pseudoElements="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",p=t.pseudoClasses="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",d=function(){var e=this.createKeywordMapper({"support.function":u,"support.constant":a,"support.type":o,"support.constant.color":f,"support.constant.fonts":l},"text",!0),t=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+c+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:"constant.numeric",regex:c},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:p},{token:e,regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],n=i.copyArray(t);n.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var r=i.copyArray(t);r.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var s=[{token:"comment",merge:!0,regex:".+"}],d=i.copyArray(s);d.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var v=i.copyArray(s);v.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=i.copyArray(s);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:d,ruleset:n,ruleset_comment:m,media_ruleset:r,media_comment:v}};r.inherits(d,s),t.CssHighlightRules=d}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;v<c.length;v++){p=c[v],p.type=="string"?d=-1:d<0&&(d=p.value.indexOf(s));if(p.value.length+h>o.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=='"')return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/ace/readme.txt b/plugins/jetpack/modules/custom-css/custom-css/js/ace/readme.txt
new file mode 100644
index 00000000..6ef94f82
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/js/ace/readme.txt
@@ -0,0 +1 @@
+The ACE editor files in this directory were pulled from https://github.com/ajaxorg/ace-builds/tree/master/src-min-noconflict, package 12.17.2012. \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/ace/theme-textmate.js b/plugins/jetpack/modules/custom-css/custom-css/js/ace/theme-textmate.js
new file mode 100644
index 00000000..d8ef4710
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/js/ace/theme-textmate.js
@@ -0,0 +1 @@
+ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm .ace_scroller {background-color: #FFFFFF;}.ace-tm .ace_cursor {border-left: 2px solid black;}.ace-tm .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_markup.ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_markup.ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;border-radius: 2px;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}';var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)}) \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/ace/worker-css.js b/plugins/jetpack/modules/custom-css/custom-css/js/ace/worker-css.js
new file mode 100644
index 00000000..59ceeaf5
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/js/ace/worker-css.js
@@ -0,0 +1 @@
+"no use strict";function initBaseUrls(e){require.tlns=e}function initSender(){var e=require(null,"ace/lib/event_emitter").EventEmitter,t=require(null,"ace/lib/oop"),n=function(){};return function(){t.implement(this,e),this.callback=function(e,t){postMessage({type:"call",id:t,data:e})},this.emit=function(e,t){postMessage({type:"event",name:e,data:t})}}.call(n.prototype),new n}if(typeof window!="undefined"&&window.document)throw"atempt to load ace worker into main window instead of webWorker";var console={log:function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})},error:function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})}},window={console:console},normalizeModule=function(e,t){if(t.indexOf("!")!==-1){var n=t.split("!");return normalizeModule(e,n[0])+"!"+normalizeModule(e,n[1])}if(t.charAt(0)=="."){var r=e.split("/").slice(0,-1).join("/"),t=r+"/"+t;while(t.indexOf(".")!==-1&&i!=t)var i=t,t=t.replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}return t},require=function(e,t){if(!t.charAt)throw new Error("worker.js require() accepts only (parentId, id) as arguments");var t=normalizeModule(e,t),n=require.modules[t];if(n)return n.initialized||(n.initialized=!0,n.exports=n.factory().exports),n.exports;var r=t.split("/");r[0]=require.tlns[r[0]]||r[0];var i=r.join("/")+".js";return require.id=t,importScripts(i),require(e,t)};require.modules={},require.tlns={};var define=function(e,t,n){arguments.length==2?(n=t,typeof e!="string"&&(t=e,e=require.id)):arguments.length==1&&(n=e,e=require.id);if(e.indexOf("text!")===0)return;var r=function(t,n){return require(e,t,n)};require.modules[e]={factory:function(){var e={exports:{}},t=n(r,e.exports,e);return t&&(e.exports=t),e}}},main,sender;onmessage=function(e){var t=e.data;if(t.command){if(!main[t.command])throw new Error("Unknown command:"+t.command);main[t.command].apply(main,t.args)}else if(t.init){initBaseUrls(t.tlns),require(null,"ace/lib/fixoldbrowsers"),sender=initSender();var n=require(null,t.module)[t.classname];main=new n(sender)}else t.event&&sender&&sender._emit(t.event,t.data)},define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"],function(e,t,n){e("./regexp"),e("./es5-shim")}),define("ace/lib/regexp",["require","exports","module"],function(e,t,n){function o(e){return(e.global?"g":"")+(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":"")}function u(e,t,n){if(Array.prototype.indexOf)return e.indexOf(t,n);for(var r=n||0;r<e.length;r++)if(e[r]===t)return r;return-1}var r={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},i=r.exec.call(/()??/,"")[1]===undefined,s=function(){var e=/^/g;return r.test.call(e,""),!e.lastIndex}();if(s&&i)return;RegExp.prototype.exec=function(e){var t=r.exec.apply(this,arguments),n,a;if(typeof e=="string"&&t){!i&&t.length>1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;e<arguments.length-2;e++)arguments[e]===undefined&&(t[e]=undefined)}));if(this._xregexp&&this._xregexp.captureNames)for(var f=1;f<t.length;f++)n=this._xregexp.captureNames[f-1],n&&(t[n]=t[f]);!s&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function m(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError;var r=o.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e,u=n.apply(s,r.concat(o.call(arguments)));return u!==null&&Object(u)===u?u:s}return n.apply(t,r.concat(o.call(arguments)))};return i});var r=Function.prototype.call,i=Array.prototype,s=Object.prototype,o=i.slice,u=r.bind(s.toString),a=r.bind(s.hasOwnProperty),f,l,c,h,p;if(p=a(s,"__defineGetter__"))f=r.bind(s.__defineGetter__),l=r.bind(s.__defineSetter__),c=r.bind(s.__lookupGetter__),h=r.bind(s.__lookupSetter__);Array.isArray||(Array.isArray=function(t){return u(t)=="[object Array]"}),Array.prototype.forEach||(Array.prototype.forEach=function(t){var n=D(this),r=arguments[1],i=0,s=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;while(i<s)i in n&&t.call(r,n[i],i,n),i++}),Array.prototype.map||(Array.prototype.map=function(t){var n=D(this),r=n.length>>>0,i=Array(r),s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o<r;o++)o in n&&(i[o]=t.call(s,n[o],o,n));return i}),Array.prototype.filter||(Array.prototype.filter=function(t){var n=D(this),r=n.length>>>0,i=[],s=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var o=0;o<r;o++)o in n&&t.call(s,n[o],o,n)&&i.push(n[o]);return i}),Array.prototype.every||(Array.prototype.every=function(t){var n=D(this),r=n.length>>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s<r;s++)if(s in n&&!t.call(i,n[s],s,n))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(t){var n=D(this),r=n.length>>>0,i=arguments[1];if(u(t)!="[object Function]")throw new TypeError;for(var s=0;s<r;s++)if(s in n&&t.call(i,n[s],s,n))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(t){var n=D(this),r=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i=0,s;if(arguments.length>=2)s=arguments[1];else do{if(i in n){s=n[i++];break}if(++i>=r)throw new TypeError}while(!0);for(;i<r;i++)i in n&&(s=t.call(void 0,s,n[i],i,n));return s}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(t){var n=D(this),r=n.length>>>0;if(u(t)!="[object Function]")throw new TypeError;if(!r&&arguments.length==1)throw new TypeError;var i,s=r-1;if(arguments.length>=2)i=arguments[1];else do{if(s in n){i=n[s--];break}if(--s<0)throw new TypeError}while(!0);do s in this&&(i=t.call(void 0,i,n[s],s,n));while(s--);return i}),Array.prototype.indexOf||(Array.prototype.indexOf=function(t){var n=D(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=M(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i<r;i++)if(i in n&&n[i]===t)return i;return-1}),Array.prototype.lastIndexOf||(Array.prototype.lastIndexOf=function(t){var n=D(this),r=n.length>>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,M(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:s)});if(!Object.getOwnPropertyDescriptor){var d="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(d+t);if(!a(t,n))return;var r,i,o;r={enumerable:!0,configurable:!0};if(p){var u=t.__proto__;t.__proto__=s;var i=c(t,n),o=h(t,n);t.__proto__=u;if(i||o)return i&&(r.get=i),o&&(r.set=o),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var v;Object.prototype.__proto__===null?v=function(){return{__proto__:null}}:v=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=v();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var g=m({}),y=typeof document=="undefined"||m(document.createElement("div"));if(!g||!y)var b=Object.defineProperty}if(!Object.defineProperty||b){var w="Property description must be an object: ",E="Object.defineProperty called on non-object: ",S="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(E+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(w+r);if(b)try{return b.call(Object,t,n,r)}catch(i){}if(a(r,"value"))if(p&&(c(t,n)||h(t,n))){var o=t.__proto__;t.__proto__=s,delete t[n],t[n]=r.value,t.__proto__=o}else t[n]=r.value;else{if(!p)throw new TypeError(S);a(r,"get")&&f(t,n,r.get),a(r,"set")&&l(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)a(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(x){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(a(t,n))n+="?";t[n]=!0;var r=a(t,n);return delete t[n],r});if(!Object.keys){var T=!0,N=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],C=N.length;for(var k in{toString:null})T=!1;Object.keys=function P(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var P=[];for(var t in e)a(e,t)&&P.push(t);if(T)for(var n=0,r=C;n<r;n++){var i=N[n];a(e,i)&&P.push(i)}return P}}if(!Date.prototype.toISOString||(new Date(-621987552e5)).toISOString().indexOf("-000001")===-1)Date.prototype.toISOString=function(){var t,n,r,i;if(!isFinite(this))throw new RangeError;t=[this.getUTCMonth()+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()],i=this.getUTCFullYear(),i=(i<0?"-":i>9999?"+":"")+("00000"+Math.abs(i)).slice(0<=i&&i<=9999?-4:-6),n=t.length;while(n--)r=t[n],r<10&&(t[n]="0"+r);return i+"-"+t.slice(0,2).join("-")+"T"+t.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(t){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()}),Date.parse("+275760-09-13T00:00:00.000Z")!==864e13&&(Date=function(e){var t=function i(t,n,r,s,o,u,a){var f=arguments.length;if(this instanceof e){var l=f==1&&String(t)===t?new e(i.parse(t)):f>=7?new e(t,n,r,s,o,u,a):f>=6?new e(t,n,r,s,o,u):f>=5?new e(t,n,r,s,o):f>=4?new e(t,n,r,s):f>=3?new e(t,n,r):f>=2?new e(t,n):f>=1?new e(t):new e;return l.constructor=i,l}return e.apply(this,arguments)},n=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$");for(var r in e)t[r]=e[r];return t.now=e.now,t.UTC=e.UTC,t.prototype=e.prototype,t.prototype.constructor=t,t.parse=function(r){var i=n.exec(r);if(i){i.shift();for(var s=1;s<7;s++)i[s]=+(i[s]||(s<3?1:0)),s==1&&i[s]--;var o=+i.pop(),u=+i.pop(),a=i.pop(),f=0;if(a){if(u>23||o>59)return NaN;f=(u*60+o)*6e4*(a=="+"?-1:1)}var l=+i[0];return 0<=l&&l<=99?(i[0]=l+400,e.UTC.apply(this,i)+f-126227808e5):e.UTC.apply(this,i)+f}return e.parse.apply(this,arguments)},t}(Date));var L=" \n \f\r   ᠎ â€â€‚         âŸã€€\u2028\u2029";if(!String.prototype.trim||L.trim()){L="["+L+"]";var A=new RegExp("^"+L+L+"*"),O=new RegExp(L+L+"*$");String.prototype.trim=function(){return String(this).replace(A,"").replace(O,"")}}var M=function(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e},_="a"[0]!="a",D=function(e){if(e==null)throw new TypeError;return _&&typeof e=="string"&&e?e.split(""):Object(e)}}),define("ace/lib/event_emitter",["require","exports","module"],function(e,t,n){var r={};r._emit=r._dispatchEvent=function(e,t){this._eventRegistry=this._eventRegistry||{},this._defaultHandlers=this._defaultHandlers||{};var n=this._eventRegistry[e]||[],r=this._defaultHandlers[e];if(!n.length&&!r)return;if(typeof t!="object"||!t)t={};t.type||(t.type=e),t.stopPropagation||(t.stopPropagation=function(){this.propagationStopped=!0}),t.preventDefault||(t.preventDefault=function(){this.defaultPrevented=!0});for(var i=0;i<n.length;i++){n[i](t);if(t.propagationStopped)break}if(r&&!t.defaultPrevented)return r(t)},r.setDefaultHandler=function(e,t){this._defaultHandlers=this._defaultHandlers||{};if(this._defaultHandlers[e])throw new Error("The default handler for '"+e+"' is already set");this._defaultHandlers[e]=t},r.on=r.addEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];n||(n=this._eventRegistry[e]=[]),n.indexOf(t)==-1&&n.push(t)},r.removeListener=r.removeEventListener=function(e,t){this._eventRegistry=this._eventRegistry||{};var n=this._eventRegistry[e];if(!n)return;var r=n.indexOf(t);r!==-1&&n.splice(r,1)},r.removeAllListeners=function(e){this._eventRegistry&&(this._eventRegistry[e]=[])},t.EventEmitter=r}),define("ace/lib/oop",["require","exports","module"],function(e,t,n){t.inherits=function(){var e=function(){};return function(t,n){e.prototype=n.prototype,t.super_=n.prototype,t.prototype=new e,t.prototype.constructor=t}}(),t.mixin=function(e,t){for(var n in t)e[n]=t[n]},t.implement=function(e,n){t.mixin(e,n)}}),define("ace/mode/css_worker",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/worker/mirror","ace/mode/css/csslint"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("../worker/mirror").Mirror,o=e("./css/csslint").CSSLint,u=t.Worker=function(e){s.call(this,e),this.setTimeout(400),this.ruleset=null,this.setDisabledRules("ids"),this.setInfoRules("adjoining-classes|qualified-headings|zero-units|gradients|import|outline-none")};r.inherits(u,s),function(){this.setInfoRules=function(e){typeof e=="string"&&(e=e.split("|")),this.infoRules=i.arrayToMap(e),this.doc.getValue()&&this.deferredUpdate.schedule(100)},this.setDisabledRules=function(e){if(!e)this.ruleset=null;else{typeof e=="string"&&(e=e.split("|"));var t={};o.getRules().forEach(function(e){t[e.id]=!0}),e.forEach(function(e){delete t[e]}),console.log(t),this.ruleset=t}this.doc.getValue()&&this.deferredUpdate.schedule(100)},this.onUpdate=function(){var e=this.doc.getValue(),t=this.infoRules,n=o.verify(e,this.ruleset);this.sender.emit("csslint",n.messages.map(function(e){return{row:e.line-1,column:e.col-1,text:e.message,type:t[e.rule.id]?"info":e.type}}))}}.call(u.prototype)}),define("ace/lib/lang",["require","exports","module"],function(e,t,n){t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){return(new Array(t+1)).join(e)};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n<r;n++)e[n]&&typeof e[n]=="object"?t[n]=this.copyObject(e[n]):t[n]=e[n];return t},t.deepCopy=function(e){if(typeof e!="object")return e;var t=e.constructor();for(var n in e)typeof e[n]=="object"?t[n]=this.deepCopy(e[n]):t[n]=e[n];return t},t.arrayToMap=function(e){var t={};for(var n=0;n<e.length;n++)t[e[n]]=1;return t},t.createMap=function(e){var t=Object.create(null);for(var n in e)t[n]=e[n];return t},t.arrayRemove=function(e,t){for(var n=0;n<=e.length;n++)t===e[n]&&e.splice(n,1)},t.escapeRegExp=function(e){return e.replace(/([.*+?^${}()|[\]\/\\])/g,"\\$1")},t.escapeHTML=function(e){return e.replace(/&/g,"&#38;").replace(/"/g,"&#34;").replace(/'/g,"&#39;").replace(/</g,"&#60;")},t.getMatchOffsets=function(e,t){var n=[];return e.replace(t,function(e){n.push({offset:arguments[arguments.length-2],length:e.length})}),n},t.deferredCall=function(e){var t=null,n=function(){t=null,e()},r=function(e){return r.cancel(),t=setTimeout(n,e||0),r};return r.schedule=r,r.call=function(){return this.cancel(),e(),r},r.cancel=function(){return clearTimeout(t),t=null,r},r},t.delayedCall=function(e,t){var n=null,r=function(){n=null,e()},i=function(e){n&&clearTimeout(n),n=setTimeout(r,e||t)};return i.delay=i,i.schedule=function(e){n==null&&(n=setTimeout(r,e||0))},i.call=function(){this.cancel(),e()},i.cancel=function(){n&&clearTimeout(n),n=null},i.isPending=function(){return n},i}}),define("ace/worker/mirror",["require","exports","module","ace/document","ace/lib/lang"],function(e,t,n){var r=e("../document").Document,i=e("../lib/lang"),s=t.Mirror=function(e){this.sender=e;var t=this.doc=new r(""),n=this.deferredUpdate=i.deferredCall(this.onUpdate.bind(this)),s=this;e.on("change",function(e){t.applyDeltas([e.data]),n.schedule(s.$timeout)})};(function(){this.$timeout=500,this.setTimeout=function(e){this.$timeout=e},this.setValue=function(e){this.doc.setValue(e),this.deferredUpdate.schedule(this.$timeout)},this.getValue=function(e){this.sender.callback(this.doc.getValue(),e)},this.onUpdate=function(){}}).call(s.prototype)}),define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=e("./range").Range,o=e("./anchor").Anchor,u=function(e){this.$lines=[],e.length==0?this.$lines=[""]:Array.isArray(e)?this.insertLines(0,e):this.insert({row:0,column:0},e)};(function(){r.implement(this,i),this.setValue=function(e){var t=this.getLength();this.remove(new s(0,0,t,this.getLine(t-1).length)),this.insert({row:0,column:0},e)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(e,t){return new o(this,e,t)},"aaa".split(/a/).length==0?this.$split=function(e){return e.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(e){return e.split(/\r\n|\r|\n/)},this.$detectNewLine=function(e){var t=e.match(/^.*?(\r\n|\r|\n)/m);t?this.$autoNewLine=t[1]:this.$autoNewLine="\n"},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";case"auto":return this.$autoNewLine}},this.$autoNewLine="\n",this.$newLineMode="auto",this.setNewLineMode=function(e){if(this.$newLineMode===e)return;this.$newLineMode=e},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(e){return e=="\r\n"||e=="\r"||e=="\n"},this.getLine=function(e){return this.$lines[e]||""},this.getLines=function(e,t){return this.$lines.slice(e,t+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(e){if(e.start.row==e.end.row)return this.$lines[e.start.row].substring(e.start.column,e.end.column);var t=this.getLines(e.start.row+1,e.end.row-1);return t.unshift((this.$lines[e.start.row]||"").substring(e.start.column)),t.push((this.$lines[e.end.row]||"").substring(0,e.end.column)),t.join(this.getNewLineCharacter())},this.$clipPosition=function(e){var t=this.getLength();return e.row>=t&&(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length),e},this.insert=function(e,t){if(!t||t.length===0)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(t);var n=this.$split(t),r=n.splice(0,1)[0],i=n.length==0?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),i!==null&&(e=this.insertNewLine(e),e=this.insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){if(t.length==0)return{row:e,column:0};if(t.length>65535){var n=this.insertLines(e,t.slice(65535));t=t.slice(0,65535)}var r=[e,0];r.push.apply(r,t),this.$lines.splice.apply(this.$lines,r);var i=new s(e,0,e+t.length,0),o={action:"insertLines",range:i,lines:t};return this._emit("change",{data:o}),n||i.end},this.insertNewLine=function(e){e=this.$clipPosition(e);var t=this.$lines[e.row]||"";this.$lines[e.row]=t.substring(0,e.column),this.$lines.splice(e.row+1,0,t.substring(e.column,t.length));var n={row:e.row+1,column:0},r={action:"insertText",range:s.fromPoints(e,n),text:this.getNewLineCharacter()};return this._emit("change",{data:r}),n},this.insertInLine=function(e,t){if(t.length==0)return e;var n=this.$lines[e.row]||"";this.$lines[e.row]=n.substring(0,e.column)+t+n.substring(e.column);var r={row:e.row,column:e.column+t.length},i={action:"insertText",range:s.fromPoints(e,r),text:t};return this._emit("change",{data:i}),r},this.remove=function(e){e.start=this.$clipPosition(e.start),e.end=this.$clipPosition(e.end);if(e.isEmpty())return e.start;var t=e.start.row,n=e.end.row;if(e.isMultiLine()){var r=e.start.column==0?t:t+1,i=n-1;e.end.column>0&&this.removeInLine(n,0,e.end.column),i>=r&&this.removeLines(r,i),r!=t&&(this.removeInLine(t,e.start.column,this.getLine(t).length),this.removeNewLine(e.start.row))}else this.removeInLine(t,e.start.column,e.end.column);return e.start},this.removeInLine=function(e,t,n){if(t==n)return;var r=new s(e,t,e,n),i=this.getLine(e),o=i.substring(t,n),u=i.substring(0,t)+i.substring(n,i.length);this.$lines.splice(e,1,u);var a={action:"removeText",range:r,text:o};return this._emit("change",{data:a}),r.start},this.removeLines=function(e,t){var n=new s(e,0,t+1,0),r=this.$lines.splice(e,t-e+1),i={action:"removeLines",range:n,nl:this.getNewLineCharacter(),lines:r};return this._emit("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),r=new s(e,t.length,e+1,0),i=t+n;this.$lines.splice(e,2,i);var o={action:"removeText",range:r,text:this.getNewLineCharacter()};this._emit("change",{data:o})},this.replace=function(e,t){if(t.length==0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);if(t)var n=this.insert(e.start,t);else n=e.start;return n},this.applyDeltas=function(e){for(var t=0;t<e.length;t++){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.insertLines(r.start.row,n.lines):n.action=="insertText"?this.insert(r.start,n.text):n.action=="removeLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="removeText"&&this.remove(r)}},this.revertDeltas=function(e){for(var t=e.length-1;t>=0;t--){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="insertText"?this.remove(r):n.action=="removeLines"?this.insertLines(r.start.row,n.lines):n.action=="removeText"&&this.insert(r.start,n.text)}}}).call(u.prototype),t.Document=u}),define("ace/range",["require","exports","module"],function(e,t,n){var r=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row==e.start.row&&this.end.row==e.end.row&&this.start.column==e.start.column&&this.end.column==e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?t<this.start.column?-1:t>this.end.column?1:0:e<this.start.row?-1:e>this.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};if(this.start.row>t)var i={row:t+1,column:0};if(this.start.row<e)var i={row:e,column:0};if(this.end.row<e)var n={row:e,column:0};return r.fromPoints(i||this.start,n||this.end)},this.extend=function(e,t){var n=this.compare(e,t);if(n==0)return this;if(n==-1)var i={row:e,column:t};else var s={row:e,column:t};return r.fromPoints(i||this.start,s||this.end)},this.isEmpty=function(){return this.start.row==this.end.row&&this.start.column==this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return r.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new r(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new r(this.start.row,0,this.end.row,0)},this.toScreenRange=function(e){var t=e.documentToScreenPosition(this.start),n=e.documentToScreenPosition(this.end);return new r(t.row,t.column,n.row,n.column)}}).call(r.prototype),r.fromPoints=function(e,t){return new r(e.row,e.column,t.row,t.column)},t.Range=r}),define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=t.Anchor=function(e,t,n){this.document=e,typeof n=="undefined"?this.setPosition(t.row,t.column):this.setPosition(t,n),this.$onChange=this.onChange.bind(this),e.on("change",this.$onChange)};(function(){r.implement(this,i),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.onChange=function(e){var t=e.data,n=t.range;if(n.start.row==n.end.row&&n.start.row!=this.row)return;if(n.start.row>this.row)return;if(n.start.row==this.row&&n.start.column>this.column)return;var r=this.row,i=this.column;t.action==="insertText"?n.start.row===r&&n.start.column<=i?n.start.row===n.end.row?i+=n.end.column-n.start.column:(i-=n.start.column,r+=n.end.row-n.start.row):n.start.row!==n.end.row&&n.start.row<r&&(r+=n.end.row-n.start.row):t.action==="insertLines"?n.start.row<=r&&(r+=n.end.row-n.start.row):t.action=="removeText"?n.start.row==r&&n.start.column<i?n.end.column>=i?i=n.start.column:i=Math.max(0,i-(n.end.column-n.start.column)):n.start.row!==n.end.row&&n.start.row<r?(n.end.row==r&&(i=Math.max(0,i-n.end.column)+n.start.column),r-=n.end.row-n.start.row):n.end.row==r&&(r-=n.end.row-n.start.row,i=Math.max(0,i-n.end.column)+n.start.column):t.action=="removeLines"&&n.start.row<=r&&(n.end.row<=r?r-=n.end.row-n.start.row:(r=n.start.row,i=0)),this.setPosition(r,i,!0)},this.setPosition=function(e,t,n){var r;n?r={row:e,column:t}:r=this.$clipPositionToDocument(e,t);if(this.row==r.row&&this.column==r.column)return;var i={row:this.row,column:this.column};this.row=r.row,this.column=r.column,this._emit("change",{old:i,value:r})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.$clipPositionToDocument=function(e,t){var n={};return e>=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/mode/css/csslint",["require","exports","module"],function(require,exports,module){function Reporter(e,t){this.messages=[],this.stats=[],this.lines=e,this.ruleset=t}var parserlib={};(function(){function e(){this._listeners={}}function t(e){this._input=e.replace(/\n\r?/g,"\n"),this._line=1,this._col=1,this._cursor=0}function n(e,t,n){this.col=n,this.line=t,this.message=e}function r(e,t,n,r){this.col=n,this.line=t,this.text=e,this.type=r}function i(e,n){this._reader=e?new t(e.toString()):null,this._token=null,this._tokenData=n,this._lt=[],this._ltIndex=0,this._ltIndexCache=[]}e.prototype={constructor:e,addListener:function(e,t){this._listeners[e]||(this._listeners[e]=[]),this._listeners[e].push(t)},fire:function(e){typeof e=="string"&&(e={type:e}),typeof e.target!="undefined"&&(e.target=this);if(typeof e.type=="undefined")throw new Error("Event object missing 'type' property.");if(this._listeners[e.type]){var t=this._listeners[e.type].concat();for(var n=0,r=t.length;n<r;n++)t[n].call(this,e)}},removeListener:function(e,t){if(this._listeners[e]){var n=this._listeners[e];for(var r=0,i=n.length;r<i;r++)if(n[r]===t){n.splice(r,1);break}}}},t.prototype={constructor:t,getCol:function(){return this._col},getLine:function(){return this._line},eof:function(){return this._cursor==this._input.length},peek:function(e){var t=null;return e=typeof e=="undefined"?1:e,this._cursor<this._input.length&&(t=this._input.charAt(this._cursor+e-1)),t},read:function(){var e=null;return this._cursor<this._input.length&&(this._input.charAt(this._cursor)=="\n"?(this._line++,this._col=1):this._col++,e=this._input.charAt(this._cursor++)),e},mark:function(){this._bookmark={cursor:this._cursor,line:this._line,col:this._col}},reset:function(){this._bookmark&&(this._cursor=this._bookmark.cursor,this._line=this._bookmark.line,this._col=this._bookmark.col,delete this._bookmark)},readTo:function(e){var t="",n;while(t.length<e.length||t.lastIndexOf(e)!=t.length-e.length){n=this.read();if(!n)throw new Error('Expected "'+e+'" at line '+this._line+", col "+this._col+".");t+=n}return t},readWhile:function(e){var t="",n=this.read();while(n!==null&&e(n))t+=n,n=this.read();return t},readMatch:function(e){var t=this._input.substring(this._cursor),n=null;return typeof e=="string"?t.indexOf(e)===0&&(n=this.readCount(e.length)):e instanceof RegExp&&e.test(t)&&(n=this.readCount(RegExp.lastMatch.length)),n},readCount:function(e){var t="";while(e--)t+=this.read();return t}},n.prototype=new Error,r.fromToken=function(e){return new r(e.value,e.startLine,e.startCol)},r.prototype={constructor:r,valueOf:function(){return this.toString()},toString:function(){return this.text}},i.createTokenData=function(e){var t=[],n={},r=e.concat([]),i=0,s=r.length+1;r.UNKNOWN=-1,r.unshift({name:"EOF"});for(;i<s;i++)t.push(r[i].name),r[r[i].name]=i,r[i].text&&(n[r[i].text]=i);return r.name=function(e){return t[e]},r.type=function(e){return n[e]},r},i.prototype={constructor:i,match:function(e,t){e instanceof Array||(e=[e]);var n=this.get(t),r=0,i=e.length;while(r<i)if(n==e[r++])return!0;return this.unget(),!1},mustMatch:function(e,t){var r;e instanceof Array||(e=[e]);if(!this.match.apply(this,arguments))throw r=this.LT(1),new n("Expected "+this._tokenData[e[0]].name+" at line "+r.startLine+", col "+r.startCol+".",r.startLine,r.startCol)},advance:function(e,t){while(this.LA(0)!==0&&!this.match(e,t))this.get();return this.LA(0)},get:function(e){var t=this._tokenData,n=this._reader,r,i=0,s=t.length,o=!1,u,a;if(this._lt.length&&this._ltIndex>=0&&this._ltIndex<this._lt.length){i++,this._token=this._lt[this._ltIndex++],a=t[this._token.type];while(a.channel!==undefined&&e!==a.channel&&this._ltIndex<this._lt.length)this._token=this._lt[this._ltIndex++],a=t[this._token.type],i++;if((a.channel===undefined||e===a.channel)&&this._ltIndex<=this._lt.length)return this._ltIndexCache.push(i),this._token.type}return u=this._getToken(),u.type>-1&&!t[u.type].hide&&(u.channel=t[u.type].channel,this._token=u,this._lt.push(u),this._ltIndexCache.push(this._lt.length-this._ltIndex+i),this._lt.length>5&&this._lt.shift(),this._ltIndexCache.length>5&&this._ltIndexCache.shift(),this._ltIndex=this._lt.length),a=t[u.type],a&&(a.hide||a.channel!==undefined&&e!==a.channel)?this.get(e):u.type},LA:function(e){var t=e,n;if(e>0){if(e>5)throw new Error("Too much lookahead.");while(t)n=this.get(),t--;while(t<e)this.unget(),t++}else if(e<0){if(!this._lt[this._ltIndex+e])throw new Error("Too much lookbehind.");n=this._lt[this._ltIndex+e].type}else n=this._token.type;return n},LT:function(e){return this.LA(e),this._lt[this._ltIndex+e-1]},peek:function(){return this.LA(1)},token:function(){return this._token},tokenName:function(e){return e<0||e>this._tokenData.length?"UNKNOWN_TOKEN":this._tokenData[e].name},tokenType:function(e){return this._tokenData[e]||-1},unget:function(){if(!this._ltIndexCache.length)throw new Error("Too much lookahead.");this._ltIndex-=this._ltIndexCache.pop(),this._token=this._lt[this._ltIndex-1]}},parserlib.util={StringReader:t,SyntaxError:n,SyntaxUnit:r,EventTarget:e,TokenStreamBase:i}})(),function(){function Combinator(e,t,n){SyntaxUnit.call(this,e,t,n,Parser.COMBINATOR_TYPE),this.type="unknown",/^\s+$/.test(e)?this.type="descendant":e==">"?this.type="child":e=="+"?this.type="adjacent-sibling":e=="~"&&(this.type="sibling")}function MediaFeature(e,t){SyntaxUnit.call(this,"("+e+(t!==null?":"+t:"")+")",e.startLine,e.startCol,Parser.MEDIA_FEATURE_TYPE),this.name=e,this.value=t}function MediaQuery(e,t,n,r,i){SyntaxUnit.call(this,(e?e+" ":"")+(t?t+" ":"")+n.join(" and "),r,i,Parser.MEDIA_QUERY_TYPE),this.modifier=e,this.mediaType=t,this.features=n}function Parser(e){EventTarget.call(this),this.options=e||{},this._tokenStream=null}function PropertyName(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.PROPERTY_NAME_TYPE),this.hack=t}function PropertyValue(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n,Parser.PROPERTY_VALUE_TYPE),this.parts=e}function PropertyValueIterator(e){this._i=0,this._parts=e.parts,this._marks=[],this.value=e}function PropertyValuePart(text,line,col){SyntaxUnit.call(this,text,line,col,Parser.PROPERTY_VALUE_PART_TYPE),this.type="unknown";var temp;if(/^([+\-]?[\d\.]+)([a-z]+)$/i.test(text)){this.type="dimension",this.value=+RegExp.$1,this.units=RegExp.$2;switch(this.units.toLowerCase()){case"em":case"rem":case"ex":case"px":case"cm":case"mm":case"in":case"pt":case"pc":case"ch":this.type="length";break;case"deg":case"rad":case"grad":this.type="angle";break;case"ms":case"s":this.type="time";break;case"hz":case"khz":this.type="frequency";break;case"dpi":case"dpcm":this.type="resolution"}}else/^([+\-]?[\d\.]+)%$/i.test(text)?(this.type="percentage",this.value=+RegExp.$1):/^([+\-]?[\d\.]+)%$/i.test(text)?(this.type="percentage",this.value=+RegExp.$1):/^([+\-]?\d+)$/i.test(text)?(this.type="integer",this.value=+RegExp.$1):/^([+\-]?[\d\.]+)$/i.test(text)?(this.type="number",this.value=+RegExp.$1):/^#([a-f0-9]{3,6})/i.test(text)?(this.type="color",temp=RegExp.$1,temp.length==3?(this.red=parseInt(temp.charAt(0)+temp.charAt(0),16),this.green=parseInt(temp.charAt(1)+temp.charAt(1),16),this.blue=parseInt(temp.charAt(2)+temp.charAt(2),16)):(this.red=parseInt(temp.substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring(4,6),16))):/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3):/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100):/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3,this.alpha=+RegExp.$4):/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100,this.alpha=+RegExp.$4):/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100):/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100,this.alpha=+RegExp.$4):/^url\(["']?([^\)"']+)["']?\)/i.test(text)?(this.type="uri",this.uri=RegExp.$1):/^([^\(]+)\(/i.test(text)?(this.type="function",this.name=RegExp.$1,this.value=text):/^["'][^"']*["']/.test(text)?(this.type="string",this.value=eval(text)):Colors[text.toLowerCase()]?(this.type="color",temp=Colors[text.toLowerCase()].substring(1),this.red=parseInt(temp.substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring(4,6),16)):/^[\,\/]$/.test(text)?(this.type="operator",this.value=text):/^[a-z\-\u0080-\uFFFF][a-z0-9\-\u0080-\uFFFF]*$/i.test(text)&&(this.type="identifier",this.value=text)}function Selector(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n,Parser.SELECTOR_TYPE),this.parts=e,this.specificity=Specificity.calculate(this)}function SelectorPart(e,t,n,r,i){SyntaxUnit.call(this,n,r,i,Parser.SELECTOR_PART_TYPE),this.elementName=e,this.modifiers=t}function SelectorSubPart(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.SELECTOR_SUB_PART_TYPE),this.type=t,this.args=[]}function Specificity(e,t,n,r){this.a=e,this.b=t,this.c=n,this.d=r}function isHexDigit(e){return e!==null&&h.test(e)}function isDigit(e){return e!==null&&/\d/.test(e)}function isWhitespace(e){return e!==null&&/\s/.test(e)}function isNewLine(e){return e!==null&&nl.test(e)}function isNameStart(e){return e!==null&&/[a-z_\u0080-\uFFFF\\]/i.test(e)}function isNameChar(e){return e!==null&&(isNameStart(e)||/[0-9\-\\]/.test(e))}function isIdentStart(e){return e!==null&&(isNameStart(e)||/\-\\/.test(e))}function mix(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function TokenStream(e){TokenStreamBase.call(this,e,Tokens)}function ValidationError(e,t,n){this.col=n,this.line=t,this.message=e}var EventTarget=parserlib.util.EventTarget,TokenStreamBase=parserlib.util.TokenStreamBase,StringReader=parserlib.util.StringReader,SyntaxError=parserlib.util.SyntaxError,SyntaxUnit=parserlib.util.SyntaxUnit,Colors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};Combinator.prototype=new SyntaxUnit,Combinator.prototype.constructor=Combinator,MediaFeature.prototype=new SyntaxUnit,MediaFeature.prototype.constructor=MediaFeature,MediaQuery.prototype=new SyntaxUnit,MediaQuery.prototype.constructor=MediaQuery,Parser.DEFAULT_TYPE=0,Parser.COMBINATOR_TYPE=1,Parser.MEDIA_FEATURE_TYPE=2,Parser.MEDIA_QUERY_TYPE=3,Parser.PROPERTY_NAME_TYPE=4,Parser.PROPERTY_VALUE_TYPE=5,Parser.PROPERTY_VALUE_PART_TYPE=6,Parser.SELECTOR_TYPE=7,Parser.SELECTOR_PART_TYPE=8,Parser.SELECTOR_SUB_PART_TYPE=9,Parser.prototype=function(){var e=new EventTarget,t,n={constructor:Parser,DEFAULT_TYPE:0,COMBINATOR_TYPE:1,MEDIA_FEATURE_TYPE:2,MEDIA_QUERY_TYPE:3,PROPERTY_NAME_TYPE:4,PROPERTY_VALUE_TYPE:5,PROPERTY_VALUE_PART_TYPE:6,SELECTOR_TYPE:7,SELECTOR_PART_TYPE:8,SELECTOR_SUB_PART_TYPE:9,_stylesheet:function(){var e=this._tokenStream,t=null,n,r,i;this.fire("startstylesheet"),this._charset(),this._skipCruft();while(e.peek()==Tokens.IMPORT_SYM)this._import(),this._skipCruft();while(e.peek()==Tokens.NAMESPACE_SYM)this._namespace(),this._skipCruft();i=e.peek();while(i>Tokens.EOF){try{switch(i){case Tokens.MEDIA_SYM:this._media(),this._skipCruft();break;case Tokens.PAGE_SYM:this._page(),this._skipCruft();break;case Tokens.FONT_FACE_SYM:this._font_face(),this._skipCruft();break;case Tokens.KEYFRAMES_SYM:this._keyframes(),this._skipCruft();break;case Tokens.UNKNOWN_SYM:e.get();if(!!this.options.strict)throw new SyntaxError("Unknown @ rule.",e.LT(0).startLine,e.LT(0).startCol);this.fire({type:"error",error:null,message:"Unknown @ rule: "+e.LT(0).value+".",line:e.LT(0).startLine,col:e.LT(0).startCol}),n=0;while(e.advance([Tokens.LBRACE,Tokens.RBRACE])==Tokens.LBRACE)n++;while(n)e.advance([Tokens.RBRACE]),n--;break;case Tokens.S:this._readWhitespace();break;default:if(!this._ruleset())switch(i){case Tokens.CHARSET_SYM:throw r=e.LT(1),this._charset(!1),new SyntaxError("@charset not allowed here.",r.startLine,r.startCol);case Tokens.IMPORT_SYM:throw r=e.LT(1),this._import(!1),new SyntaxError("@import not allowed here.",r.startLine,r.startCol);case Tokens.NAMESPACE_SYM:throw r=e.LT(1),this._namespace(!1),new SyntaxError("@namespace not allowed here.",r.startLine,r.startCol);default:e.get(),this._unexpectedToken(e.token())}}}catch(s){if(!(s instanceof SyntaxError&&!this.options.strict))throw s;this.fire({type:"error",error:s,message:s.message,line:s.line,col:s.col})}i=e.peek()}i!=Tokens.EOF&&this._unexpectedToken(e.token()),this.fire("endstylesheet")},_charset:function(e){var t=this._tokenStream,n,r,i,s;t.match(Tokens.CHARSET_SYM)&&(i=t.token().startLine,s=t.token().startCol,this._readWhitespace(),t.mustMatch(Tokens.STRING),r=t.token(),n=r.value,this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),e!==!1&&this.fire({type:"charset",charset:n,line:i,col:s}))},_import:function(e){var t=this._tokenStream,n,r,i,s=[];t.mustMatch(Tokens.IMPORT_SYM),i=t.token(),this._readWhitespace(),t.mustMatch([Tokens.STRING,Tokens.URI]),r=t.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/,"$1"),this._readWhitespace(),s=this._media_query_list(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace(),e!==!1&&this.fire({type:"import",uri:r,media:s,line:i.startLine,col:i.startCol})},_namespace:function(e){var t=this._tokenStream,n,r,i,s;t.mustMatch(Tokens.NAMESPACE_SYM),n=t.token().startLine,r=t.token().startCol,this._readWhitespace(),t.match(Tokens.IDENT)&&(i=t.token().value,this._readWhitespace()),t.mustMatch([Tokens.STRING,Tokens.URI]),s=t.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/,"$1"),this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace(),e!==!1&&this.fire({type:"namespace",prefix:i,uri:s,line:n,col:r})},_media:function(){var e=this._tokenStream,t,n,r;e.mustMatch(Tokens.MEDIA_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),r=this._media_query_list(),e.mustMatch(Tokens.LBRACE),this._readWhitespace(),this.fire({type:"startmedia",media:r,line:t,col:n});for(;;)if(e.peek()==Tokens.PAGE_SYM)this._page();else if(!this._ruleset())break;e.mustMatch(Tokens.RBRACE),this._readWhitespace(),this.fire({type:"endmedia",media:r,line:t,col:n})},_media_query_list:function(){var e=this._tokenStream,t=[];this._readWhitespace(),(e.peek()==Tokens.IDENT||e.peek()==Tokens.LPAREN)&&t.push(this._media_query());while(e.match(Tokens.COMMA))this._readWhitespace(),t.push(this._media_query());return t},_media_query:function(){var e=this._tokenStream,t=null,n=null,r=null,i=[];e.match(Tokens.IDENT)&&(n=e.token().value.toLowerCase(),n!="only"&&n!="not"?(e.unget(),n=null):r=e.token()),this._readWhitespace(),e.peek()==Tokens.IDENT?(t=this._media_type(),r===null&&(r=e.token())):e.peek()==Tokens.LPAREN&&(r===null&&(r=e.LT(1)),i.push(this._media_expression()));if(t===null&&i.length===0)return null;this._readWhitespace();while(e.match(Tokens.IDENT))e.token().value.toLowerCase()!="and"&&this._unexpectedToken(e.token()),this._readWhitespace(),i.push(this._media_expression());return new MediaQuery(n,t,i,r.startLine,r.startCol)},_media_type:function(){return this._media_feature()},_media_expression:function(){var e=this._tokenStream,t=null,n,r=null;return e.mustMatch(Tokens.LPAREN),t=this._media_feature(),this._readWhitespace(),e.match(Tokens.COLON)&&(this._readWhitespace(),n=e.LT(1),r=this._expression()),e.mustMatch(Tokens.RPAREN),this._readWhitespace(),new MediaFeature(t,r?new SyntaxUnit(r,n.startLine,n.startCol):null)},_media_feature:function(){var e=this._tokenStream;return e.mustMatch(Tokens.IDENT),SyntaxUnit.fromToken(e.token())},_page:function(){var e=this._tokenStream,t,n,r=null,i=null;e.mustMatch(Tokens.PAGE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),e.match(Tokens.IDENT)&&(r=e.token().value,r.toLowerCase()==="auto"&&this._unexpectedToken(e.token())),e.peek()==Tokens.COLON&&(i=this._pseudo_page()),this._readWhitespace(),this.fire({type:"startpage",id:r,pseudo:i,line:t,col:n}),this._readDeclarations(!0,!0),this.fire({type:"endpage",id:r,pseudo:i,line:t,col:n})},_margin:function(){var e=this._tokenStream,t,n,r=this._margin_sym();return r?(t=e.token().startLine,n=e.token().startCol,this.fire({type:"startpagemargin",margin:r,line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endpagemargin",margin:r,line:t,col:n}),!0):!1},_margin_sym:function(){var e=this._tokenStream;return e.match([Tokens.TOPLEFTCORNER_SYM,Tokens.TOPLEFT_SYM,Tokens.TOPCENTER_SYM,Tokens.TOPRIGHT_SYM,Tokens.TOPRIGHTCORNER_SYM,Tokens.BOTTOMLEFTCORNER_SYM,Tokens.BOTTOMLEFT_SYM,Tokens.BOTTOMCENTER_SYM,Tokens.BOTTOMRIGHT_SYM,Tokens.BOTTOMRIGHTCORNER_SYM,Tokens.LEFTTOP_SYM,Tokens.LEFTMIDDLE_SYM,Tokens.LEFTBOTTOM_SYM,Tokens.RIGHTTOP_SYM,Tokens.RIGHTMIDDLE_SYM,Tokens.RIGHTBOTTOM_SYM])?SyntaxUnit.fromToken(e.token()):null},_pseudo_page:function(){var e=this._tokenStream;return e.mustMatch(Tokens.COLON),e.mustMatch(Tokens.IDENT),e.token().value},_font_face:function(){var e=this._tokenStream,t,n;e.mustMatch(Tokens.FONT_FACE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),this.fire({type:"startfontface",line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endfontface",line:t,col:n})},_operator:function(){var e=this._tokenStream,t=null;return e.match([Tokens.SLASH,Tokens.COMMA])&&(t=e.token(),this._readWhitespace()),t?PropertyValuePart.fromToken(t):null},_combinator:function(){var e=this._tokenStream,t=null,n;return e.match([Tokens.PLUS,Tokens.GREATER,Tokens.TILDE])&&(n=e.token(),t=new Combinator(n.value,n.startLine,n.startCol),this._readWhitespace()),t},_unary_operator:function(){var e=this._tokenStream;return e.match([Tokens.MINUS,Tokens.PLUS])?e.token().value:null},_property:function(){var e=this._tokenStream,t=null,n=null,r,i,s,o;return e.peek()==Tokens.STAR&&this.options.starHack&&(e.get(),i=e.token(),n=i.value,s=i.startLine,o=i.startCol),e.match(Tokens.IDENT)&&(i=e.token(),r=i.value,r.charAt(0)=="_"&&this.options.underscoreHack&&(n="_",r=r.substring(1)),t=new PropertyName(r,n,s||i.startLine,o||i.startCol),this._readWhitespace()),t},_ruleset:function(){var e=this._tokenStream,t,n;try{n=this._selectors_group()}catch(r){if(r instanceof SyntaxError&&!this.options.strict){this.fire({type:"error",error:r,message:r.message,line:r.line,col:r.col}),t=e.advance([Tokens.RBRACE]);if(t!=Tokens.RBRACE)throw r;return!0}throw r}return n&&(this.fire({type:"startrule",selectors:n,line:n[0].line,col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endrule",selectors:n,line:n[0].line,col:n[0].col})),n},_selectors_group:function(){var e=this._tokenStream,t=[],n;n=this._selector();if(n!==null){t.push(n);while(e.match(Tokens.COMMA))this._readWhitespace(),n=this._selector(),n!==null?t.push(n):this._unexpectedToken(e.LT(1))}return t.length?t:null},_selector:function(){var e=this._tokenStream,t=[],n=null,r=null,i=null;n=this._simple_selector_sequence();if(n===null)return null;t.push(n);do{r=this._combinator();if(r!==null)t.push(r),n=this._simple_selector_sequence(),n===null?this._unexpectedToken(e.LT(1)):t.push(n);else{if(!this._readWhitespace())break;i=new Combinator(e.token().value,e.token().startLine,e.token().startCol),r=this._combinator(),n=this._simple_selector_sequence(),n===null?r!==null&&this._unexpectedToken(e.LT(1)):(r!==null?t.push(r):t.push(i),t.push(n))}}while(!0);return new Selector(t,t[0].line,t[0].col)},_simple_selector_sequence:function(){var e=this._tokenStream,t=null,n=[],r="",i=[function(){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo,this._negation],s=0,o=i.length,u=null,a=!1,f,l;f=e.LT(1).startLine,l=e.LT(1).startCol,t=this._type_selector(),t||(t=this._universal()),t!==null&&(r+=t);for(;;){if(e.peek()===Tokens.S)break;while(s<o&&u===null)u=i[s++].call(this);if(u===null){if(r==="")return null;break}s=0,n.push(u),r+=u.toString(),u=null}return r!==""?new SelectorPart(t,n,r,f,l):null},_type_selector:function(){var e=this._tokenStream,t=this._namespace_prefix(),n=this._element_name();return n?(t&&(n.text=t+n.text,n.col-=t.length),n):(t&&(e.unget(),t.length>1&&e.unget()),null)},_class:function(){var e=this._tokenStream,t;return e.match(Tokens.DOT)?(e.mustMatch(Tokens.IDENT),t=e.token(),new SelectorSubPart("."+t.value,"class",t.startLine,t.startCol-1)):null},_element_name:function(){var e=this._tokenStream,t;return e.match(Tokens.IDENT)?(t=e.token(),new SelectorSubPart(t.value,"elementName",t.startLine,t.startCol)):null},_namespace_prefix:function(){var e=this._tokenStream,t="";if(e.LA(1)===Tokens.PIPE||e.LA(2)===Tokens.PIPE)e.match([Tokens.IDENT,Tokens.STAR])&&(t+=e.token().value),e.mustMatch(Tokens.PIPE),t+="|";return t.length?t:null},_universal:function(){var e=this._tokenStream,t="",n;return n=this._namespace_prefix(),n&&(t+=n),e.match(Tokens.STAR)&&(t+="*"),t.length?t:null},_attrib:function(){var e=this._tokenStream,t=null,n,r;return e.match(Tokens.LBRACKET)?(r=e.token(),t=r.value,t+=this._readWhitespace(),n=this._namespace_prefix(),n&&(t+=n),e.mustMatch(Tokens.IDENT),t+=e.token().value,t+=this._readWhitespace(),e.match([Tokens.PREFIXMATCH,Tokens.SUFFIXMATCH,Tokens.SUBSTRINGMATCH,Tokens.EQUALS,Tokens.INCLUDES,Tokens.DASHMATCH])&&(t+=e.token().value,t+=this._readWhitespace(),e.mustMatch([Tokens.IDENT,Tokens.STRING]),t+=e.token().value,t+=this._readWhitespace()),e.mustMatch(Tokens.RBRACKET),new SelectorSubPart(t+"]","attribute",r.startLine,r.startCol)):null},_pseudo:function(){var e=this._tokenStream,t=null,n=":",r,i;return e.match(Tokens.COLON)&&(e.match(Tokens.COLON)&&(n+=":"),e.match(Tokens.IDENT)?(t=e.token().value,r=e.token().startLine,i=e.token().startCol-n.length):e.peek()==Tokens.FUNCTION&&(r=e.LT(1).startLine,i=e.LT(1).startCol-n.length,t=this._functional_pseudo()),t&&(t=new SelectorSubPart(n+t,"pseudo",r,i))),t},_functional_pseudo:function(){var e=this._tokenStream,t=null;return e.match(Tokens.FUNCTION)&&(t=e.token().value,t+=this._readWhitespace(),t+=this._expression(),e.mustMatch(Tokens.RPAREN),t+=")"),t},_expression:function(){var e=this._tokenStream,t="";while(e.match([Tokens.PLUS,Tokens.MINUS,Tokens.DIMENSION,Tokens.NUMBER,Tokens.STRING,Tokens.IDENT,Tokens.LENGTH,Tokens.FREQ,Tokens.ANGLE,Tokens.TIME,Tokens.RESOLUTION]))t+=e.token().value,t+=this._readWhitespace();return t.length?t:null},_negation:function(){var e=this._tokenStream,t,n,r="",i,s=null;return e.match(Tokens.NOT)&&(r=e.token().value,t=e.token().startLine,n=e.token().startCol,r+=this._readWhitespace(),i=this._negation_arg(),r+=i,r+=this._readWhitespace(),e.match(Tokens.RPAREN),r+=e.token().value,s=new SelectorSubPart(r,"not",t,n),s.args.push(i)),s},_negation_arg:function(){var e=this._tokenStream,t=[this._type_selector,this._universal,function(){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo],n=null,r=0,i=t.length,s,o,u,a;o=e.LT(1).startLine,u=e.LT(1).startCol;while(r<i&&n===null)n=t[r].call(this),r++;return n===null&&this._unexpectedToken(e.LT(1)),n.type=="elementName"?a=new SelectorPart(n,[],n.toString(),o,u):a=new SelectorPart(null,[n],n.toString(),o,u),a},_declaration:function(){var e=this._tokenStream,t=null,n=null,r=null,i=null,s=null,o="";t=this._property();if(t!==null){e.mustMatch(Tokens.COLON),this._readWhitespace(),n=this._expr(),(!n||n.length===0)&&this._unexpectedToken(e.LT(1)),r=this._prio(),o=t.toString();if(this.options.starHack&&t.hack=="*"||this.options.underscoreHack&&t.hack=="_")o=t.text;try{this._validateProperty(o,n)}catch(u){s=u}return this.fire({type:"property",property:t,value:n,important:r,line:t.line,col:t.col,invalid:s}),!0}return!1},_prio:function(){var e=this._tokenStream,t=e.match(Tokens.IMPORTANT_SYM);return this._readWhitespace(),t},_expr:function(){var e=this._tokenStream,t=[],n=null,r=null;n=this._term();if(n!==null){t.push(n);do{r=this._operator(),r&&t.push(r),n=this._term();if(n===null)break;t.push(n)}while(!0)}return t.length>0?new PropertyValue(t,t[0].line,t[0].col):null},_term:function(){var e=this._tokenStream,t=null,n=null,r,i,s;return t=this._unary_operator(),t!==null&&(i=e.token().startLine,s=e.token().startCol),e.peek()==Tokens.IE_FUNCTION&&this.options.ieFilters?(n=this._ie_function(),t===null&&(i=e.token().startLine,s=e.token().startCol)):e.match([Tokens.NUMBER,Tokens.PERCENTAGE,Tokens.LENGTH,Tokens.ANGLE,Tokens.TIME,Tokens.FREQ,Tokens.STRING,Tokens.IDENT,Tokens.URI,Tokens.UNICODE_RANGE])?(n=e.token().value,t===null&&(i=e.token().startLine,s=e.token().startCol),this._readWhitespace()):(r=this._hexcolor(),r===null?(t===null&&(i=e.LT(1).startLine,s=e.LT(1).startCol),n===null&&(e.LA(3)==Tokens.EQUALS&&this.options.ieFilters?n=this._ie_function():n=this._function())):(n=r.value,t===null&&(i=r.startLine,s=r.startCol))),n!==null?new PropertyValuePart(t!==null?t+n:n,i,s):null},_function:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match(Tokens.FUNCTION)){t=e.token().value,this._readWhitespace(),n=this._expr(),t+=n;if(this.options.ieFilters&&e.peek()==Tokens.EQUALS)do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_ie_function:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match([Tokens.IE_FUNCTION,Tokens.FUNCTION])){t=e.token().value;do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_hexcolor:function(){var e=this._tokenStream,t=null,n;if(e.match(Tokens.HASH)){t=e.token(),n=t.value;if(!/#[a-f0-9]{3,6}/i.test(n))throw new SyntaxError("Expected a hex color but found '"+n+"' at line "+t.startLine+", col "+t.startCol+".",t.startLine,t.startCol);this._readWhitespace()}return t},_keyframes:function(){var e=this._tokenStream,t,n,r,i="";e.mustMatch(Tokens.KEYFRAMES_SYM),t=e.token(),/^@\-([^\-]+)\-/.test(t.value)&&(i=RegExp.$1),this._readWhitespace(),r=this._keyframe_name(),this._readWhitespace(),e.mustMatch(Tokens.LBRACE),this.fire({type:"startkeyframes",name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),n=e.peek();while(n==Tokens.IDENT||n==Tokens.PERCENTAGE)this._keyframe_rule(),this._readWhitespace(),n=e.peek();this.fire({type:"endkeyframes",name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),e.mustMatch(Tokens.RBRACE)},_keyframe_name:function(){var e=this._tokenStream,t;return e.mustMatch([Tokens.IDENT,Tokens.STRING]),SyntaxUnit.fromToken(e.token())},_keyframe_rule:function(){var e=this._tokenStream,t,n=this._key_list();this.fire({type:"startkeyframerule",keys:n,line:n[0].line,col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endkeyframerule",keys:n,line:n[0].line,col:n[0].col})},_key_list:function(){var e=this._tokenStream,t,n,r=[];r.push(this._key()),this._readWhitespace();while(e.match(Tokens.COMMA))this._readWhitespace(),r.push(this._key()),this._readWhitespace();return r},_key:function(){var e=this._tokenStream,t;if(e.match(Tokens.PERCENTAGE))return SyntaxUnit.fromToken(e.token());if(e.match(Tokens.IDENT)){t=e.token();if(/from|to/i.test(t.value))return SyntaxUnit.fromToken(t);e.unget()}this._unexpectedToken(e.LT(1))},_skipCruft:function(){while(this._tokenStream.match([Tokens.S,Tokens.CDO,Tokens.CDC]));},_readDeclarations:function(e,t){var n=this._tokenStream,r;this._readWhitespace(),e&&n.mustMatch(Tokens.LBRACE),this._readWhitespace();try{for(;;){if(!(n.match(Tokens.SEMICOLON)||t&&this._margin())){if(!this._declaration())break;if(!n.match(Tokens.SEMICOLON))break}this._readWhitespace()}n.mustMatch(Tokens.RBRACE),this._readWhitespace()}catch(i){if(!(i instanceof SyntaxError&&!this.options.strict))throw i;this.fire({type:"error",error:i,message:i.message,line:i.line,col:i.col}),r=n.advance([Tokens.SEMICOLON,Tokens.RBRACE]);if(r==Tokens.SEMICOLON)this._readDeclarations(!1,t);else if(r!=Tokens.RBRACE)throw i}},_readWhitespace:function(){var e=this._tokenStream,t="";while(e.match(Tokens.S))t+=e.token().value;return t},_unexpectedToken:function(e){throw new SyntaxError("Unexpected token '"+e.value+"' at line "+e.startLine+", col "+e.startCol+".",e.startLine,e.startCol)},_verifyEnd:function(){this._tokenStream.LA(1)!=Tokens.EOF&&this._unexpectedToken(this._tokenStream.LT(1))},_validateProperty:function(e,t){Validation.validate(e,t)},parse:function(e){this._tokenStream=new TokenStream(e,Tokens),this._stylesheet()},parseStyleSheet:function(e){return this.parse(e)},parseMediaQuery:function(e){this._tokenStream=new TokenStream(e,Tokens);var t=this._media_query();return this._verifyEnd(),t},parsePropertyValue:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._expr();return this._readWhitespace(),this._verifyEnd(),t},parseRule:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._ruleset();return this._readWhitespace(),this._verifyEnd(),t},parseSelector:function(e){this._tokenStream=new TokenStream(e,Tokens),this._readWhitespace();var t=this._selector();return this._readWhitespace(),this._verifyEnd(),t},parseStyleAttribute:function(e){e+="}",this._tokenStream=new TokenStream(e,Tokens),this._readDeclarations()}};for(t in n)n.hasOwnProperty(t)&&(e[t]=n[t]);return e}();var Properties={"alignment-adjust":"auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | <percentage> | <length>","alignment-baseline":"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",animation:1,"animation-delay":{multi:"<time>",comma:!0},"animation-direction":{multi:"normal | alternate",comma:!0},"animation-duration":{multi:"<time>",comma:!0},"animation-iteration-count":{multi:"<number> | infinite",comma:!0},"animation-name":{multi:"none | <ident>",comma:!0},"animation-play-state":{multi:"running | paused",comma:!0},"animation-timing-function":1,"-moz-animation-delay":{multi:"<time>",comma:!0},"-moz-animation-direction":{multi:"normal | alternate",comma:!0},"-moz-animation-duration":{multi:"<time>",comma:!0},"-moz-animation-iteration-count":{multi:"<number> | infinite",comma:!0},"-moz-animation-name":{multi:"none | <ident>",comma:!0},"-moz-animation-play-state":{multi:"running | paused",comma:!0},"-ms-animation-delay":{multi:"<time>",comma:!0},"-ms-animation-direction":{multi:"normal | alternate",comma:!0},"-ms-animation-duration":{multi:"<time>",comma:!0},"-ms-animation-iteration-count":{multi:"<number> | infinite",comma:!0},"-ms-animation-name":{multi:"none | <ident>",comma:!0},"-ms-animation-play-state":{multi:"running | paused",comma:!0},"-webkit-animation-delay":{multi:"<time>",comma:!0},"-webkit-animation-direction":{multi:"normal | alternate",comma:!0},"-webkit-animation-duration":{multi:"<time>",comma:!0},"-webkit-animation-iteration-count":{multi:"<number> | infinite",comma:!0},"-webkit-animation-name":{multi:"none | <ident>",comma:!0},"-webkit-animation-play-state":{multi:"running | paused",comma:!0},"-o-animation-delay":{multi:"<time>",comma:!0},"-o-animation-direction":{multi:"normal | alternate",comma:!0},"-o-animation-duration":{multi:"<time>",comma:!0},"-o-animation-iteration-count":{multi:"<number> | infinite",comma:!0},"-o-animation-name":{multi:"none | <ident>",comma:!0},"-o-animation-play-state":{multi:"running | paused",comma:!0},appearance:"icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal | inherit",azimuth:function(e){var t="<angle> | leftwards | rightwards | inherit",n="left-side | far-left | left | center-left | center | center-right | right | far-right | right-side",r=!1,i=!1,s;ValidationTypes.isAny(e,t)||(ValidationTypes.isAny(e,"behind")&&(r=!0,i=!0),ValidationTypes.isAny(e,n)&&(i=!0,r||ValidationTypes.isAny(e,"behind")));if(e.hasNext())throw s=e.next(),i?new ValidationError("Expected end of value but found '"+s+"'.",s.line,s.col):new ValidationError("Expected (<'azimuth'>) but found '"+s+"'.",s.line,s.col)},"backface-visibility":"visible | hidden",background:1,"background-attachment":{multi:"<attachment>",comma:!0},"background-clip":{multi:"<box>",comma:!0},"background-color":"<color> | inherit","background-image":{multi:"<bg-image>",comma:!0},"background-origin":{multi:"<box>",comma:!0},"background-position":{multi:"<bg-position>",comma:!0},"background-repeat":{multi:"<repeat-style>"},"background-size":{multi:"<bg-size>",comma:!0},"baseline-shift":"baseline | sub | super | <percentage> | <length>",behavior:1,binding:1,bleed:"<length>","bookmark-label":"<content> | <attr> | <string>","bookmark-level":"none | <integer>","bookmark-state":"open | closed","bookmark-target":"none | <uri> | <attr>",border:"<border-width> || <border-style> || <color>","border-bottom":"<border-width> || <border-style> || <color>","border-bottom-color":"<color>","border-bottom-left-radius":"<x-one-radius>","border-bottom-right-radius":"<x-one-radius>","border-bottom-style":"<border-style>","border-bottom-width":"<border-width>","border-collapse":"collapse | separate | inherit","border-color":{multi:"<color> | inherit",max:4},"border-image":1,"border-image-outset":{multi:"<length> | <number>",max:4},"border-image-repeat":{multi:"stretch | repeat | round",max:2},"border-image-slice":function(e){var t=!1,n="<number> | <percentage>",r=!1,i=0,s=4,o;ValidationTypes.isAny(e,"fill")&&(r=!0,t=!0);while(e.hasNext()&&i<s){t=ValidationTypes.isAny(e,n);if(!t)break;i++}r?t=!0:ValidationTypes.isAny(e,"fill");if(e.hasNext())throw o=e.next(),t?new ValidationError("Expected end of value but found '"+o+"'.",o.line,o.col):new ValidationError("Expected ([<number> | <percentage>]{1,4} && fill?) but found '"+o+"'.",o.line,o.col)},"border-image-source":"<image> | none","border-image-width":{multi:"<length> | <percentage> | <number> | auto",max:4},"border-left":"<border-width> || <border-style> || <color>","border-left-color":"<color> | inherit","border-left-style":"<border-style>","border-left-width":"<border-width>","border-radius":function(e){var t=!1,n="<length> | <percentage>",r=!1,i=!1,s=0,o=8,u;while(e.hasNext()&&s<o){t=ValidationTypes.isAny(e,n);if(!t){if(!(e.peek()=="/"&&s>1&&!r))break;r=!0,o=s+5,e.next()}s++}if(e.hasNext())throw u=e.next(),t?new ValidationError("Expected end of value but found '"+u+"'.",u.line,u.col):new ValidationError("Expected (<'border-radius'>) but found '"+u+"'.",u.line,u.col)},"border-right":"<border-width> || <border-style> || <color>","border-right-color":"<color> | inherit","border-right-style":"<border-style>","border-right-width":"<border-width>","border-spacing":{multi:"<length> | inherit",max:2},"border-style":{multi:"<border-style>",max:4},"border-top":"<border-width> || <border-style> || <color>","border-top-color":"<color> | inherit","border-top-left-radius":"<x-one-radius>","border-top-right-radius":"<x-one-radius>","border-top-style":"<border-style>","border-top-width":"<border-width>","border-width":{multi:"<border-width>",max:4},bottom:"<margin-width> | inherit","box-align":"start | end | center | baseline | stretch","box-decoration-break":"slice |clone","box-direction":"normal | reverse | inherit","box-flex":"<number>","box-flex-group":"<integer>","box-lines":"single | multiple","box-ordinal-group":"<integer>","box-orient":"horizontal | vertical | inline-axis | block-axis | inherit","box-pack":"start | end | center | justify","box-shadow":function(e){var t=!1,n;if(!ValidationTypes.isAny(e,"none"))Validation.multiProperty("<shadow>",e,!0,Infinity);else if(e.hasNext())throw n=e.next(),new ValidationError("Expected end of value but found '"+n+"'.",n.line,n.col)},"box-sizing":"content-box | border-box | inherit","break-after":"auto | always | avoid | left | right | page | column | avoid-page | avoid-column","break-before":"auto | always | avoid | left | right | page | column | avoid-page | avoid-column","break-inside":"auto | avoid | avoid-page | avoid-column","caption-side":"top | bottom | inherit",clear:"none | right | left | both | inherit",clip:1,color:"<color> | inherit","color-profile":1,"column-count":"<integer> | auto","column-fill":"auto | balance","column-gap":"<length> | normal","column-rule":"<border-width> || <border-style> || <color>","column-rule-color":"<color>","column-rule-style":"<border-style>","column-rule-width":"<border-width>","column-span":"none | all","column-width":"<length> | auto",columns:1,content:1,"counter-increment":1,"counter-reset":1,crop:"<shape> | auto",cue:"cue-after | cue-before | inherit","cue-after":1,"cue-before":1,cursor:1,direction:"ltr | rtl | inherit",display:"inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid | none | inherit","dominant-baseline":1,"drop-initial-after-adjust":"central | middle | after-edge | text-after-edge | ideographic | alphabetic | mathematical | <percentage> | <length>","drop-initial-after-align":"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical","drop-initial-before-adjust":"before-edge | text-before-edge | central | middle | hanging | mathematical | <percentage> | <length>","drop-initial-before-align":"caps-height | baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical","drop-initial-size":"auto | line | <length> | <percentage>","drop-initial-value":"initial | <integer>",elevation:"<angle> | below | level | above | higher | lower | inherit","empty-cells":"show | hide | inherit",filter:1,fit:"fill | hidden | meet | slice","fit-position":1,"float":"left | right | none | inherit","float-offset":1,font:1,"font-family":1,"font-size":"<absolute-size> | <relative-size> | <length> | <percentage> | inherit","font-size-adjust":"<number> | none | inherit","font-stretch":"normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit","font-style":"normal | italic | oblique | inherit","font-variant":"normal | small-caps | inherit","font-weight":"normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit","grid-cell-stacking":"columns | rows | layer","grid-column":1,"grid-columns":1,"grid-column-align":"start | end | center | stretch","grid-column-sizing":1,"grid-column-span":"<integer>","grid-flow":"none | rows | columns","grid-layer":"<integer>","grid-row":1,"grid-rows":1,"grid-row-align":"start | end | center | stretch","grid-row-span":"<integer>","grid-row-sizing":1,"hanging-punctuation":1,height:"<margin-width> | inherit","hyphenate-after":"<integer> | auto","hyphenate-before":"<integer> | auto","hyphenate-character":"<string> | auto","hyphenate-lines":"no-limit | <integer>","hyphenate-resource":1,hyphens:"none | manual | auto",icon:1,"image-orientation":"angle | auto","image-rendering":1,"image-resolution":1,"inline-box-align":"initial | last | <integer>",left:"<margin-width> | inherit","letter-spacing":"<length> | normal | inherit","line-height":"<number> | <length> | <percentage> | normal | inherit","line-break":"auto | loose | normal | strict","line-stacking":1,"line-stacking-ruby":"exclude-ruby | include-ruby","line-stacking-shift":"consider-shifts | disregard-shifts","line-stacking-strategy":"inline-line-height | block-line-height | max-height | grid-height","list-style":1,"list-style-image":"<uri> | none | inherit","list-style-position":"inside | outside | inherit","list-style-type":"disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit",margin:{multi:"<margin-width> | inherit",max:4},"margin-bottom":"<margin-width> | inherit","margin-left":"<margin-width> | inherit","margin-right":"<margin-width> | inherit","margin-top":"<margin-width> | inherit",mark:1,"mark-after":1,"mark-before":1,marks:1,"marquee-direction":1,"marquee-play-count":1,"marquee-speed":1,"marquee-style":1,"max-height":"<length> | <percentage> | none | inherit","max-width":"<length> | <percentage> | none | inherit","min-height":"<length> | <percentage> | inherit","min-width":"<length> | <percentage> | inherit","move-to":1,"nav-down":1,"nav-index":1,"nav-left":1,"nav-right":1,"nav-up":1,opacity:"<number> | inherit",orphans:"<integer> | inherit",outline:1,"outline-color":"<color> | invert | inherit","outline-offset":1,"outline-style":"<border-style> | inherit","outline-width":"<border-width> | inherit",overflow:"visible | hidden | scroll | auto | inherit","overflow-style":1,"overflow-x":1,"overflow-y":1,padding:{multi:"<padding-width> | inherit",max:4},"padding-bottom":"<padding-width> | inherit","padding-left":"<padding-width> | inherit","padding-right":"<padding-width> | inherit","padding-top":"<padding-width> | inherit",page:1,"page-break-after":"auto | always | avoid | left | right | inherit","page-break-before":"auto | always | avoid | left | right | inherit","page-break-inside":"auto | avoid | inherit","page-policy":1,pause:1,"pause-after":1,"pause-before":1,perspective:1,"perspective-origin":1,phonemes:1,pitch:1,"pitch-range":1,"play-during":1,"pointer-events":"auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | inherit",position:"static | relative | absolute | fixed | inherit","presentation-level":1,"punctuation-trim":1,quotes:1,"rendering-intent":1,resize:1,rest:1,"rest-after":1,"rest-before":1,richness:1,right:"<margin-width> | inherit",rotation:1,"rotation-point":1,"ruby-align":1,"ruby-overhang":1,"ruby-position":1,"ruby-span":1,size:1,speak:"normal | none | spell-out | inherit","speak-header":"once | always | inherit","speak-numeral":"digits | continuous | inherit","speak-punctuation":"code | none | inherit","speech-rate":1,src:1,stress:1,"string-set":1,"table-layout":"auto | fixed | inherit","tab-size":"<integer> | <length>",target:1,"target-name":1,"target-new":1,"target-position":1,"text-align":"left | right | center | justify | inherit","text-align-last":1,"text-decoration":1,"text-emphasis":1,"text-height":1,"text-indent":"<length> | <percentage> | inherit","text-justify":"auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida","text-outline":1,"text-overflow":1,"text-rendering":"auto | optimizeSpeed | optimizeLegibility | geometricPrecision | inherit","text-shadow":1,"text-transform":"capitalize | uppercase | lowercase | none | inherit","text-wrap":"normal | none | avoid",top:"<margin-width> | inherit",transform:1,"transform-origin":1,"transform-style":1,transition:1,"transition-delay":1,"transition-duration":1,"transition-property":1,"transition-timing-function":1,"unicode-bidi":"normal | embed | bidi-override | inherit","user-modify":"read-only | read-write | write-only | inherit","user-select":"none | text | toggle | element | elements | all | inherit","vertical-align":"<percentage> | <length> | baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit",visibility:"visible | hidden | collapse | inherit","voice-balance":1,"voice-duration":1,"voice-family":1,"voice-pitch":1,"voice-pitch-range":1,"voice-rate":1,"voice-stress":1,"voice-volume":1,volume:1,"white-space":"normal | pre | nowrap | pre-wrap | pre-line | inherit","white-space-collapse":1,widows:"<integer> | inherit",width:"<length> | <percentage> | auto | inherit","word-break":"normal | keep-all | break-all","word-spacing":"<length> | normal | inherit","word-wrap":1,"z-index":"<integer> | auto | inherit",zoom:"<number> | <percentage> | normal"};PropertyName.prototype=new SyntaxUnit,PropertyName.prototype.constructor=PropertyName,PropertyName.prototype.toString=function(){return(this.hack?this.hack:"")+this.text},PropertyValue.prototype=new SyntaxUnit,PropertyValue.prototype.constructor=PropertyValue,PropertyValueIterator.prototype.count=function(){return this._parts.length},PropertyValueIterator.prototype.isFirst=function(){return this._i===0},PropertyValueIterator.prototype.hasNext=function(){return this._i<this._parts.length},PropertyValueIterator.prototype.mark=function(){this._marks.push(this._i)},PropertyValueIterator.prototype.peek=function(e){return this.hasNext()?this._parts[this._i+(e||0)]:null},PropertyValueIterator.prototype.next=function(){return this.hasNext()?this._parts[this._i++]:null},PropertyValueIterator.prototype.previous=function(){return this._i>0?this._parts[--this._i]:null},PropertyValueIterator.prototype.restore=function(){this._marks.length&&(this._i=this._marks.pop())},PropertyValuePart.prototype=new SyntaxUnit,PropertyValuePart.prototype.constructor=PropertyValuePart,PropertyValuePart.fromToken=function(e){return new PropertyValuePart(e.value,e.startLine,e.startCol)};var Pseudos={":first-letter":1,":first-line":1,":before":1,":after":1};Pseudos.ELEMENT=1,Pseudos.CLASS=2,Pseudos.isElement=function(e){return e.indexOf("::")===0||Pseudos[e.toLowerCase()]==Pseudos.ELEMENT},Selector.prototype=new SyntaxUnit,Selector.prototype.constructor=Selector,SelectorPart.prototype=new SyntaxUnit,SelectorPart.prototype.constructor=SelectorPart,SelectorSubPart.prototype=new SyntaxUnit,SelectorSubPart.prototype.constructor=SelectorSubPart,Specificity.prototype={constructor:Specificity,compare:function(e){var t=["a","b","c","d"],n,r;for(n=0,r=t.length;n<r;n++){if(this[t[n]]<e[t[n]])return-1;if(this[t[n]]>e[t[n]])return 1}return 0},valueOf:function(){return this.a*1e3+this.b*100+this.c*10+this.d},toString:function(){return this.a+","+this.b+","+this.c+","+this.d}},Specificity.calculate=function(e){function u(e){var t,n,r,a,f=e.elementName?e.elementName.text:"",l;f&&f.charAt(f.length-1)!="*"&&o++;for(t=0,r=e.modifiers.length;t<r;t++){l=e.modifiers[t];switch(l.type){case"class":case"attribute":s++;break;case"id":i++;break;case"pseudo":Pseudos.isElement(l.text)?o++:s++;break;case"not":for(n=0,a=l.args.length;n<a;n++)u(l.args[n])}}}var t,n,r,i=0,s=0,o=0;for(t=0,n=e.parts.length;t<n;t++)r=e.parts[t],r instanceof SelectorPart&&u(r);return new Specificity(0,i,s,o)};var h=/^[0-9a-fA-F]$/,nonascii=/^[\u0080-\uFFFF]$/,nl=/\n|\r\n|\r|\f/;TokenStream.prototype=mix(new TokenStreamBase,{_getToken:function(e){var t,n=this._reader,r=null,i=n.getLine(),s=n.getCol();t=n.read();while(t){switch(t){case"/":n.peek()=="*"?r=this.commentToken(t,i,s):r=this.charToken(t,i,s);break;case"|":case"~":case"^":case"$":case"*":n.peek()=="="?r=this.comparisonToken(t,i,s):r=this.charToken(t,i,s);break;case'"':case"'":r=this.stringToken(t,i,s);break;case"#":isNameChar(n.peek())?r=this.hashToken(t,i,s):r=this.charToken(t,i,s);break;case".":isDigit(n.peek())?r=this.numberToken(t,i,s):r=this.charToken(t,i,s);break;case"-":n.peek()=="-"?r=this.htmlCommentEndToken(t,i,s):isNameStart(n.peek())?r=this.identOrFunctionToken(t,i,s):r=this.charToken(t,i,s);break;case"!":r=this.importantToken(t,i,s);break;case"@":r=this.atRuleToken(t,i,s);break;case":":r=this.notToken(t,i,s);break;case"<":r=this.htmlCommentStartToken(t,i,s);break;case"U":case"u":if(n.peek()=="+"){r=this.unicodeRangeToken(t,i,s);break};default:isDigit(t)?r=this.numberToken(t,i,s):isWhitespace(t)?r=this.whitespaceToken(t,i,s):isIdentStart(t)?r=this.identOrFunctionToken(t,i,s):r=this.charToken(t,i,s)}break}return!r&&t===null&&(r=this.createToken(Tokens.EOF,null,i,s)),r},createToken:function(e,t,n,r,i){var s=this._reader;return i=i||{},{value:t,type:e,channel:i.channel,hide:i.hide||!1,startLine:n,startCol:r,endLine:s.getLine(),endCol:s.getCol()}},atRuleToken:function(e,t,n){var r=e,i=this._reader,s=Tokens.CHAR,o=!1,u,a;i.mark(),u=this.readName(),r=e+u,s=Tokens.type(r.toLowerCase());if(s==Tokens.CHAR||s==Tokens.UNKNOWN)r.length>1?s=Tokens.UNKNOWN_SYM:(s=Tokens.CHAR,r=e,i.reset());return this.createToken(s,r,t,n)},charToken:function(e,t,n){var r=Tokens.type(e);return r==-1&&(r=Tokens.CHAR),this.createToken(r,e,t,n)},commentToken:function(e,t,n){var r=this._reader,i=this.readComment(e);return this.createToken(Tokens.COMMENT,i,t,n)},comparisonToken:function(e,t,n){var r=this._reader,i=e+r.read(),s=Tokens.type(i)||Tokens.CHAR;return this.createToken(s,i,t,n)},hashToken:function(e,t,n){var r=this._reader,i=this.readName(e);return this.createToken(Tokens.HASH,i,t,n)},htmlCommentStartToken:function(e,t,n){var r=this._reader,i=e;return r.mark(),i+=r.readCount(3),i=="<!--"?this.createToken(Tokens.CDO,i,t,n):(r.reset(),this.charToken(e,t,n))},htmlCommentEndToken:function(e,t,n){var r=this._reader,i=e;return r.mark(),i+=r.readCount(2),i=="-->"?this.createToken(Tokens.CDC,i,t,n):(r.reset(),this.charToken(e,t,n))},identOrFunctionToken:function(e,t,n){var r=this._reader,i=this.readName(e),s=Tokens.IDENT;return r.peek()=="("?(i+=r.read(),i.toLowerCase()=="url("?(s=Tokens.URI,i=this.readURI(i),i.toLowerCase()=="url("&&(s=Tokens.FUNCTION)):s=Tokens.FUNCTION):r.peek()==":"&&i.toLowerCase()=="progid"&&(i+=r.readTo("("),s=Tokens.IE_FUNCTION),this.createToken(s,i,t,n)},importantToken:function(e,t,n){var r=this._reader,i=e,s=Tokens.CHAR,o,u;r.mark(),u=r.read();while(u){if(u=="/"){if(r.peek()!="*")break;o=this.readComment(u);if(o==="")break}else{if(!isWhitespace(u)){if(/i/i.test(u)){o=r.readCount(8),/mportant/i.test(o)&&(i+=u+o,s=Tokens.IMPORTANT_SYM);break}break}i+=u+this.readWhitespace()}u=r.read()}return s==Tokens.CHAR?(r.reset(),this.charToken(e,t,n)):this.createToken(s,i,t,n)},notToken:function(e,t,n){var r=this._reader,i=e;return r.mark(),i+=r.readCount(4),i.toLowerCase()==":not("?this.createToken(Tokens.NOT,i,t,n):(r.reset(),this.charToken(e,t,n))},numberToken:function(e,t,n){var r=this._reader,i=this.readNumber(e),s,o=Tokens.NUMBER,u=r.peek();return isIdentStart(u)?(s=this.readName(r.read()),i+=s,/^em$|^ex$|^px$|^gd$|^rem$|^vw$|^vh$|^vm$|^ch$|^cm$|^mm$|^in$|^pt$|^pc$/i.test(s)?o=Tokens.LENGTH:/^deg|^rad$|^grad$/i.test(s)?o=Tokens.ANGLE:/^ms$|^s$/i.test(s)?o=Tokens.TIME:/^hz$|^khz$/i.test(s)?o=Tokens.FREQ:/^dpi$|^dpcm$/i.test(s)?o=Tokens.RESOLUTION:o=Tokens.DIMENSION):u=="%"&&(i+=r.read(),o=Tokens.PERCENTAGE),this.createToken(o,i,t,n)},stringToken:function(e,t,n){var r=e,i=e,s=this._reader,o=e,u=Tokens.STRING,a=s.read();while(a){i+=a;if(a==r&&o!="\\")break;if(isNewLine(s.peek())&&a!="\\"){u=Tokens.INVALID;break}o=a,a=s.read()}return a===null&&(u=Tokens.INVALID),this.createToken(u,i,t,n)},unicodeRangeToken:function(e,t,n){var r=this._reader,i=e,s,o=Tokens.CHAR;return r.peek()=="+"&&(r.mark(),i+=r.read(),i+=this.readUnicodeRangePart(!0),i.length==2?r.reset():(o=Tokens.UNICODE_RANGE,i.indexOf("?")==-1&&r.peek()=="-"&&(r.mark(),s=r.read(),s+=this.readUnicodeRangePart(!1),s.length==1?r.reset():i+=s))),this.createToken(o,i,t,n)},whitespaceToken:function(e,t,n){var r=this._reader,i=e+this.readWhitespace();return this.createToken(Tokens.S,i,t,n)},readUnicodeRangePart:function(e){var t=this._reader,n="",r=t.peek();while(isHexDigit(r)&&n.length<6)t.read(),n+=r,r=t.peek();if(e)while(r=="?"&&n.length<6)t.read(),n+=r,r=t.peek();return n},readWhitespace:function(){var e=this._reader,t="",n=e.peek();while(isWhitespace(n))e.read(),t+=n,n=e.peek();return t},readNumber:function(e){var t=this._reader,n=e,r=e==".",i=t.peek();while(i){if(isDigit(i))n+=t.read();else{if(i!=".")break;if(r)break;r=!0,n+=t.read()}i=t.peek()}return n},readString:function(){var e=this._reader,t=e.read(),n=t,r=t,i=e.peek();while(i){i=e.read(),n+=i;if(i==t&&r!="\\")break;if(isNewLine(e.peek())&&i!="\\"){n="";break}r=i,i=e.peek()}return i===null&&(n=""),n},readURI:function(e){var t=this._reader,n=e,r="",i=t.peek();t.mark();while(i&&isWhitespace(i))t.read(),i=t.peek();i=="'"||i=='"'?r=this.readString():r=this.readURL(),i=t.peek();while(i&&isWhitespace(i))t.read(),i=t.peek();return r===""||i!=")"?(n=e,t.reset()):n+=r+t.read(),n},readURL:function(){var e=this._reader,t="",n=e.peek();while(/^[!#$%&\\*-~]$/.test(n))t+=e.read(),n=e.peek();return t},readName:function(e){var t=this._reader,n=e||"",r=t.peek();for(;;)if(r=="\\")n+=this.readEscape(t.read()),r=t.peek();else{if(!r||!isNameChar(r))break;n+=t.read(),r=t.peek()}return n},readEscape:function(e){var t=this._reader,n=e||"",r=0,i=t.peek();if(isHexDigit(i))do n+=t.read(),i=t.peek();while(i&&isHexDigit(i)&&++r<6);return n.length==3&&/\s/.test(i)||n.length==7||n.length==1?t.read():i="",n+i},readComment:function(e){var t=this._reader,n=e||"",r=t.read();if(r=="*"){while(r){n+=r;if(n.length>2&&r=="*"&&t.peek()=="/"){n+=t.read();break}r=t.read()}return n}return""}});var Tokens=[{name:"CDO"},{name:"CDC"},{name:"S",whitespace:!0},{name:"COMMENT",comment:!0,hide:!0,channel:"comment"},{name:"INCLUDES",text:"~="},{name:"DASHMATCH",text:"|="},{name:"PREFIXMATCH",text:"^="},{name:"SUFFIXMATCH",text:"$="},{name:"SUBSTRINGMATCH",text:"*="},{name:"STRING"},{name:"IDENT"},{name:"HASH"},{name:"IMPORT_SYM",text:"@import"},{name:"PAGE_SYM",text:"@page"},{name:"MEDIA_SYM",text:"@media"},{name:"FONT_FACE_SYM",text:"@font-face"},{name:"CHARSET_SYM",text:"@charset"},{name:"NAMESPACE_SYM",text:"@namespace"},{name:"UNKNOWN_SYM"},{name:"KEYFRAMES_SYM",text:["@keyframes","@-webkit-keyframes","@-moz-keyframes","@-o-keyframes"]},{name:"IMPORTANT_SYM"},{name:"LENGTH"},{name:"ANGLE"},{name:"TIME"},{name:"FREQ"},{name:"DIMENSION"},{name:"PERCENTAGE"},{name:"NUMBER"},{name:"URI"},{name:"FUNCTION"},{name:"UNICODE_RANGE"},{name:"INVALID"},{name:"PLUS",text:"+"},{name:"GREATER",text:">"},{name:"COMMA",text:","},{name:"TILDE",text:"~"},{name:"NOT"},{name:"TOPLEFTCORNER_SYM",text:"@top-left-corner"},{name:"TOPLEFT_SYM",text:"@top-left"},{name:"TOPCENTER_SYM",text:"@top-center"},{name:"TOPRIGHT_SYM",text:"@top-right"},{name:"TOPRIGHTCORNER_SYM",text:"@top-right-corner"},{name:"BOTTOMLEFTCORNER_SYM",text:"@bottom-left-corner"},{name:"BOTTOMLEFT_SYM",text:"@bottom-left"},{name:"BOTTOMCENTER_SYM",text:"@bottom-center"},{name:"BOTTOMRIGHT_SYM",text:"@bottom-right"},{name:"BOTTOMRIGHTCORNER_SYM",text:"@bottom-right-corner"},{name:"LEFTTOP_SYM",text:"@left-top"},{name:"LEFTMIDDLE_SYM",text:"@left-middle"},{name:"LEFTBOTTOM_SYM",text:"@left-bottom"},{name:"RIGHTTOP_SYM",text:"@right-top"},{name:"RIGHTMIDDLE_SYM",text:"@right-middle"},{name:"RIGHTBOTTOM_SYM",text:"@right-bottom"},{name:"RESOLUTION",state:"media"},{name:"IE_FUNCTION"},{name:"CHAR"},{name:"PIPE",text:"|"},{name:"SLASH",text:"/"},{name:"MINUS",text:"-"},{name:"STAR",text:"*"},{name:"LBRACE",text:"{"},{name:"RBRACE",text:"}"},{name:"LBRACKET",text:"["},{name:"RBRACKET",text:"]"},{name:"EQUALS",text:"="},{name:"COLON",text:":"},{name:"SEMICOLON",text:";"},{name:"LPAREN",text:"("},{name:"RPAREN",text:")"},{name:"DOT",text:"."}];(function(){var e=[],t={};Tokens.UNKNOWN=-1,Tokens.unshift({name:"EOF"});for(var n=0,r=Tokens.length;n<r;n++){e.push(Tokens[n].name),Tokens[Tokens[n].name]=n;if(Tokens[n].text)if(Tokens[n].text instanceof Array)for(var i=0;i<Tokens[n].text.length;i++)t[Tokens[n].text[i]]=n;else t[Tokens[n].text]=n}Tokens.name=function(t){return e[t]},Tokens.type=function(e){return t[e]||-1}})();var Validation={validate:function(e,t){var n=e.toString().toLowerCase(),r=t.parts,i=new PropertyValueIterator(t),s=Properties[n],o,u,a,f,l,c,h,p,d,v,m;if(!s){if(n.indexOf("-")!==0)throw new ValidationError("Unknown property '"+e+"'.",e.line,e.col)}else typeof s!="number"&&(typeof s=="string"?s.indexOf("||")>-1?this.groupProperty(s,i):this.singleProperty(s,i,1):s.multi?this.multiProperty(s.multi,i,s.comma,s.max||Infinity):typeof s=="function"&&s(i))},singleProperty:function(e,t,n,r){var i=!1,s=t.value,o=0,u;while(t.hasNext()&&o<n){i=ValidationTypes.isAny(t,e);if(!i)break;o++}if(!i)throw t.hasNext()&&!t.isFirst()?(u=t.peek(),new ValidationError("Expected end of value but found '"+u+"'.",u.line,u.col)):new ValidationError("Expected ("+e+") but found '"+s+"'.",s.line,s.col);if(t.hasNext())throw u=t.next(),new ValidationError("Expected end of value but found '"+u+"'.",u.line,u.col)},multiProperty:function(e,t,n,r){var i=!1,s=t.value,o=0,u=!1,a;while(t.hasNext()&&!i&&o<r){if(!ValidationTypes.isAny(t,e))break;o++;if(!t.hasNext())i=!0;else if(n){if(t.peek()!=",")break;a=t.next()}}if(!i)throw t.hasNext()&&!t.isFirst()?(a=t.peek(),new ValidationError("Expected end of value but found '"+a+"'.",a.line,a.col)):(a=t.previous(),n&&a==","?new ValidationError("Expected end of value but found '"+a+"'.",a.line,a.col):new ValidationError("Expected ("+e+") but found '"+s+"'.",s.line,s.col));if(t.hasNext())throw a=t.next(),new ValidationError("Expected end of value but found '"+a+"'.",a.line,a.col)},groupProperty:function(e,t,n){var r=!1,i=t.value,s=e.split("||").length,o={count:0},u=!1,a,f;while(t.hasNext()&&!r){a=ValidationTypes.isAnyOfGroup(t,e);if(!a)break;if(o[a])break;o[a]=1,o.count++,u=!0;if(o.count==s||!t.hasNext())r=!0}if(!r)throw u&&t.hasNext()?(f=t.peek(),new ValidationError("Expected end of value but found '"+f+"'.",f.line,f.col)):new ValidationError("Expected ("+e+") but found '"+i+"'.",i.line,i.col);if(t.hasNext())throw f=t.next(),new ValidationError("Expected end of value but found '"+f+"'.",f.line,f.col)}};ValidationError.prototype=new Error;var ValidationTypes={isLiteral:function(e,t){var n=e.text.toString().toLowerCase(),r=t.split(" | "),i,s,o=!1;for(i=0,s=r.length;i<s&&!o;i++)n==r[i].toLowerCase()&&(o=!0);return o},isSimple:function(e){return!!this.simple[e]},isComplex:function(e){return!!this.complex[e]},isAny:function(e,t){var n=t.split(" | "),r,i,s=!1;for(r=0,i=n.length;r<i&&!s&&e.hasNext();r++)s=this.isType(e,n[r]);return s},isAnyOfGroup:function(e,t){var n=t.split(" || "),r,i,s=!1;for(r=0,i=n.length;r<i&&!s;r++)s=this.isType(e,n[r]);return s?n[r-1]:!1},isType:function(e,t){var n=e.peek(),r=!1;return t.charAt(0)!="<"?(r=this.isLiteral(n,t),r&&e.next()):this.simple[t]?(r=this.simple[t](n),r&&e.next()):r=this.complex[t](e),r},simple:{"<absolute-size>":function(e){return ValidationTypes.isLiteral(e,"xx-small | x-small | small | medium | large | x-large | xx-large")},"<attachment>":function(e){return ValidationTypes.isLiteral(e,"scroll | fixed | local")},"<attr>":function(e){return e.type=="function"&&e.name=="attr"},"<bg-image>":function(e){return this["<image>"](e)||this["<gradient>"](e)||e=="none"},"<gradient>":function(e){return e.type=="function"&&/^(?:\-(?:ms|moz|o|webkit)\-)?(?:repeating\-)?(?:radial\-|linear\-)?gradient/i.test(e)},"<box>":function(e){return ValidationTypes.isLiteral(e,"padding-box | border-box | content-box")},"<content>":function(e){return e.type=="function"&&e.name=="content"},"<relative-size>":function(e){return ValidationTypes.isLiteral(e,"smaller | larger")},"<ident>":function(e){return e.type=="identifier"},"<length>":function(e){return e.type=="length"||e.type=="number"||e.type=="integer"||e=="0"},"<color>":function(e){return e.type=="color"||e=="transparent"},"<number>":function(e){return e.type=="number"||this["<integer>"](e)},"<integer>":function(e){return e.type=="integer"},"<line>":function(e){return e.type=="integer"},"<angle>":function(e){return e.type=="angle"},"<uri>":function(e){return e.type=="uri"},"<image>":function(e){return this["<uri>"](e)},"<percentage>":function(e){return e.type=="percentage"||e=="0"},"<border-width>":function(e){return this["<length>"](e)||ValidationTypes.isLiteral(e,"thin | medium | thick")},"<border-style>":function(e){return ValidationTypes.isLiteral(e,"none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset")},"<margin-width>":function(e){return this["<length>"](e)||this["<percentage>"](e)||ValidationTypes.isLiteral(e,"auto")},"<padding-width>":function(e){return this["<length>"](e)||this["<percentage>"](e)},"<shape>":function(e){return e.type=="function"&&(e.name=="rect"||e.name=="inset-rect")},"<time>":function(e){return e.type=="time"}},complex:{"<bg-position>":function(e){var t=this,n=!1,r="<percentage> | <length>",i="left | center | right",s="top | center | bottom",o,u,a;return ValidationTypes.isAny(e,"top | bottom")?n=!0:ValidationTypes.isAny(e,r)?e.hasNext()&&(n=ValidationTypes.isAny(e,r+" | "+s)):ValidationTypes.isAny(e,i)&&e.hasNext()&&(ValidationTypes.isAny(e,s)?(n=!0,ValidationTypes.isAny(e,r)):ValidationTypes.isAny(e,r)&&(ValidationTypes.isAny(e,s)&&ValidationTypes.isAny(e,r),n=!0)),n},"<bg-size>":function(e){var t=this,n=!1,r="<percentage> | <length> | auto",i,s,o;return ValidationTypes.isAny(e,"cover | contain")?n=!0:ValidationTypes.isAny(e,r)&&(n=!0,ValidationTypes.isAny(e,r)),n},"<repeat-style>":function(e){var t=!1,n="repeat | space | round | no-repeat",r;return e.hasNext()&&(r=e.next(),ValidationTypes.isLiteral(r,"repeat-x | repeat-y")?t=!0:ValidationTypes.isLiteral(r,n)&&(t=!0,e.hasNext()&&ValidationTypes.isLiteral(e.peek(),n)&&e.next())),t},"<shadow>":function(e){var t=!1,n=0,r=!1,i=!1,s;if(e.hasNext()){ValidationTypes.isAny(e,"inset")&&(r=!0),ValidationTypes.isAny(e,"<color>")&&(i=!0);while(ValidationTypes.isAny(e,"<length>")&&n<4)n++;e.hasNext()&&(i||ValidationTypes.isAny(e,"<color>"),r||ValidationTypes.isAny(e,"inset")),t=n>=2&&n<=4}return t},"<x-one-radius>":function(e){var t=!1,n=0,r="<length> | <percentage>",i;return ValidationTypes.isAny(e,r)&&(t=!0,ValidationTypes.isAny(e,r)),t}}};parserlib.css={Colors:Colors,Combinator:Combinator,Parser:Parser,PropertyName:PropertyName,PropertyValue:PropertyValue,PropertyValuePart:PropertyValuePart,MediaFeature:MediaFeature,MediaQuery:MediaQuery,Selector:Selector,SelectorPart:SelectorPart,SelectorSubPart:SelectorSubPart,Specificity:Specificity,TokenStream:TokenStream,Tokens:Tokens,ValidationError:ValidationError}}();var CSSLint=function(){var e=[],t=[],n=new parserlib.util.EventTarget;return n.version="0.9.9",n.addRule=function(t){e.push(t),e[t.id]=t},n.clearRules=function(){e=[]},n.getRules=function(){return[].concat(e).sort(function(e,t){return e.id>t.id?1:0})},n.getRuleset=function(){var t={},n=0,r=e.length;while(n<r)t[e[n++].id]=1;return t},n.addFormatter=function(e){t[e.id]=e},n.getFormatter=function(e){return t[e]},n.format=function(e,t,n,r){var i=this.getFormatter(n),s=null;return i&&(s=i.startFormat(),s+=i.formatResults(e,t,r||{}),s+=i.endFormat()),s},n.hasFormat=function(e){return t.hasOwnProperty(e)},n.verify=function(t,n){var r=0,i=e.length,s,o,u,a=new parserlib.css.Parser({starHack:!0,ieFilters:!0,underscoreHack:!0,strict:!1});o=t.replace(/\n\r?/g,"$split$").split("$split$"),n||(n=this.getRuleset()),s=new Reporter(o,n),n.errors=2;for(r in n)n.hasOwnProperty(r)&&e[r]&&e[r].init(a,s);try{a.parse(t)}catch(f){s.error("Fatal error, cannot continue: "+f.message,f.line,f.col,{})}return u={messages:s.messages,stats:s.stats},u.messages.sort(function(e,t){return e.rollup&&!t.rollup?1:!e.rollup&&t.rollup?-1:e.line-t.line}),u},n}();Reporter.prototype={constructor:Reporter,error:function(e,t,n,r){this.messages.push({type:"error",line:t,col:n,message:e,evidence:this.lines[t-1],rule:r||{}})},warn:function(e,t,n,r){this.report(e,t,n,r)},report:function(e,t,n,r){this.messages.push({type:this.ruleset[r.id]==2?"error":"warning",line:t,col:n,message:e,evidence:this.lines[t-1],rule:r})},info:function(e,t,n,r){this.messages.push({type:"info",line:t,col:n,message:e,evidence:this.lines[t-1],rule:r})},rollupError:function(e,t){this.messages.push({type:"error",rollup:!0,message:e,rule:t})},rollupWarn:function(e,t){this.messages.push({type:"warning",rollup:!0,message:e,rule:t})},stat:function(e,t){this.stats[e]=t}},CSSLint._Reporter=Reporter,CSSLint.Util={mix:function(e,t){var n;for(n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return n},indexOf:function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},forEach:function(e,t){if(e.forEach)return e.forEach(t);for(var n=0,r=e.length;n<r;n++)t(e[n],n,e)}},CSSLint.addRule({id:"adjoining-classes",name:"Disallow adjoining classes",desc:"Don't use adjoining classes.",browsers:"IE6",init:function(e,t){var n=this;e.addListener("startrule",function(r){var i=r.selectors,s,o,u,a,f,l,c;for(f=0;f<i.length;f++){s=i[f];for(l=0;l<s.parts.length;l++){o=s.parts[l];if(o.type==e.SELECTOR_PART_TYPE){a=0;for(c=0;c<o.modifiers.length;c++)u=o.modifiers[c],u.type=="class"&&a++,a>1&&t.report("Don't use adjoining classes.",o.line,o.col,n)}}}})}}),CSSLint.addRule({id:"box-model",name:"Beware of broken box size",desc:"Don't use width or height when using padding or border.",browsers:"All",init:function(e,t){function u(){s={},o=!1}function a(){var e,u;if(!o){if(s.height)for(e in i)i.hasOwnProperty(e)&&s[e]&&(u=s[e].value,(e!="padding"||u.parts.length!==2||u.parts[0].value!==0)&&t.report("Using height with "+e+" can sometimes make elements larger than you expect.",s[e].line,s[e].col,n));if(s.width)for(e in r)r.hasOwnProperty(e)&&s[e]&&(u=s[e].value,(e!="padding"||u.parts.length!==2||u.parts[1].value!==0)&&t.report("Using width with "+e+" can sometimes make elements larger than you expect.",s[e].line,s[e].col,n))}}var n=this,r={border:1,"border-left":1,"border-right":1,padding:1,"padding-left":1,"padding-right":1},i={border:1,"border-bottom":1,"border-top":1,padding:1,"padding-bottom":1,"padding-top":1},s,o=!1;e.addListener("startrule",u),e.addListener("startfontface",u),e.addListener("startpage",u),e.addListener("startpagemargin",u),e.addListener("startkeyframerule",u),e.addListener("property",function(e){var t=e.property.text.toLowerCase();i[t]||r[t]?!/^0\S*$/.test(e.value)&&(t!="border"||e.value!="none")&&(s[t]={line:e.property.line,col:e.property.col,value:e.value}):/^(width|height)/i.test(t)&&/^(length|percentage)/.test(e.value.parts[0].type)?s[t]=1:t=="box-sizing"&&(o=!0)}),e.addListener("endrule",a),e.addListener("endfontface",a),e.addListener("endpage",a),e.addListener("endpagemargin",a),e.addListener("endkeyframerule",a)}}),CSSLint.addRule({id:"box-sizing",name:"Disallow use of box-sizing",desc:"The box-sizing properties isn't supported in IE6 and IE7.",browsers:"IE6, IE7",tags:["Compatibility"],init:function(e,t){var n=this;e.addListener("property",function(e){var r=e.property.text.toLowerCase();r=="box-sizing"&&t.report("The box-sizing property isn't supported in IE6 and IE7.",e.line,e.col,n)})}}),CSSLint.addRule({id:"compatible-vendor-prefixes",name:"Require compatible vendor prefixes",desc:"Include all compatible vendor prefixes to reach a wider range of users.",browsers:"All",init:function(e,t){var n=this,r,i,s,o,u,a,f,l=!1,c=Array.prototype.push,h=[];r={animation:"webkit moz","animation-delay":"webkit moz","animation-direction":"webkit moz","animation-duration":"webkit moz","animation-fill-mode":"webkit moz","animation-iteration-count":"webkit moz","animation-name":"webkit moz","animation-play-state":"webkit moz","animation-timing-function":"webkit moz",appearance:"webkit moz","border-end":"webkit moz","border-end-color":"webkit moz","border-end-style":"webkit moz","border-end-width":"webkit moz","border-image":"webkit moz o","border-radius":"webkit moz","border-start":"webkit moz","border-start-color":"webkit moz","border-start-style":"webkit moz","border-start-width":"webkit moz","box-align":"webkit moz ms","box-direction":"webkit moz ms","box-flex":"webkit moz ms","box-lines":"webkit ms","box-ordinal-group":"webkit moz ms","box-orient":"webkit moz ms","box-pack":"webkit moz ms","box-sizing":"webkit moz","box-shadow":"webkit moz","column-count":"webkit moz ms","column-gap":"webkit moz ms","column-rule":"webkit moz ms","column-rule-color":"webkit moz ms","column-rule-style":"webkit moz ms","column-rule-width":"webkit moz ms","column-width":"webkit moz ms",hyphens:"epub moz","line-break":"webkit ms","margin-end":"webkit moz","margin-start":"webkit moz","marquee-speed":"webkit wap","marquee-style":"webkit wap","padding-end":"webkit moz","padding-start":"webkit moz","tab-size":"moz o","text-size-adjust":"webkit ms",transform:"webkit moz ms o","transform-origin":"webkit moz ms o",transition:"webkit moz o","transition-delay":"webkit moz o","transition-duration":"webkit moz o","transition-property":"webkit moz o","transition-timing-function":"webkit moz o","user-modify":"webkit moz","user-select":"webkit moz ms","word-break":"epub ms","writing-mode":"epub ms"};for(s in r)if(r.hasOwnProperty(s)){o=[],u=r[s].split(" ");for(a=0,f=u.length;a<f;a++)o.push("-"+u[a]+"-"+s);r[s]=o,c.apply(h,o)}e.addListener("startrule",function(){i=[]}),e.addListener("startkeyframes",function(e){l=e.prefix||!0}),e.addListener("endkeyframes",function(e){l=!1}),e.addListener("property",function(e){var t=e.property;CSSLint.Util.indexOf(h,t.text)>-1&&(!l||typeof l!="string"||t.text.indexOf("-"+l+"-")!==0)&&i.push(t)}),e.addListener("endrule",function(e){if(!i.length)return;var s={},o,u,a,f,l,c,h,p,d,v;for(o=0,u=i.length;o<u;o++){a=i[o];for(f in r)r.hasOwnProperty(f)&&(l=r[f],CSSLint.Util.indexOf(l,a.text)>-1&&(s[f]||(s[f]={full:l.slice(0),actual:[],actualNodes:[]}),CSSLint.Util.indexOf(s[f].actual,a.text)===-1&&(s[f].actual.push(a.text),s[f].actualNodes.push(a))))}for(f in s)if(s.hasOwnProperty(f)){c=s[f],h=c.full,p=c.actual;if(h.length>p.length)for(o=0,u=h.length;o<u;o++)d=h[o],CSSLint.Util.indexOf(p,d)===-1&&(v=p.length===1?p[0]:p.length==2?p.join(" and "):p.join(", "),t.report("The property "+d+" is compatible with "+v+" and should be included as well.",c.actualNodes[0].line,c.actualNodes[0].col,n))}})}}),CSSLint.addRule({id:"display-property-grouping",name:"Require properties appropriate for display",desc:"Certain properties shouldn't be used with certain display property values.",browsers:"All",init:function(e,t){function s(e,s,o){i[e]&&(typeof r[e]!="string"||i[e].value.toLowerCase()!=r[e])&&t.report(o||e+" can't be used with display: "+s+".",i[e].line,i[e].col,n)}function o(){i={}}function u(){var e=i.display?i.display.value:null;if(e)switch(e){case"inline":s("height",e),s("width",e),s("margin",e),s("margin-top",e),s("margin-bottom",e),s("float",e,"display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).");break;case"block":s("vertical-align",e);break;case"inline-block":s("float",e);break;default:e.indexOf("table-")===0&&(s("margin",e),s("margin-left",e),s("margin-right",e),s("margin-top",e),s("margin-bottom",e),s("float",e))}}var n=this,r={display:1,"float":"none",height:1,width:1,margin:1,"margin-left":1,"margin-right":1,"margin-bottom":1,"margin-top":1,padding:1,"padding-left":1,"padding-right":1,"padding-bottom":1,"padding-top":1,"vertical-align":1},i;e.addListener("startrule",o),e.addListener("startfontface",o),e.addListener("startkeyframerule",o),e.addListener("startpagemargin",o),e.addListener("startpage",o),e.addListener("property",function(e){var t=e.property.text.toLowerCase();r[t]&&(i[t]={value:e.value.text,line:e.property.line,col:e.property.col})}),e.addListener("endrule",u),e.addListener("endfontface",u),e.addListener("endkeyframerule",u),e.addListener("endpagemargin",u),e.addListener("endpage",u)}}),CSSLint.addRule({id:"duplicate-background-images",name:"Disallow duplicate background images",desc:"Every background-image should be unique. Use a common class for e.g. sprites.",browsers:"All",init:function(e,t){var n=this,r={};e.addListener("property",function(e){var i=e.property.text,s=e.value,o,u;if(i.match(/background/i))for(o=0,u=s.parts.length;o<u;o++)s.parts[o].type=="uri"&&(typeof r[s.parts[o].uri]=="undefined"?r[s.parts[o].uri]=e:t.report("Background image '"+s.parts[o].uri+"' was used multiple times, first declared at line "+r[s.parts[o].uri].line+", col "+r[s.parts[o].uri].col+".",e.line,e.col,n))})}}),CSSLint.addRule({id:"duplicate-properties",name:"Disallow duplicate properties",desc:"Duplicate properties must appear one after the other.",browsers:"All",init:function(e,t){function s(e){r={}}var n=this,r,i;e.addListener("startrule",s),e.addListener("startfontface",s),e.addListener("startpage",s),e.addListener("startpagemargin",s),e.addListener("startkeyframerule",s),e.addListener("property",function(e){var s=e.property,o=s.text.toLowerCase();r[o]&&(i!=o||r[o]==e.value.text)&&t.report("Duplicate property '"+e.property+"' found.",e.line,e.col,n),r[o]=e.value.text,i=o})}}),CSSLint.addRule({id:"empty-rules",name:"Disallow empty rules",desc:"Rules without any properties specified should be removed.",browsers:"All",init:function(e,t){var n=this,r=0;e.addListener("startrule",function(){r=0}),e.addListener("property",function(){r++}),e.addListener("endrule",function(e){var i=e.selectors;r===0&&t.report("Rule is empty.",i[0].line,i[0].col,n)})}}),CSSLint.addRule({id:"errors",name:"Parsing Errors",desc:"This rule looks for recoverable syntax errors.",browsers:"All",init:function(e,t){var n=this;e.addListener("error",function(e){t.error(e.message,e.line,e.col,n)})}}),CSSLint.addRule({id:"fallback-colors",name:"Require fallback colors",desc:"For older browsers that don't support RGBA, HSL, or HSLA, provide a fallback color.",browsers:"IE6,IE7,IE8",init:function(e,t){function o(e){s={},r=null}var n=this,r,i={color:1,background:1,"background-color":1},s;e.addListener("startrule",o),e.addListener("startfontface",o),e.addListener("startpage",o),e.addListener("startpagemargin",o),e.addListener("startkeyframerule",o),e.addListener("property",function(e){var s=e.property,o=s.text.toLowerCase(),u=e.value.parts,a=0,f="",l=u.length;if(i[o])while(a<l)u[a].type=="color"&&("alpha"in u[a]||"hue"in u[a]?(/([^\)]+)\(/.test(u[a])&&(f=RegExp.$1.toUpperCase()),(!r||r.property.text.toLowerCase()!=o||r.colorType!="compat")&&t.report("Fallback "+o+" (hex or RGB) should precede "+f+" "+o+".",e.line,e.col,n)):e.colorType="compat"),a++;r=e})}}),CSSLint.addRule({id:"floats",name:"Disallow too many floats",desc:"This rule tests if the float property is used too many times",browsers:"All",init:function(e,t){var n=this,r=0;e.addListener("property",function(e){e.property.text.toLowerCase()=="float"&&e.value.text.toLowerCase()!="none"&&r++}),e.addListener("endstylesheet",function(){t.stat("floats",r),r>=10&&t.rollupWarn("Too many floats ("+r+"), you're probably using them for layout. Consider using a grid system instead.",n)})}}),CSSLint.addRule({id:"font-faces",name:"Don't use too many web fonts",desc:"Too many different web fonts in the same stylesheet.",browsers:"All",init:function(e,t){var n=this,r=0;e.addListener("startfontface",function(){r++}),e.addListener("endstylesheet",function(){r>5&&t.rollupWarn("Too many @font-face declarations ("+r+").",n)})}}),CSSLint.addRule({id:"font-sizes",name:"Disallow too many font sizes",desc:"Checks the number of font-size declarations.",browsers:"All",init:function(e,t){var n=this,r=0;e.addListener("property",function(e){e.property=="font-size"&&r++}),e.addListener("endstylesheet",function(){t.stat("font-sizes",r),r>=10&&t.rollupWarn("Too many font-size declarations ("+r+"), abstraction needed.",n)})}}),CSSLint.addRule({id:"gradients",name:"Require all gradient definitions",desc:"When using a vendor-prefixed gradient, make sure to use them all.",browsers:"All",init:function(e,t){var n=this,r;e.addListener("startrule",function(){r={moz:0,webkit:0,oldWebkit:0,ms:0,o:0}}),e.addListener("property",function(e){/\-(moz|ms|o|webkit)(?:\-(?:linear|radial))\-gradient/i.test(e.value)?r[RegExp.$1]=1:/\-webkit\-gradient/i.test(e.value)&&(r.oldWebkit=1)}),e.addListener("endrule",function(e){var i=[];r.moz||i.push("Firefox 3.6+"),r.webkit||i.push("Webkit (Safari 5+, Chrome)"),r.oldWebkit||i.push("Old Webkit (Safari 4+, Chrome)"),r.ms||i.push("Internet Explorer 10+"),r.o||i.push("Opera 11.1+"),i.length&&i.length<5&&t.report("Missing vendor-prefixed CSS gradients for "+i.join(", ")+".",e.selectors[0].line,e.selectors[0].col,n)})}}),CSSLint.addRule({id:"ids",name:"Disallow IDs in selectors",desc:"Selectors should not contain IDs.",browsers:"All",init:function(e,t){var n=this;e.addListener("startrule",function(r){var i=r.selectors,s,o,u,a,f,l,c;for(f=0;f<i.length;f++){s=i[f],a=0;for(l=0;l<s.parts.length;l++){o=s.parts[l];if(o.type==e.SELECTOR_PART_TYPE)for(c=0;c<o.modifiers.length;c++)u=o.modifiers[c],u.type=="id"&&a++}a==1?t.report("Don't use IDs in selectors.",s.line,s.col,n):a>1&&t.report(a+" IDs in the selector, really?",s.line,s.col,n)}})}}),CSSLint.addRule({id:"import",name:"Disallow @import",desc:"Don't use @import, use <link> instead.",browsers:"All",init:function(e,t){var n=this;e.addListener("import",function(e){t.report("@import prevents parallel downloads, use <link> instead.",e.line,e.col,n)})}}),CSSLint.addRule({id:"important",name:"Disallow !important",desc:"Be careful when using !important declaration",browsers:"All",init:function(e,t){var n=this,r=0;e.addListener("property",function(e){e.important===!0&&(r++,t.report("Use of !important",e.line,e.col,n))}),e.addListener("endstylesheet",function(){t.stat("important",r),r>=10&&t.rollupWarn("Too many !important declarations ("+r+"), try to use less than 10 to avoid specificity issues.",n)})}}),CSSLint.addRule({id:"known-properties",name:"Require use of known properties",desc:"Properties should be known (listed in CSS3 specification) or be a vendor-prefixed property.",browsers:"All",init:function(e,t){var n=this;e.addListener("property",function(e){var r=e.property.text.toLowerCase();e.invalid&&t.report(e.invalid.message,e.line,e.col,n)})}}),CSSLint.addRule({id:"outline-none",name:"Disallow outline: none",desc:"Use of outline: none or outline: 0 should be limited to :focus rules.",browsers:"All",tags:["Accessibility"],init:function(e,t){function i(e){e.selectors?r={line:e.line,col:e.col,selectors:e.selectors,propCount:0,outline:!1}:r=null}function s(e){r&&r.outline&&(r.selectors.toString().toLowerCase().indexOf(":focus")==-1?t.report("Outlines should only be modified using :focus.",r.line,r.col,n):r.propCount==1&&t.report("Outlines shouldn't be hidden unless other visual changes are made.",r.line,r.col,n))}var n=this,r;e.addListener("startrule",i),e.addListener("startfontface",i),e.addListener("startpage",i),e.addListener("startpagemargin",i),e.addListener("startkeyframerule",i),e.addListener("property",function(e){var t=e.property.text.toLowerCase(),n=e.value;r&&(r.propCount++,t=="outline"&&(n=="none"||n=="0")&&(r.outline=!0))}),e.addListener("endrule",s),e.addListener("endfontface",s),e.addListener("endpage",s),e.addListener("endpagemargin",s),e.addListener("endkeyframerule",s)}}),CSSLint.addRule({id:"overqualified-elements",name:"Disallow overqualified elements",desc:"Don't use classes or IDs with elements (a.foo or a#foo).",browsers:"All",init:function(e,t){var n=this,r={};e.addListener("startrule",function(i){var s=i.selectors,o,u,a,f,l,c;for(f=0;f<s.length;f++){o=s[f];for(l=0;l<o.parts.length;l++){u=o.parts[l];if(u.type==e.SELECTOR_PART_TYPE)for(c=0;c<u.modifiers.length;c++)a=u.modifiers[c],u.elementName&&a.type=="id"?t.report("Element ("+u+") is overqualified, just use "+a+" without element name.",u.line,u.col,n):a.type=="class"&&(r[a]||(r[a]=[]),r[a].push({modifier:a,part:u}))}}}),e.addListener("endstylesheet",function(){var e;for(e in r)r.hasOwnProperty(e)&&r[e].length==1&&r[e][0].part.elementName&&t.report("Element ("+r[e][0].part+") is overqualified, just use "+r[e][0].modifier+" without element name.",r[e][0].part.line,r[e][0].part.col,n)})}}),CSSLint.addRule({id:"qualified-headings",name:"Disallow qualified headings",desc:"Headings should not be qualified (namespaced).",browsers:"All",init:function(e,t){var n=this;e.addListener("startrule",function(r){var i=r.selectors,s,o,u,a;for(u=0;u<i.length;u++){s=i[u];for(a=0;a<s.parts.length;a++)o=s.parts[a],o.type==e.SELECTOR_PART_TYPE&&o.elementName&&/h[1-6]/.test(o.elementName.toString())&&a>0&&t.report("Heading ("+o.elementName+") should not be qualified.",o.line,o.col,n)}})}}),CSSLint.addRule({id:"regex-selectors",name:"Disallow selectors that look like regexs",desc:"Selectors that look like regular expressions are slow and should be avoided.",browsers:"All",init:function(e,t){var n=this;e.addListener("startrule",function(r){var i=r.selectors,s,o,u,a,f,l;for(a=0;a<i.length;a++){s=i[a];for(f=0;f<s.parts.length;f++){o=s.parts[f];if(o.type==e.SELECTOR_PART_TYPE)for(l=0;l<o.modifiers.length;l++)u=o.modifiers[l],u.type=="attribute"&&/([\~\|\^\$\*]=)/.test(u)&&t.report("Attribute selectors with "+RegExp.$1+" are slow!",u.line,u.col,n)}}})}}),CSSLint.addRule({id:"rules-count",name:"Rules Count",desc:"Track how many rules there are.",browsers:"All",init:function(e,t){var n=this,r=0;e.addListener("startrule",function(){r++}),e.addListener("endstylesheet",function(){t.stat("rule-count",r)})}}),CSSLint.addRule({id:"shorthand",name:"Require shorthand properties",desc:"Use shorthand properties where possible.",browsers:"All",init:function(e,t){function f(e){u={}}function l(e){var r,i,s,o;for(r in a)if(a.hasOwnProperty(r)){o=0;for(i=0,s=a[r].length;i<s;i++)o+=u[a[r][i]]?1:0;o==a[r].length&&t.report("The properties "+a[r].join(", ")+" can be replaced by "+r+".",e.line,e.col,n)}}var n=this,r,i,s,o={},u,a={margin:["margin-top","margin-bottom","margin-left","margin-right"],padding:["padding-top","padding-bottom","padding-left","padding-right"]};for(r in a)if(a.hasOwnProperty(r))for(i=0,s=a[r].length;i<s;i++)o[a[r][i]]=r;e.addListener("startrule",f),e.addListener("startfontface",f),e.addListener("property",function(e){var t=e.property.toString().toLowerCase(),n=e.value.parts[0].value;o[t]&&(u[t]=1)}),e.addListener("endrule",l),e.addListener("endfontface",l)}}),CSSLint.addRule({id:"star-property-hack",name:"Disallow properties with a star prefix",desc:"Checks for the star property hack (targets IE6/7)",browsers:"All",init:function(e,t){var n=this;e.addListener("property",function(e){var r=e.property;r.hack=="*"&&t.report("Property with star prefix found.",e.property.line,e.property.col,n)})}}),CSSLint.addRule({id:"text-indent",name:"Disallow negative text-indent",desc:"Checks for text indent less than -99px",browsers:"All",init:function(e,t){function s(e){r=!1,i="inherit"}function o(e){r&&i!="ltr"&&t.report("Negative text-indent doesn't work well with RTL. If you use text-indent for image replacement explicitly set direction for that item to ltr.",r.line,r.col,n)}var n=this,r,i;e.addListener("startrule",s),e.addListener("startfontface",s),e.addListener("property",function(e){var t=e.property.toString().toLowerCase(),n=e.value;t=="text-indent"&&n.parts[0].value<-99?r=e.property:t=="direction"&&n=="ltr"&&(i="ltr")}),e.addListener("endrule",o),e.addListener("endfontface",o)}}),CSSLint.addRule({id:"underscore-property-hack",name:"Disallow properties with an underscore prefix",desc:"Checks for the underscore property hack (targets IE6)",browsers:"All",init:function(e,t){var n=this;e.addListener("property",function(e){var r=e.property;r.hack=="_"&&t.report("Property with underscore prefix found.",e.property.line,e.property.col,n)})}}),CSSLint.addRule({id:"unique-headings",name:"Headings should only be defined once",desc:"Headings should be defined only once.",browsers:"All",init:function(e,t){var n=this,r={h1:0,h2:0,h3:0,h4:0,h5:0,h6:0};e.addListener("startrule",function(e){var i=e.selectors,s,o,u,a,f;for(a=0;a<i.length;a++){s=i[a],o=s.parts[s.parts.length-1];if(o.elementName&&/(h[1-6])/i.test(o.elementName.toString())){for(f=0;f<o.modifiers.length;f++)if(o.modifiers[f].type=="pseudo"){u=!0;break}u||(r[RegExp.$1]++,r[RegExp.$1]>1&&t.report("Heading ("+o.elementName+") has already been defined.",o.line,o.col,n))}}}),e.addListener("endstylesheet",function(e){var i,s=[];for(i in r)r.hasOwnProperty(i)&&r[i]>1&&s.push(r[i]+" "+i+"s");s.length&&t.rollupWarn("You have "+s.join(", ")+" defined in this stylesheet.",n)})}}),CSSLint.addRule({id:"universal-selector",name:"Disallow universal selector",desc:"The universal selector (*) is known to be slow.",browsers:"All",init:function(e,t){var n=this;e.addListener("startrule",function(e){var r=e.selectors,i,s,o,u,a,f;for(u=0;u<r.length;u++)i=r[u],s=i.parts[i.parts.length-1],s.elementName=="*"&&t.report(n.desc,s.line,s.col,n)})}}),CSSLint.addRule({id:"unqualified-attributes",name:"Disallow unqualified attribute selectors",desc:"Unqualified attribute selectors are known to be slow.",browsers:"All",init:function(e,t){var n=this;e.addListener("startrule",function(r){var i=r.selectors,s,o,u,a,f,l;for(a=0;a<i.length;a++){s=i[a],o=s.parts[s.parts.length-1];if(o.type==e.SELECTOR_PART_TYPE)for(l=0;l<o.modifiers.length;l++)u=o.modifiers[l],u.type=="attribute"&&(!o.elementName||o.elementName=="*")&&t.report(n.desc,o.line,o.col,n)}})}}),CSSLint.addRule({id:"vendor-prefix",name:"Require standard property with vendor prefix",desc:"When using a vendor-prefixed property, make sure to include the standard one.",browsers:"All",init:function(e,t){function o(){r={},i=1}function u(e){var i,o,u,a,f,l,c=[];for(i in r)s[i]&&c.push({actual:i,needed:s[i]});for(o=0,u=c.length;o<u;o++)f=c[o].needed,l=c[o].actual,r[f]?r[f][0].pos<r[l][0].pos&&t.report("Standard property '"+f+"' should come after vendor-prefixed property '"+l+"'.",r[l][0].name.line,r[l][0].name.col,n):t.report("Missing standard property '"+f+"' to go along with '"+l+"'.",r[l][0].name.line,r[l][0].name.col,n)}var n=this,r,i,s={"-webkit-border-radius":"border-radius","-webkit-border-top-left-radius":"border-top-left-radius","-webkit-border-top-right-radius":"border-top-right-radius","-webkit-border-bottom-left-radius":"border-bottom-left-radius","-webkit-border-bottom-right-radius":"border-bottom-right-radius","-o-border-radius":"border-radius","-o-border-top-left-radius":"border-top-left-radius","-o-border-top-right-radius":"border-top-right-radius","-o-border-bottom-left-radius":"border-bottom-left-radius","-o-border-bottom-right-radius":"border-bottom-right-radius","-moz-border-radius":"border-radius","-moz-border-radius-topleft":"border-top-left-radius","-moz-border-radius-topright":"border-top-right-radius","-moz-border-radius-bottomleft":"border-bottom-left-radius","-moz-border-radius-bottomright":"border-bottom-right-radius","-moz-column-count":"column-count","-webkit-column-count":"column-count","-moz-column-gap":"column-gap","-webkit-column-gap":"column-gap","-moz-column-rule":"column-rule","-webkit-column-rule":"column-rule","-moz-column-rule-style":"column-rule-style","-webkit-column-rule-style":"column-rule-style","-moz-column-rule-color":"column-rule-color","-webkit-column-rule-color":"column-rule-color","-moz-column-rule-width":"column-rule-width","-webkit-column-rule-width":"column-rule-width","-moz-column-width":"column-width","-webkit-column-width":"column-width","-webkit-column-span":"column-span","-webkit-columns":"columns","-moz-box-shadow":"box-shadow","-webkit-box-shadow":"box-shadow","-moz-transform":"transform","-webkit-transform":"transform","-o-transform":"transform","-ms-transform":"transform","-moz-transform-origin":"transform-origin","-webkit-transform-origin":"transform-origin","-o-transform-origin":"transform-origin","-ms-transform-origin":"transform-origin","-moz-box-sizing":"box-sizing","-webkit-box-sizing":"box-sizing","-moz-user-select":"user-select","-khtml-user-select":"user-select","-webkit-user-select":"user-select"};e.addListener("startrule",o),e.addListener("startfontface",o),e.addListener("startpage",o),e.addListener("startpagemargin",o),e.addListener("startkeyframerule",o),e.addListener("property",function(e){var t=e.property.text.toLowerCase();r[t]||(r[t]=[]),r[t].push({name:e.property,value:e.value,pos:i++})}),e.addListener("endrule",u),e.addListener("endfontface",u),e.addListener("endpage",u),e.addListener("endpagemargin",u),e.addListener("endkeyframerule",u)}}),CSSLint.addRule({id:"zero-units",name:"Disallow units for 0 values",desc:"You don't need to specify units when a value is 0.",browsers:"All",init:function(e,t){var n=this;e.addListener("property",function(e){var r=e.value.parts,i=0,s=r.length;while(i<s)(r[i].units||r[i].type=="percentage")&&r[i].value===0&&r[i].type!="time"&&t.report("Values of 0 shouldn't have units specified.",r[i].line,r[i].col,n),i++})}}),exports.CSSLint=CSSLint}) \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/safecss-ace.js b/plugins/jetpack/modules/custom-css/custom-css/js/safecss-ace.js
new file mode 100644
index 00000000..65b01d6e
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/js/safecss-ace.js
@@ -0,0 +1,69 @@
+(function(global, $){
+ // shared scope insied IIFE in case it's needed.
+ var editor;
+ var syncCSS = function() {
+ $("#safecss").val( editor.getSession().getValue() );
+ };
+ var loadAce = function() {
+ // Set up ACE editor
+ ace.config.set( 'modePath', safecssAceSrcPath );
+ ace.config.set( 'workerPath', safecssAceSrcPath );
+ ace.config.set( 'themePath', safecssAceSrcPath );
+
+ editor = ace.edit( 'safecss-ace' );
+ // Globalize it so we can access it other places
+ global.safecss_editor = editor;
+ // Word-wrap, othewise the initial comments are borked.
+ editor.getSession().setUseWrapMode(true);
+ // This adds an annoying vertical line to the editor; get rid of it.
+ editor.setShowPrintMargin( false );
+ // Grab straight from the textarea
+ editor.getSession().setValue( $("#safecss").val() );
+ // We're editing CSS content
+ var CSSMode = ace.require( 'ace/mode/css' ).Mode;
+ editor.getSession().setMode( new CSSMode() );
+ // ace.js comes with the textmate coloring scheme already.
+ // kill the spinner
+ jQuery.fn.spin && $("#safecss-container").spin( false );
+ /*
+ // TODO: Add shortcuts for save and preview
+ editor.commands.addCommand({
+ name: 'cssPreview',
+ bindKey: {
+ win: 'Ctrl-P',
+ mac: 'Command-P',
+ sender: 'editor'
+ },
+ exec: function( env, args, request ) {
+ safecss_update_content();
+ jQuery( '#preview' ).click(); // this doesn't work :(
+ }
+ } );
+ */
+
+ // When submitting, make sure to include the updated CSS
+ // The Ace editor unfortunately doesn't handle this for us
+ $( '#safecssform' ).submit(syncCSS);
+ }
+
+ // exit if we're on IE <= 7
+ if ( ( $.browser.msie && parseInt( $.browser.version, 10 ) <= 7 ) || navigator.userAgent.match(/iPad/i) != null ) {
+ $("#safecss-container").hide();
+ $("#safecss").removeClass('hide-if-js');
+ return false;
+ }
+ // syntaxy goodness.
+ else {
+ $( '#safecss-ace, #safecss-container' ).css( 'height',
+ Math.max( 250, $( window ).height() - $( '#safecss-container' ).offset().top - $( '#wpadminbar' ).height() )
+ );
+
+ $(global).load(loadAce);
+ }
+
+ // for now, expose the syncCSS function.
+ global.aceSyncCSS = syncCSS;
+
+})(this, jQuery);
+
+
diff --git a/plugins/jetpack/modules/custom-css/custom-css/preprocessors.php b/plugins/jetpack/modules/custom-css/custom-css/preprocessors.php
new file mode 100644
index 00000000..eef6ab43
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/preprocessors.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * CSS preprocessor registration.
+ *
+ * To add a new preprocessor (or replace an existing one), hook into the
+ * jetpack_custom_css_preprocessors filter and add an entry to the array
+ * that is passed in.
+ *
+ * Format is:
+ * $preprocessors[ UNIQUE_KEY ] => array( 'name' => 'Processor name', 'callback' => [processing function] );
+ *
+ * The callback function accepts a single string argument (non-CSS markup) and returns a string (CSS).
+ *
+ * @param array $preprocessors The list of preprocessors added thus far.
+ * @return array
+ */
+
+function jetpack_register_css_preprocessors( $preprocessors ) {
+ $preprocessors['less'] = array(
+ 'name' => 'LESS',
+ 'callback' => 'jetpack_less_css_preprocess'
+ );
+
+ $preprocessors['sass'] = array(
+ 'name' => 'Sass (SCSS Syntax)',
+ 'callback' => 'jetpack_sass_css_preprocess'
+ );
+
+ return $preprocessors;
+}
+
+add_filter( 'jetpack_custom_css_preprocessors', 'jetpack_register_css_preprocessors' );
+
+function jetpack_less_css_preprocess( $less ) {
+ require( dirname( __FILE__ ) . '/preprocessors/lessc.inc.php' );
+
+ $compiler = new lessc();
+
+ try {
+ return $compiler->compile( $less );
+ } catch ( Exception $e ) {
+ return $less;
+ }
+}
+
+function jetpack_sass_css_preprocess( $sass ) {
+ require_once( dirname( __FILE__ ) . '/preprocessors/scss.inc.php' );
+
+ $compiler = new scssc();
+
+ try {
+ return $compiler->compile( $sass );
+ } catch ( Exception $e ) {
+ return $sass;
+ }
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/custom-css/custom-css/preprocessors/lessc.inc.php b/plugins/jetpack/modules/custom-css/custom-css/preprocessors/lessc.inc.php
new file mode 100644
index 00000000..c42147c5
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/preprocessors/lessc.inc.php
@@ -0,0 +1,3359 @@
+<?php
+
+/**
+ * lessphp v0.3.8
+ * http://leafo.net/lessphp
+ *
+ * LESS css compiler, adapted from http://lesscss.org
+ *
+ * Copyright 2012, Leaf Corcoran <leafot@gmail.com>
+ * Licensed under MIT or GPLv3, see LICENSE
+ */
+
+
+/**
+ * The less compiler and parser.
+ *
+ * Converting LESS to CSS is a three stage process. The incoming file is parsed
+ * by `lessc_parser` into a syntax tree, then it is compiled into another tree
+ * representing the CSS structure by `lessc`. The CSS tree is fed into a
+ * formatter, like `lessc_formatter` which then outputs CSS as a string.
+ *
+ * During the first compile, all values are *reduced*, which means that their
+ * types are brought to the lowest form before being dump as strings. This
+ * handles math equations, variable dereferences, and the like.
+ *
+ * The `parse` function of `lessc` is the entry point.
+ *
+ * In summary:
+ *
+ * The `lessc` class creates an intstance of the parser, feeds it LESS code,
+ * then transforms the resulting tree to a CSS tree. This class also holds the
+ * evaluation context, such as all available mixins and variables at any given
+ * time.
+ *
+ * The `lessc_parser` class is only concerned with parsing its input.
+ *
+ * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string,
+ * handling things like indentation.
+ */
+class lessc {
+ static public $VERSION = "v0.3.8";
+ static protected $TRUE = array("keyword", "true");
+ static protected $FALSE = array("keyword", "false");
+
+ protected $libFunctions = array();
+ protected $registeredVars = array();
+ protected $preserveComments = false;
+
+ public $vPrefix = '@'; // prefix of abstract properties
+ public $mPrefix = '$'; // prefix of abstract blocks
+ public $parentSelector = '&';
+
+ public $importDisabled = false;
+ public $importDir = '';
+
+ protected $numberPrecision = null;
+
+ // set to the parser that generated the current line when compiling
+ // so we know how to create error messages
+ protected $sourceParser = null;
+ protected $sourceLoc = null;
+
+ static public $defaultValue = array("keyword", "");
+
+ static protected $nextImportId = 0; // uniquely identify imports
+
+ // attempts to find the path of an import url, returns null for css files
+ protected function findImport($url) {
+ foreach ((array)$this->importDir as $dir) {
+ $full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url;
+ if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) {
+ return $file;
+ }
+ }
+
+ return null;
+ }
+
+ protected function fileExists($name) {
+ return is_file($name);
+ }
+
+ static public function compressList($items, $delim) {
+ if (!isset($items[1]) && isset($items[0])) return $items[0];
+ else return array('list', $delim, $items);
+ }
+
+ static public function preg_quote($what) {
+ return preg_quote($what, '/');
+ }
+
+ protected function tryImport($importPath, $parentBlock, $out) {
+ if ($importPath[0] == "function" && $importPath[1] == "url") {
+ $importPath = $this->flattenList($importPath[2]);
+ }
+
+ $str = $this->coerceString($importPath);
+ if ($str === null) return false;
+
+ $url = $this->compileValue($this->lib_e($str));
+
+ // don't import if it ends in css
+ if (substr_compare($url, '.css', -4, 4) === 0) return false;
+
+ $realPath = $this->findImport($url);
+ if ($realPath === null) return false;
+
+ if ($this->importDisabled) {
+ return array(false, "/* import disabled */");
+ }
+
+ $this->addParsedFile($realPath);
+ $parser = $this->makeParser($realPath);
+ $root = $parser->parse(file_get_contents($realPath));
+
+ // set the parents of all the block props
+ foreach ($root->props as $prop) {
+ if ($prop[0] == "block") {
+ $prop[1]->parent = $parentBlock;
+ }
+ }
+
+ // copy mixins into scope, set their parents
+ // bring blocks from import into current block
+ // TODO: need to mark the source parser these came from this file
+ foreach ($root->children as $childName => $child) {
+ if (isset($parentBlock->children[$childName])) {
+ $parentBlock->children[$childName] = array_merge(
+ $parentBlock->children[$childName],
+ $child);
+ } else {
+ $parentBlock->children[$childName] = $child;
+ }
+ }
+
+ $pi = pathinfo($realPath);
+ $dir = $pi["dirname"];
+
+ list($top, $bottom) = $this->sortProps($root->props, true);
+ $this->compileImportedProps($top, $parentBlock, $out, $parser, $dir);
+
+ return array(true, $bottom, $parser, $dir);
+ }
+
+ protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) {
+ $oldSourceParser = $this->sourceParser;
+
+ $oldImport = $this->importDir;
+
+ // TODO: this is because the importDir api is stupid
+ $this->importDir = (array)$this->importDir;
+ array_unshift($this->importDir, $importDir);
+
+ foreach ($props as $prop) {
+ $this->compileProp($prop, $block, $out);
+ }
+
+ $this->importDir = $oldImport;
+ $this->sourceParser = $oldSourceParser;
+ }
+
+ /**
+ * Recursively compiles a block.
+ *
+ * A block is analogous to a CSS block in most cases. A single LESS document
+ * is encapsulated in a block when parsed, but it does not have parent tags
+ * so all of it's children appear on the root level when compiled.
+ *
+ * Blocks are made up of props and children.
+ *
+ * Props are property instructions, array tuples which describe an action
+ * to be taken, eg. write a property, set a variable, mixin a block.
+ *
+ * The children of a block are just all the blocks that are defined within.
+ * This is used to look up mixins when performing a mixin.
+ *
+ * Compiling the block involves pushing a fresh environment on the stack,
+ * and iterating through the props, compiling each one.
+ *
+ * See lessc::compileProp()
+ *
+ */
+ protected function compileBlock($block) {
+ switch ($block->type) {
+ case "root":
+ $this->compileRoot($block);
+ break;
+ case null:
+ $this->compileCSSBlock($block);
+ break;
+ case "media":
+ $this->compileMedia($block);
+ break;
+ case "directive":
+ $name = "@" . $block->name;
+ if (!empty($block->value)) {
+ $name .= " " . $this->compileValue($this->reduce($block->value));
+ }
+
+ $this->compileNestedBlock($block, array($name));
+ break;
+ default:
+ $this->throwError("unknown block type: $block->type\n");
+ }
+ }
+
+ protected function compileCSSBlock($block) {
+ $env = $this->pushEnv();
+
+ $selectors = $this->compileSelectors($block->tags);
+ $env->selectors = $this->multiplySelectors($selectors);
+ $out = $this->makeOutputBlock(null, $env->selectors);
+
+ $this->scope->children[] = $out;
+ $this->compileProps($block, $out);
+
+ $block->scope = $env; // mixins carry scope with them!
+ $this->popEnv();
+ }
+
+ protected function compileMedia($media) {
+ $env = $this->pushEnv($media);
+ $parentScope = $this->mediaParent($this->scope);
+
+ $query = $this->compileMediaQuery($this->multiplyMedia($env));
+
+ $this->scope = $this->makeOutputBlock($media->type, array($query));
+ $parentScope->children[] = $this->scope;
+
+ $this->compileProps($media, $this->scope);
+
+ if (count($this->scope->lines) > 0) {
+ $orphanSelelectors = $this->findClosestSelectors();
+ if (!is_null($orphanSelelectors)) {
+ $orphan = $this->makeOutputBlock(null, $orphanSelelectors);
+ $orphan->lines = $this->scope->lines;
+ array_unshift($this->scope->children, $orphan);
+ $this->scope->lines = array();
+ }
+ }
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ protected function mediaParent($scope) {
+ while (!empty($scope->parent)) {
+ if (!empty($scope->type) && $scope->type != "media") {
+ break;
+ }
+ $scope = $scope->parent;
+ }
+
+ return $scope;
+ }
+
+ protected function compileNestedBlock($block, $selectors) {
+ $this->pushEnv($block);
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
+ $this->scope->parent->children[] = $this->scope;
+
+ $this->compileProps($block, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ protected function compileRoot($root) {
+ $this->pushEnv();
+ $this->scope = $this->makeOutputBlock($root->type);
+ $this->compileProps($root, $this->scope);
+ $this->popEnv();
+ }
+
+ protected function compileProps($block, $out) {
+ foreach ($this->sortProps($block->props) as $prop) {
+ $this->compileProp($prop, $block, $out);
+ }
+ }
+
+ protected function sortProps($props, $split = false) {
+ $vars = array();
+ $imports = array();
+ $other = array();
+
+ foreach ($props as $prop) {
+ switch ($prop[0]) {
+ case "assign":
+ if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) {
+ $vars[] = $prop;
+ } else {
+ $other[] = $prop;
+ }
+ break;
+ case "import":
+ $id = self::$nextImportId++;
+ $prop[] = $id;
+ $imports[] = $prop;
+ $other[] = array("import_mixin", $id);
+ break;
+ default:
+ $other[] = $prop;
+ }
+ }
+
+ if ($split) {
+ return array(array_merge($vars, $imports), $other);
+ } else {
+ return array_merge($vars, $imports, $other);
+ }
+ }
+
+ protected function compileMediaQuery($queries) {
+ $compiledQueries = array();
+ foreach ($queries as $query) {
+ $parts = array();
+ foreach ($query as $q) {
+ switch ($q[0]) {
+ case "mediaType":
+ $parts[] = implode(" ", array_slice($q, 1));
+ break;
+ case "mediaExp":
+ if (isset($q[2])) {
+ $parts[] = "($q[1]: " .
+ $this->compileValue($this->reduce($q[2])) . ")";
+ } else {
+ $parts[] = "($q[1])";
+ }
+ break;
+ }
+ }
+
+ if (count($parts) > 0) {
+ $compiledQueries[] = implode(" and ", $parts);
+ }
+ }
+
+ $out = "@media";
+ if (!empty($parts)) {
+ $out .= " " .
+ implode($this->formatter->selectorSeparator, $compiledQueries);
+ }
+ return $out;
+ }
+
+ protected function multiplyMedia($env, $childQueries = null) {
+ if (is_null($env) ||
+ !empty($env->block->type) && $env->block->type != "media")
+ {
+ return $childQueries;
+ }
+
+ // plain old block, skip
+ if (empty($env->block->type)) {
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ $out = array();
+ $queries = $env->block->queries;
+ if (is_null($childQueries)) {
+ $out = $queries;
+ } else {
+ foreach ($queries as $parent) {
+ foreach ($childQueries as $child) {
+ $out[] = array_merge($parent, $child);
+ }
+ }
+ }
+
+ return $this->multiplyMedia($env->parent, $out);
+ }
+
+ protected function expandParentSelectors(&$tag, $replace) {
+ $parts = explode("$&$", $tag);
+ $count = 0;
+ foreach ($parts as &$part) {
+ $part = str_replace($this->parentSelector, $replace, $part, $c);
+ $count += $c;
+ }
+ $tag = implode($this->parentSelector, $parts);
+ return $count;
+ }
+
+ protected function findClosestSelectors() {
+ $env = $this->env;
+ $selectors = null;
+ while ($env !== null) {
+ if (isset($env->selectors)) {
+ $selectors = $env->selectors;
+ break;
+ }
+ $env = $env->parent;
+ }
+
+ return $selectors;
+ }
+
+
+ // multiply $selectors against the nearest selectors in env
+ protected function multiplySelectors($selectors) {
+ // find parent selectors
+
+ $parentSelectors = $this->findClosestSelectors();
+ if (is_null($parentSelectors)) {
+ // kill parent reference in top level selector
+ foreach ($selectors as &$s) {
+ $this->expandParentSelectors($s, "");
+ }
+
+ return $selectors;
+ }
+
+ $out = array();
+ foreach ($parentSelectors as $parent) {
+ foreach ($selectors as $child) {
+ $count = $this->expandParentSelectors($child, $parent);
+
+ // don't prepend the parent tag if & was used
+ if ($count > 0) {
+ $out[] = trim($child);
+ } else {
+ $out[] = trim($parent . ' ' . $child);
+ }
+ }
+ }
+
+ return $out;
+ }
+
+ // reduces selector expressions
+ protected function compileSelectors($selectors) {
+ $out = array();
+
+ foreach ($selectors as $s) {
+ if (is_array($s)) {
+ list(, $value) = $s;
+ $out[] = $this->compileValue($this->reduce($value));
+ } else {
+ $out[] = $s;
+ }
+ }
+
+ return $out;
+ }
+
+ protected function eq($left, $right) {
+ return $left == $right;
+ }
+
+ protected function patternMatch($block, $callingArgs) {
+ // match the guards if it has them
+ // any one of the groups must have all its guards pass for a match
+ if (!empty($block->guards)) {
+ $groupPassed = false;
+ foreach ($block->guards as $guardGroup) {
+ foreach ($guardGroup as $guard) {
+ $this->pushEnv();
+ $this->zipSetArgs($block->args, $callingArgs);
+
+ $negate = false;
+ if ($guard[0] == "negate") {
+ $guard = $guard[1];
+ $negate = true;
+ }
+
+ $passed = $this->reduce($guard) == self::$TRUE;
+ if ($negate) $passed = !$passed;
+
+ $this->popEnv();
+
+ if ($passed) {
+ $groupPassed = true;
+ } else {
+ $groupPassed = false;
+ break;
+ }
+ }
+
+ if ($groupPassed) break;
+ }
+
+ if (!$groupPassed) {
+ return false;
+ }
+ }
+
+ $numCalling = count($callingArgs);
+
+ if (empty($block->args)) {
+ return $block->isVararg || $numCalling == 0;
+ }
+
+ $i = -1; // no args
+ // try to match by arity or by argument literal
+ foreach ($block->args as $i => $arg) {
+ switch ($arg[0]) {
+ case "lit":
+ if (empty($callingArgs[$i]) || !$this->eq($arg[1], $callingArgs[$i])) {
+ return false;
+ }
+ break;
+ case "arg":
+ // no arg and no default value
+ if (!isset($callingArgs[$i]) && !isset($arg[2])) {
+ return false;
+ }
+ break;
+ case "rest":
+ $i--; // rest can be empty
+ break 2;
+ }
+ }
+
+ if ($block->isVararg) {
+ return true; // not having enough is handled above
+ } else {
+ $numMatched = $i + 1;
+ // greater than becuase default values always match
+ return $numMatched >= $numCalling;
+ }
+ }
+
+ protected function patternMatchAll($blocks, $callingArgs) {
+ $matches = null;
+ foreach ($blocks as $block) {
+ if ($this->patternMatch($block, $callingArgs)) {
+ $matches[] = $block;
+ }
+ }
+
+ return $matches;
+ }
+
+ // attempt to find blocks matched by path and args
+ protected function findBlocks($searchIn, $path, $args, $seen=array()) {
+ if ($searchIn == null) return null;
+ if (isset($seen[$searchIn->id])) return null;
+ $seen[$searchIn->id] = true;
+
+ $name = $path[0];
+
+ if (isset($searchIn->children[$name])) {
+ $blocks = $searchIn->children[$name];
+ if (count($path) == 1) {
+ $matches = $this->patternMatchAll($blocks, $args);
+ if (!empty($matches)) {
+ // This will return all blocks that match in the closest
+ // scope that has any matching block, like lessjs
+ return $matches;
+ }
+ } else {
+ $matches = array();
+ foreach ($blocks as $subBlock) {
+ $subMatches = $this->findBlocks($subBlock,
+ array_slice($path, 1), $args, $seen);
+
+ if (!is_null($subMatches)) {
+ foreach ($subMatches as $sm) {
+ $matches[] = $sm;
+ }
+ }
+ }
+
+ return count($matches) > 0 ? $matches : null;
+ }
+ }
+
+ if ($searchIn->parent === $searchIn) return null;
+ return $this->findBlocks($searchIn->parent, $path, $args, $seen);
+ }
+
+ // sets all argument names in $args to either the default value
+ // or the one passed in through $values
+ protected function zipSetArgs($args, $values) {
+ $i = 0;
+ $assignedValues = array();
+ foreach ($args as $a) {
+ if ($a[0] == "arg") {
+ if ($i < count($values) && !is_null($values[$i])) {
+ $value = $values[$i];
+ } elseif (isset($a[2])) {
+ $value = $a[2];
+ } else $value = null;
+
+ $value = $this->reduce($value);
+ $this->set($a[1], $value);
+ $assignedValues[] = $value;
+ }
+ $i++;
+ }
+
+ // check for a rest
+ $last = end($args);
+ if ($last[0] == "rest") {
+ $rest = array_slice($values, count($args) - 1);
+ $this->set($last[1], $this->reduce(array("list", " ", $rest)));
+ }
+
+ $this->env->arguments = $assignedValues;
+ }
+
+ // compile a prop and update $lines or $blocks appropriately
+ protected function compileProp($prop, $block, $out) {
+ // set error position context
+ $this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1;
+
+ switch ($prop[0]) {
+ case 'assign':
+ list(, $name, $value) = $prop;
+ if ($name[0] == $this->vPrefix) {
+ $this->set($name, $value);
+ } else {
+ $out->lines[] = $this->formatter->property($name,
+ $this->compileValue($this->reduce($value)));
+ }
+ break;
+ case 'block':
+ list(, $child) = $prop;
+ $this->compileBlock($child);
+ break;
+ case 'mixin':
+ list(, $path, $args, $suffix) = $prop;
+
+ $args = array_map(array($this, "reduce"), (array)$args);
+ $mixins = $this->findBlocks($block, $path, $args);
+
+ if ($mixins === null) {
+ // fwrite(STDERR,"failed to find block: ".implode(" > ", $path)."\n");
+ break; // throw error here??
+ }
+
+ foreach ($mixins as $mixin) {
+ $haveScope = false;
+ if (isset($mixin->parent->scope)) {
+ $haveScope = true;
+ $mixinParentEnv = $this->pushEnv();
+ $mixinParentEnv->storeParent = $mixin->parent->scope;
+ }
+
+ $haveArgs = false;
+ if (isset($mixin->args)) {
+ $haveArgs = true;
+ $this->pushEnv();
+ $this->zipSetArgs($mixin->args, $args);
+ }
+
+ $oldParent = $mixin->parent;
+ if ($mixin != $block) $mixin->parent = $block;
+
+ foreach ($this->sortProps($mixin->props) as $subProp) {
+ if ($suffix !== null &&
+ $subProp[0] == "assign" &&
+ is_string($subProp[1]) &&
+ $subProp[1]{0} != $this->vPrefix)
+ {
+ $subProp[2] = array(
+ 'list', ' ',
+ array($subProp[2], array('keyword', $suffix))
+ );
+ }
+
+ $this->compileProp($subProp, $mixin, $out);
+ }
+
+ $mixin->parent = $oldParent;
+
+ if ($haveArgs) $this->popEnv();
+ if ($haveScope) $this->popEnv();
+ }
+
+ break;
+ case 'raw':
+ $out->lines[] = $prop[1];
+ break;
+ case "directive":
+ list(, $name, $value) = $prop;
+ $out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';';
+ break;
+ case "comment":
+ $out->lines[] = $prop[1];
+ break;
+ case "import";
+ list(, $importPath, $importId) = $prop;
+ $importPath = $this->reduce($importPath);
+
+ if (!isset($this->env->imports)) {
+ $this->env->imports = array();
+ }
+
+ $result = $this->tryImport($importPath, $block, $out);
+
+ $this->env->imports[$importId] = $result === false ?
+ array(false, "@import " . $this->compileValue($importPath).";") :
+ $result;
+
+ break;
+ case "import_mixin":
+ list(,$importId) = $prop;
+ $import = $this->env->imports[$importId];
+ if ($import[0] === false) {
+ $out->lines[] = $import[1];
+ } else {
+ list(, $bottom, $parser, $importDir) = $import;
+ $this->compileImportedProps($bottom, $block, $out, $parser, $importDir);
+ }
+
+ break;
+ default:
+ $this->throwError("unknown op: {$prop[0]}\n");
+ }
+ }
+
+
+ /**
+ * Compiles a primitive value into a CSS property value.
+ *
+ * Values in lessphp are typed by being wrapped in arrays, their format is
+ * typically:
+ *
+ * array(type, contents [, additional_contents]*)
+ *
+ * The input is expected to be reduced. This function will not work on
+ * things like expressions and variables.
+ */
+ protected function compileValue($value) {
+ switch ($value[0]) {
+ case 'list':
+ // [1] - delimiter
+ // [2] - array of values
+ return implode($value[1], array_map(array($this, 'compileValue'), $value[2]));
+ case 'raw_color':
+ if (!empty($this->formatter->compressColors)) {
+ return $this->compileValue($this->coerceColor($value));
+ }
+ return $value[1];
+ case 'keyword':
+ // [1] - the keyword
+ return $value[1];
+ case 'number':
+ list(, $num, $unit) = $value;
+ // [1] - the number
+ // [2] - the unit
+ if ($this->numberPrecision !== null) {
+ $num = round($num, $this->numberPrecision);
+ }
+ return $num . $unit;
+ case 'string':
+ // [1] - contents of string (includes quotes)
+ list(, $delim, $content) = $value;
+ foreach ($content as &$part) {
+ if (is_array($part)) {
+ $part = $this->compileValue($part);
+ }
+ }
+ return $delim . implode($content) . $delim;
+ case 'color':
+ // [1] - red component (either number or a %)
+ // [2] - green component
+ // [3] - blue component
+ // [4] - optional alpha component
+ list(, $r, $g, $b) = $value;
+ $r = round($r);
+ $g = round($g);
+ $b = round($b);
+
+ if (count($value) == 5 && $value[4] != 1) { // rgba
+ return 'rgba('.$r.','.$g.','.$b.','.$value[4].')';
+ }
+
+ $h = sprintf("#%02x%02x%02x", $r, $g, $b);
+
+ if (!empty($this->formatter->compressColors)) {
+ // Converting hex color to short notation (e.g. #003399 to #039)
+ if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
+ $h = '#' . $h[1] . $h[3] . $h[5];
+ }
+ }
+
+ return $h;
+
+ case 'function':
+ list(, $name, $args) = $value;
+ return $name.'('.$this->compileValue($args).')';
+ default: // assumed to be unit
+ $this->throwError("unknown value type: $value[0]");
+ }
+ }
+
+ protected function lib_isnumber($value) {
+ return $this->toBool($value[0] == "number");
+ }
+
+ protected function lib_isstring($value) {
+ return $this->toBool($value[0] == "string");
+ }
+
+ protected function lib_iscolor($value) {
+ return $this->toBool($this->coerceColor($value));
+ }
+
+ protected function lib_iskeyword($value) {
+ return $this->toBool($value[0] == "keyword");
+ }
+
+ protected function lib_ispixel($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "px");
+ }
+
+ protected function lib_ispercentage($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "%");
+ }
+
+ protected function lib_isem($value) {
+ return $this->toBool($value[0] == "number" && $value[2] == "em");
+ }
+
+ protected function lib_rgbahex($color) {
+ $color = $this->coerceColor($color);
+ if (is_null($color))
+ $this->throwError("color expected for rgbahex");
+
+ return sprintf("#%02x%02x%02x%02x",
+ isset($color[4]) ? $color[4]*255 : 255,
+ $color[1],$color[2], $color[3]);
+ }
+
+ protected function lib_argb($color){
+ return $this->lib_rgbahex($color);
+ }
+
+ // utility func to unquote a string
+ protected function lib_e($arg) {
+ switch ($arg[0]) {
+ case "list":
+ $items = $arg[2];
+ if (isset($items[0])) {
+ return $this->lib_e($items[0]);
+ }
+ return self::$defaultValue;
+ case "string":
+ $arg[1] = "";
+ return $arg;
+ case "keyword":
+ return $arg;
+ default:
+ return array("keyword", $this->compileValue($arg));
+ }
+ }
+
+ protected function lib__sprintf($args) {
+ if ($args[0] != "list") return $args;
+ $values = $args[2];
+ $string = array_shift($values);
+ $template = $this->compileValue($this->lib_e($string));
+
+ $i = 0;
+ if (preg_match_all('/%[dsa]/', $template, $m)) {
+ foreach ($m[0] as $match) {
+ $val = isset($values[$i]) ?
+ $this->reduce($values[$i]) : array('keyword', '');
+
+ // lessjs compat, renders fully expanded color, not raw color
+ if ($color = $this->coerceColor($val)) {
+ $val = $color;
+ }
+
+ $i++;
+ $rep = $this->compileValue($this->lib_e($val));
+ $template = preg_replace('/'.self::preg_quote($match).'/',
+ $rep, $template, 1);
+ }
+ }
+
+ $d = $string[0] == "string" ? $string[1] : '"';
+ return array("string", $d, array($template));
+ }
+
+ protected function lib_floor($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", floor($value), $arg[2]);
+ }
+
+ protected function lib_ceil($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", ceil($value), $arg[2]);
+ }
+
+ protected function lib_round($arg) {
+ $value = $this->assertNumber($arg);
+ return array("number", round($value), $arg[2]);
+ }
+
+ /**
+ * Helper function to get arguments for color manipulation functions.
+ * takes a list that contains a color like thing and a percentage
+ */
+ protected function colorArgs($args) {
+ if ($args[0] != 'list' || count($args[2]) < 2) {
+ return array(array('color', 0, 0, 0), 0);
+ }
+ list($color, $delta) = $args[2];
+ $color = $this->assertColor($color);
+ $delta = floatval($delta[1]);
+
+ return array($color, $delta);
+ }
+
+ protected function lib_darken($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[3] = $this->clamp($hsl[3] - $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_lighten($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[3] = $this->clamp($hsl[3] + $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_saturate($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[2] = $this->clamp($hsl[2] + $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_desaturate($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+ $hsl[2] = $this->clamp($hsl[2] - $delta, 100);
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_spin($args) {
+ list($color, $delta) = $this->colorArgs($args);
+
+ $hsl = $this->toHSL($color);
+
+ $hsl[1] = $hsl[1] + $delta % 360;
+ if ($hsl[1] < 0) $hsl[1] += 360;
+
+ return $this->toRGB($hsl);
+ }
+
+ protected function lib_fadeout($args) {
+ list($color, $delta) = $this->colorArgs($args);
+ $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100);
+ return $color;
+ }
+
+ protected function lib_fadein($args) {
+ list($color, $delta) = $this->colorArgs($args);
+ $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100);
+ return $color;
+ }
+
+ protected function lib_hue($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[1]);
+ }
+
+ protected function lib_saturation($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[2]);
+ }
+
+ protected function lib_lightness($color) {
+ $hsl = $this->toHSL($this->assertColor($color));
+ return round($hsl[3]);
+ }
+
+ // get the alpha of a color
+ // defaults to 1 for non-colors or colors without an alpha
+ protected function lib_alpha($value) {
+ if (!is_null($color = $this->coerceColor($value))) {
+ return isset($color[4]) ? $color[4] : 1;
+ }
+ }
+
+ // set the alpha of the color
+ protected function lib_fade($args) {
+ list($color, $alpha) = $this->colorArgs($args);
+ $color[4] = $this->clamp($alpha / 100.0);
+ return $color;
+ }
+
+ protected function lib_percentage($arg) {
+ $num = $this->assertNumber($arg);
+ return array("number", $num*100, "%");
+ }
+
+ // mixes two colors by weight
+ // mix(@color1, @color2, @weight);
+ // http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method
+ protected function lib_mix($args) {
+ if ($args[0] != "list" || count($args[2]) < 3)
+ $this->throwError("mix expects (color1, color2, weight)");
+
+ list($first, $second, $weight) = $args[2];
+ $first = $this->assertColor($first);
+ $second = $this->assertColor($second);
+
+ $first_a = $this->lib_alpha($first);
+ $second_a = $this->lib_alpha($second);
+ $weight = $weight[1] / 100.0;
+
+ $w = $weight * 2 - 1;
+ $a = $first_a - $second_a;
+
+ $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
+ $w2 = 1.0 - $w1;
+
+ $new = array('color',
+ $w1 * $first[1] + $w2 * $second[1],
+ $w1 * $first[2] + $w2 * $second[2],
+ $w1 * $first[3] + $w2 * $second[3],
+ );
+
+ if ($first_a != 1.0 || $second_a != 1.0) {
+ $new[] = $first_a * $weight + $second_a * ($weight - 1);
+ }
+
+ return $this->fixColor($new);
+ }
+
+ protected function assertColor($value, $error = "expected color value") {
+ $color = $this->coerceColor($value);
+ if (is_null($color)) $this->throwError($error);
+ return $color;
+ }
+
+ protected function assertNumber($value, $error = "expecting number") {
+ if ($value[0] == "number") return $value[1];
+ $this->throwError($error);
+ }
+
+ protected function toHSL($color) {
+ if ($color[0] == 'hsl') return $color;
+
+ $r = $color[1] / 255;
+ $g = $color[2] / 255;
+ $b = $color[3] / 255;
+
+ $min = min($r, $g, $b);
+ $max = max($r, $g, $b);
+
+ $L = ($min + $max) / 2;
+ if ($min == $max) {
+ $S = $H = 0;
+ } else {
+ if ($L < 0.5)
+ $S = ($max - $min)/($max + $min);
+ else
+ $S = ($max - $min)/(2.0 - $max - $min);
+
+ if ($r == $max) $H = ($g - $b)/($max - $min);
+ elseif ($g == $max) $H = 2.0 + ($b - $r)/($max - $min);
+ elseif ($b == $max) $H = 4.0 + ($r - $g)/($max - $min);
+
+ }
+
+ $out = array('hsl',
+ ($H < 0 ? $H + 6 : $H)*60,
+ $S*100,
+ $L*100,
+ );
+
+ if (count($color) > 4) $out[] = $color[4]; // copy alpha
+ return $out;
+ }
+
+ protected function toRGB_helper($comp, $temp1, $temp2) {
+ if ($comp < 0) $comp += 1.0;
+ elseif ($comp > 1) $comp -= 1.0;
+
+ if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp;
+ if (2 * $comp < 1) return $temp2;
+ if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6;
+
+ return $temp1;
+ }
+
+ /**
+ * Converts a hsl array into a color value in rgb.
+ * Expects H to be in range of 0 to 360, S and L in 0 to 100
+ */
+ protected function toRGB($color) {
+ if ($color == 'color') return $color;
+
+ $H = $color[1] / 360;
+ $S = $color[2] / 100;
+ $L = $color[3] / 100;
+
+ if ($S == 0) {
+ $r = $g = $b = $L;
+ } else {
+ $temp2 = $L < 0.5 ?
+ $L*(1.0 + $S) :
+ $L + $S - $L * $S;
+
+ $temp1 = 2.0 * $L - $temp2;
+
+ $r = $this->toRGB_helper($H + 1/3, $temp1, $temp2);
+ $g = $this->toRGB_helper($H, $temp1, $temp2);
+ $b = $this->toRGB_helper($H - 1/3, $temp1, $temp2);
+ }
+
+ // $out = array('color', round($r*255), round($g*255), round($b*255));
+ $out = array('color', $r*255, $g*255, $b*255);
+ if (count($color) > 4) $out[] = $color[4]; // copy alpha
+ return $out;
+ }
+
+ protected function clamp($v, $max = 1, $min = 0) {
+ return min($max, max($min, $v));
+ }
+
+ /**
+ * Convert the rgb, rgba, hsl color literals of function type
+ * as returned by the parser into values of color type.
+ */
+ protected function funcToColor($func) {
+ $fname = $func[1];
+ if ($func[2][0] != 'list') return false; // need a list of arguments
+ $rawComponents = $func[2][2];
+
+ if ($fname == 'hsl' || $fname == 'hsla') {
+ $hsl = array('hsl');
+ $i = 0;
+ foreach ($rawComponents as $c) {
+ $val = $this->reduce($c);
+ $val = isset($val[1]) ? floatval($val[1]) : 0;
+
+ if ($i == 0) $clamp = 360;
+ elseif ($i < 3) $clamp = 100;
+ else $clamp = 1;
+
+ $hsl[] = $this->clamp($val, $clamp);
+ $i++;
+ }
+
+ while (count($hsl) < 4) $hsl[] = 0;
+ return $this->toRGB($hsl);
+
+ } elseif ($fname == 'rgb' || $fname == 'rgba') {
+ $components = array();
+ $i = 1;
+ foreach ($rawComponents as $c) {
+ $c = $this->reduce($c);
+ if ($i < 4) {
+ if ($c[0] == "number" && $c[2] == "%") {
+ $components[] = 255 * ($c[1] / 100);
+ } else {
+ $components[] = floatval($c[1]);
+ }
+ } elseif ($i == 4) {
+ if ($c[0] == "number" && $c[2] == "%") {
+ $components[] = 1.0 * ($c[1] / 100);
+ } else {
+ $components[] = floatval($c[1]);
+ }
+ } else break;
+
+ $i++;
+ }
+ while (count($components) < 3) $components[] = 0;
+ array_unshift($components, 'color');
+ return $this->fixColor($components);
+ }
+
+ return false;
+ }
+
+ protected function reduce($value, $forExpression = false) {
+ switch ($value[0]) {
+ case "variable":
+ $key = $value[1];
+ if (is_array($key)) {
+ $key = $this->reduce($key);
+ $key = $this->vPrefix . $this->compileValue($this->lib_e($key));
+ }
+
+ $seen =& $this->env->seenNames;
+
+ if (!empty($seen[$key])) {
+ $this->throwError("infinite loop detected: $key");
+ }
+
+ $seen[$key] = true;
+ $out = $this->reduce($this->get($key, self::$defaultValue));
+ $seen[$key] = false;
+ return $out;
+ case "list":
+ foreach ($value[2] as &$item) {
+ $item = $this->reduce($item, $forExpression);
+ }
+ return $value;
+ case "expression":
+ return $this->evaluate($value);
+ case "string":
+ foreach ($value[2] as &$part) {
+ if (is_array($part)) {
+ $strip = $part[0] == "variable";
+ $part = $this->reduce($part);
+ if ($strip) $part = $this->lib_e($part);
+ }
+ }
+ return $value;
+ case "escape":
+ list(,$inner) = $value;
+ return $this->lib_e($this->reduce($inner));
+ case "function":
+ $color = $this->funcToColor($value);
+ if ($color) return $color;
+
+ list(, $name, $args) = $value;
+ if ($name == "%") $name = "_sprintf";
+ $f = isset($this->libFunctions[$name]) ?
+ $this->libFunctions[$name] : array($this, 'lib_'.$name);
+
+ if (is_callable($f)) {
+ if ($args[0] == 'list')
+ $args = self::compressList($args[2], $args[1]);
+
+ $ret = call_user_func($f, $this->reduce($args, true), $this);
+
+ if (is_null($ret)) {
+ return array("string", "", array(
+ $name, "(", $args, ")"
+ ));
+ }
+
+ // convert to a typed value if the result is a php primitive
+ if (is_numeric($ret)) $ret = array('number', $ret, "");
+ elseif (!is_array($ret)) $ret = array('keyword', $ret);
+
+ return $ret;
+ }
+
+ // plain function, reduce args
+ $value[2] = $this->reduce($value[2]);
+ return $value;
+ case "unary":
+ list(, $op, $exp) = $value;
+ $exp = $this->reduce($exp);
+
+ if ($exp[0] == "number") {
+ switch ($op) {
+ case "+":
+ return $exp;
+ case "-":
+ $exp[1] *= -1;
+ return $exp;
+ }
+ }
+ return array("string", "", array($op, $exp));
+ }
+
+ if ($forExpression) {
+ switch ($value[0]) {
+ case "keyword":
+ if ($color = $this->coerceColor($value)) {
+ return $color;
+ }
+ break;
+ case "raw_color":
+ return $this->coerceColor($value);
+ }
+ }
+
+ return $value;
+ }
+
+
+ // coerce a value for use in color operation
+ protected function coerceColor($value) {
+ switch($value[0]) {
+ case 'color': return $value;
+ case 'raw_color':
+ $c = array("color", 0, 0, 0);
+ $colorStr = substr($value[1], 1);
+ $num = hexdec($colorStr);
+ $width = strlen($colorStr) == 3 ? 16 : 256;
+
+ for ($i = 3; $i > 0; $i--) { // 3 2 1
+ $t = $num % $width;
+ $num /= $width;
+
+ $c[$i] = $t * (256/$width) + $t * floor(16/$width);
+ }
+
+ return $c;
+ case 'keyword':
+ $name = $value[1];
+ if (isset(self::$cssColors[$name])) {
+ list($r, $g, $b) = explode(',', self::$cssColors[$name]);
+ return array('color', $r, $g, $b);
+ }
+ return null;
+ }
+ }
+
+ // make something string like into a string
+ protected function coerceString($value) {
+ switch ($value[0]) {
+ case "string":
+ return $value;
+ case "keyword":
+ return array("string", "", array($value[1]));
+ }
+ return null;
+ }
+
+ // turn list of length 1 into value type
+ protected function flattenList($value) {
+ if ($value[0] == "list" && count($value[2]) == 1) {
+ return $this->flattenList($value[2][0]);
+ }
+ return $value;
+ }
+
+ protected function toBool($a) {
+ if ($a) return self::$TRUE;
+ else return self::$FALSE;
+ }
+
+ // evaluate an expression
+ protected function evaluate($exp) {
+ list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp;
+
+ $left = $this->reduce($left, true);
+ $right = $this->reduce($right, true);
+
+ if ($leftColor = $this->coerceColor($left)) {
+ $left = $leftColor;
+ }
+
+ if ($rightColor = $this->coerceColor($right)) {
+ $right = $rightColor;
+ }
+
+ $ltype = $left[0];
+ $rtype = $right[0];
+
+ // operators that work on all types
+ if ($op == "and") {
+ return $this->toBool($left == self::$TRUE && $right == self::$TRUE);
+ }
+
+ if ($op == "=") {
+ return $this->toBool($this->eq($left, $right) );
+ }
+
+ if ($op == "+" && !is_null($str = $this->stringConcatenate($left, $right))) {
+ return $str;
+ }
+
+ // type based operators
+ $fname = "op_${ltype}_${rtype}";
+ if (is_callable(array($this, $fname))) {
+ $out = $this->$fname($op, $left, $right);
+ if (!is_null($out)) return $out;
+ }
+
+ // make the expression look it did before being parsed
+ $paddedOp = $op;
+ if ($whiteBefore) $paddedOp = " " . $paddedOp;
+ if ($whiteAfter) $paddedOp .= " ";
+
+ return array("string", "", array($left, $paddedOp, $right));
+ }
+
+ protected function stringConcatenate($left, $right) {
+ if ($strLeft = $this->coerceString($left)) {
+ if ($right[0] == "string") {
+ $right[1] = "";
+ }
+ $strLeft[2][] = $right;
+ return $strLeft;
+ }
+
+ if ($strRight = $this->coerceString($right)) {
+ array_unshift($strRight[2], $left);
+ return $strRight;
+ }
+ }
+
+
+ // make sure a color's components don't go out of bounds
+ protected function fixColor($c) {
+ foreach (range(1, 3) as $i) {
+ if ($c[$i] < 0) $c[$i] = 0;
+ if ($c[$i] > 255) $c[$i] = 255;
+ }
+
+ return $c;
+ }
+
+ protected function op_number_color($op, $lft, $rgt) {
+ if ($op == '+' || $op == '*') {
+ return $this->op_color_number($op, $rgt, $lft);
+ }
+ }
+
+ protected function op_color_number($op, $lft, $rgt) {
+ if ($rgt[0] == '%') $rgt[1] /= 100;
+
+ return $this->op_color_color($op, $lft,
+ array_fill(1, count($lft) - 1, $rgt[1]));
+ }
+
+ protected function op_color_color($op, $left, $right) {
+ $out = array('color');
+ $max = count($left) > count($right) ? count($left) : count($right);
+ foreach (range(1, $max - 1) as $i) {
+ $lval = isset($left[$i]) ? $left[$i] : 0;
+ $rval = isset($right[$i]) ? $right[$i] : 0;
+ switch ($op) {
+ case '+':
+ $out[] = $lval + $rval;
+ break;
+ case '-':
+ $out[] = $lval - $rval;
+ break;
+ case '*':
+ $out[] = $lval * $rval;
+ break;
+ case '%':
+ $out[] = $lval % $rval;
+ break;
+ case '/':
+ if ($rval == 0) $this->throwError("evaluate error: can't divide by zero");
+ $out[] = $lval / $rval;
+ break;
+ default:
+ $this->throwError('evaluate error: color op number failed on op '.$op);
+ }
+ }
+ return $this->fixColor($out);
+ }
+
+ // operator on two numbers
+ protected function op_number_number($op, $left, $right) {
+ $unit = empty($left[2]) ? $right[2] : $left[2];
+
+ $value = 0;
+ switch ($op) {
+ case '+':
+ $value = $left[1] + $right[1];
+ break;
+ case '*':
+ $value = $left[1] * $right[1];
+ break;
+ case '-':
+ $value = $left[1] - $right[1];
+ break;
+ case '%':
+ $value = $left[1] % $right[1];
+ break;
+ case '/':
+ if ($right[1] == 0) $this->throwError('parse error: divide by zero');
+ $value = $left[1] / $right[1];
+ break;
+ case '<':
+ return $this->toBool($left[1] < $right[1]);
+ case '>':
+ return $this->toBool($left[1] > $right[1]);
+ case '>=':
+ return $this->toBool($left[1] >= $right[1]);
+ case '=<':
+ return $this->toBool($left[1] <= $right[1]);
+ default:
+ $this->throwError('parse error: unknown number operator: '.$op);
+ }
+
+ return array("number", $value, $unit);
+ }
+
+
+ /* environment functions */
+
+ protected function makeOutputBlock($type, $selectors = null) {
+ $b = new stdclass;
+ $b->lines = array();
+ $b->children = array();
+ $b->selectors = $selectors;
+ $b->type = $type;
+ $b->parent = $this->scope;
+ return $b;
+ }
+
+ // the state of execution
+ protected function pushEnv($block = null) {
+ $e = new stdclass;
+ $e->parent = $this->env;
+ $e->store = array();
+ $e->block = $block;
+
+ $this->env = $e;
+ return $e;
+ }
+
+ // pop something off the stack
+ protected function popEnv() {
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ return $old;
+ }
+
+ // set something in the current env
+ protected function set($name, $value) {
+ $this->env->store[$name] = $value;
+ }
+
+
+ // get the highest occurrence entry for a name
+ protected function get($name, $default=null) {
+ $current = $this->env;
+
+ $isArguments = $name == $this->vPrefix . 'arguments';
+ while ($current) {
+ if ($isArguments && isset($current->arguments)) {
+ return array('list', ' ', $current->arguments);
+ }
+
+ if (isset($current->store[$name]))
+ return $current->store[$name];
+ else {
+ $current = isset($current->storeParent) ?
+ $current->storeParent : $current->parent;
+ }
+ }
+
+ return $default;
+ }
+
+ // inject array of unparsed strings into environment as variables
+ protected function injectVariables($args) {
+ $this->pushEnv();
+ $parser = new lessc_parser($this, __METHOD__);
+ foreach ($args as $name => $strValue) {
+ if ($name{0} != '@') $name = '@'.$name;
+ $parser->count = 0;
+ $parser->buffer = (string)$strValue;
+ if (!$parser->propertyValue($value)) {
+ throw new Exception("failed to parse passed in variable $name: $strValue");
+ }
+
+ $this->set($name, $value);
+ }
+ }
+
+ /**
+ * Initialize any static state, can initialize parser for a file
+ * $opts isn't used yet
+ */
+ public function __construct($fname = null) {
+ if ($fname !== null) {
+ // used for deprecated parse method
+ $this->_parseFile = $fname;
+ }
+ }
+
+ public function compile($string, $name = null) {
+ $locale = setlocale(LC_NUMERIC, 0);
+ setlocale(LC_NUMERIC, "C");
+
+ $this->parser = $this->makeParser($name);
+ $root = $this->parser->parse($string);
+
+ $this->env = null;
+ $this->scope = null;
+
+ $this->formatter = $this->newFormatter();
+
+ if (!empty($this->registeredVars)) {
+ $this->injectVariables($this->registeredVars);
+ }
+
+ $this->sourceParser = $this->parser; // used for error messages
+ $this->compileBlock($root);
+
+ ob_start();
+ $this->formatter->block($this->scope);
+ $out = ob_get_clean();
+ setlocale(LC_NUMERIC, $locale);
+ return $out;
+ }
+
+ public function compileFile($fname, $outFname = null) {
+ if (!is_readable($fname)) {
+ throw new Exception('load error: failed to find '.$fname);
+ }
+
+ $pi = pathinfo($fname);
+
+ $oldImport = $this->importDir;
+
+ $this->importDir = (array)$this->importDir;
+ $this->importDir[] = $pi['dirname'].'/';
+
+ $this->allParsedFiles = array();
+ $this->addParsedFile($fname);
+
+ $out = $this->compile(file_get_contents($fname), $fname);
+
+ $this->importDir = $oldImport;
+
+ if ($outFname !== null) {
+ return file_put_contents($outFname, $out);
+ }
+
+ return $out;
+ }
+
+ // compile only if changed input has changed or output doesn't exist
+ public function checkedCompile($in, $out) {
+ if (!is_file($out) || filemtime($in) > filemtime($out)) {
+ $this->compileFile($in, $out);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Execute lessphp on a .less file or a lessphp cache structure
+ *
+ * The lessphp cache structure contains information about a specific
+ * less file having been parsed. It can be used as a hint for future
+ * calls to determine whether or not a rebuild is required.
+ *
+ * The cache structure contains two important keys that may be used
+ * externally:
+ *
+ * compiled: The final compiled CSS
+ * updated: The time (in seconds) the CSS was last compiled
+ *
+ * The cache structure is a plain-ol' PHP associative array and can
+ * be serialized and unserialized without a hitch.
+ *
+ * @param mixed $in Input
+ * @param bool $force Force rebuild?
+ * @return array lessphp cache structure
+ */
+ public function cachedCompile($in, $force = false) {
+ // assume no root
+ $root = null;
+
+ if (is_string($in)) {
+ $root = $in;
+ } elseif (is_array($in) and isset($in['root'])) {
+ if ($force or ! isset($in['files'])) {
+ // If we are forcing a recompile or if for some reason the
+ // structure does not contain any file information we should
+ // specify the root to trigger a rebuild.
+ $root = $in['root'];
+ } elseif (isset($in['files']) and is_array($in['files'])) {
+ foreach ($in['files'] as $fname => $ftime ) {
+ if (!file_exists($fname) or filemtime($fname) > $ftime) {
+ // One of the files we knew about previously has changed
+ // so we should look at our incoming root again.
+ $root = $in['root'];
+ break;
+ }
+ }
+ }
+ } else {
+ // TODO: Throw an exception? We got neither a string nor something
+ // that looks like a compatible lessphp cache structure.
+ return null;
+ }
+
+ if ($root !== null) {
+ // If we have a root value which means we should rebuild.
+ $out = array();
+ $out['root'] = $root;
+ $out['compiled'] = $this->compileFile($root);
+ $out['files'] = $this->allParsedFiles();
+ $out['updated'] = time();
+ return $out;
+ } else {
+ // No changes, pass back the structure
+ // we were given initially.
+ return $in;
+ }
+
+ }
+
+ // parse and compile buffer
+ // This is deprecated
+ public function parse($str = null, $initialVariables = null) {
+ if (is_array($str)) {
+ $initialVariables = $str;
+ $str = null;
+ }
+
+ $oldVars = $this->registeredVars;
+ if ($initialVariables !== null) {
+ $this->setVariables($initialVariables);
+ }
+
+ if ($str == null) {
+ if (empty($this->_parseFile)) {
+ throw new exception("nothing to parse");
+ }
+
+ $out = $this->compileFile($this->_parseFile);
+ } else {
+ $out = $this->compile($str);
+ }
+
+ $this->registeredVars = $oldVars;
+ return $out;
+ }
+
+ protected function makeParser($name) {
+ $parser = new lessc_parser($this, $name);
+ $parser->writeComments = $this->preserveComments;
+
+ return $parser;
+ }
+
+ public function setFormatter($name) {
+ $this->formatterName = $name;
+ }
+
+ protected function newFormatter() {
+ $className = "lessc_formatter_lessjs";
+ if (!empty($this->formatterName)) {
+ if (!is_string($this->formatterName))
+ return $this->formatterName;
+ $className = "lessc_formatter_$this->formatterName";
+ }
+
+ return new $className;
+ }
+
+ public function setPreserveComments($preserve) {
+ $this->preserveComments = $preserve;
+ }
+
+ public function registerFunction($name, $func) {
+ $this->libFunctions[$name] = $func;
+ }
+
+ public function unregisterFunction($name) {
+ unset($this->libFunctions[$name]);
+ }
+
+ public function setVariables($variables) {
+ $this->registeredVars = array_merge($this->registeredVars, $variables);
+ }
+
+ public function unsetVariable($name) {
+ unset($this->registeredVars[$name]);
+ }
+
+ public function setImportDir($dirs) {
+ $this->importDir = (array)$dirs;
+ }
+
+ public function addImportDir($dir) {
+ $this->importDir = (array)$this->importDir;
+ $this->importDir[] = $dir;
+ }
+
+ public function allParsedFiles() {
+ return $this->allParsedFiles;
+ }
+
+ protected function addParsedFile($file) {
+ $this->allParsedFiles[realpath($file)] = filemtime($file);
+ }
+
+ /**
+ * Uses the current value of $this->count to show line and line number
+ */
+ protected function throwError($msg = null) {
+ if ($this->sourceLoc >= 0) {
+ $this->sourceParser->throwError($msg, $this->sourceLoc);
+ }
+ throw new exception($msg);
+ }
+
+ // compile file $in to file $out if $in is newer than $out
+ // returns true when it compiles, false otherwise
+ public static function ccompile($in, $out, $less = null) {
+ if ($less === null) {
+ $less = new self;
+ }
+ return $less->checkedCompile($in, $out);
+ }
+
+ public static function cexecute($in, $force = false, $less = null) {
+ if ($less === null) {
+ $less = new self;
+ }
+ return $less->cachedCompile($in, $force);
+ }
+
+ static protected $cssColors = array(
+ 'aliceblue' => '240,248,255',
+ 'antiquewhite' => '250,235,215',
+ 'aqua' => '0,255,255',
+ 'aquamarine' => '127,255,212',
+ 'azure' => '240,255,255',
+ 'beige' => '245,245,220',
+ 'bisque' => '255,228,196',
+ 'black' => '0,0,0',
+ 'blanchedalmond' => '255,235,205',
+ 'blue' => '0,0,255',
+ 'blueviolet' => '138,43,226',
+ 'brown' => '165,42,42',
+ 'burlywood' => '222,184,135',
+ 'cadetblue' => '95,158,160',
+ 'chartreuse' => '127,255,0',
+ 'chocolate' => '210,105,30',
+ 'coral' => '255,127,80',
+ 'cornflowerblue' => '100,149,237',
+ 'cornsilk' => '255,248,220',
+ 'crimson' => '220,20,60',
+ 'cyan' => '0,255,255',
+ 'darkblue' => '0,0,139',
+ 'darkcyan' => '0,139,139',
+ 'darkgoldenrod' => '184,134,11',
+ 'darkgray' => '169,169,169',
+ 'darkgreen' => '0,100,0',
+ 'darkgrey' => '169,169,169',
+ 'darkkhaki' => '189,183,107',
+ 'darkmagenta' => '139,0,139',
+ 'darkolivegreen' => '85,107,47',
+ 'darkorange' => '255,140,0',
+ 'darkorchid' => '153,50,204',
+ 'darkred' => '139,0,0',
+ 'darksalmon' => '233,150,122',
+ 'darkseagreen' => '143,188,143',
+ 'darkslateblue' => '72,61,139',
+ 'darkslategray' => '47,79,79',
+ 'darkslategrey' => '47,79,79',
+ 'darkturquoise' => '0,206,209',
+ 'darkviolet' => '148,0,211',
+ 'deeppink' => '255,20,147',
+ 'deepskyblue' => '0,191,255',
+ 'dimgray' => '105,105,105',
+ 'dimgrey' => '105,105,105',
+ 'dodgerblue' => '30,144,255',
+ 'firebrick' => '178,34,34',
+ 'floralwhite' => '255,250,240',
+ 'forestgreen' => '34,139,34',
+ 'fuchsia' => '255,0,255',
+ 'gainsboro' => '220,220,220',
+ 'ghostwhite' => '248,248,255',
+ 'gold' => '255,215,0',
+ 'goldenrod' => '218,165,32',
+ 'gray' => '128,128,128',
+ 'green' => '0,128,0',
+ 'greenyellow' => '173,255,47',
+ 'grey' => '128,128,128',
+ 'honeydew' => '240,255,240',
+ 'hotpink' => '255,105,180',
+ 'indianred' => '205,92,92',
+ 'indigo' => '75,0,130',
+ 'ivory' => '255,255,240',
+ 'khaki' => '240,230,140',
+ 'lavender' => '230,230,250',
+ 'lavenderblush' => '255,240,245',
+ 'lawngreen' => '124,252,0',
+ 'lemonchiffon' => '255,250,205',
+ 'lightblue' => '173,216,230',
+ 'lightcoral' => '240,128,128',
+ 'lightcyan' => '224,255,255',
+ 'lightgoldenrodyellow' => '250,250,210',
+ 'lightgray' => '211,211,211',
+ 'lightgreen' => '144,238,144',
+ 'lightgrey' => '211,211,211',
+ 'lightpink' => '255,182,193',
+ 'lightsalmon' => '255,160,122',
+ 'lightseagreen' => '32,178,170',
+ 'lightskyblue' => '135,206,250',
+ 'lightslategray' => '119,136,153',
+ 'lightslategrey' => '119,136,153',
+ 'lightsteelblue' => '176,196,222',
+ 'lightyellow' => '255,255,224',
+ 'lime' => '0,255,0',
+ 'limegreen' => '50,205,50',
+ 'linen' => '250,240,230',
+ 'magenta' => '255,0,255',
+ 'maroon' => '128,0,0',
+ 'mediumaquamarine' => '102,205,170',
+ 'mediumblue' => '0,0,205',
+ 'mediumorchid' => '186,85,211',
+ 'mediumpurple' => '147,112,219',
+ 'mediumseagreen' => '60,179,113',
+ 'mediumslateblue' => '123,104,238',
+ 'mediumspringgreen' => '0,250,154',
+ 'mediumturquoise' => '72,209,204',
+ 'mediumvioletred' => '199,21,133',
+ 'midnightblue' => '25,25,112',
+ 'mintcream' => '245,255,250',
+ 'mistyrose' => '255,228,225',
+ 'moccasin' => '255,228,181',
+ 'navajowhite' => '255,222,173',
+ 'navy' => '0,0,128',
+ 'oldlace' => '253,245,230',
+ 'olive' => '128,128,0',
+ 'olivedrab' => '107,142,35',
+ 'orange' => '255,165,0',
+ 'orangered' => '255,69,0',
+ 'orchid' => '218,112,214',
+ 'palegoldenrod' => '238,232,170',
+ 'palegreen' => '152,251,152',
+ 'paleturquoise' => '175,238,238',
+ 'palevioletred' => '219,112,147',
+ 'papayawhip' => '255,239,213',
+ 'peachpuff' => '255,218,185',
+ 'peru' => '205,133,63',
+ 'pink' => '255,192,203',
+ 'plum' => '221,160,221',
+ 'powderblue' => '176,224,230',
+ 'purple' => '128,0,128',
+ 'red' => '255,0,0',
+ 'rosybrown' => '188,143,143',
+ 'royalblue' => '65,105,225',
+ 'saddlebrown' => '139,69,19',
+ 'salmon' => '250,128,114',
+ 'sandybrown' => '244,164,96',
+ 'seagreen' => '46,139,87',
+ 'seashell' => '255,245,238',
+ 'sienna' => '160,82,45',
+ 'silver' => '192,192,192',
+ 'skyblue' => '135,206,235',
+ 'slateblue' => '106,90,205',
+ 'slategray' => '112,128,144',
+ 'slategrey' => '112,128,144',
+ 'snow' => '255,250,250',
+ 'springgreen' => '0,255,127',
+ 'steelblue' => '70,130,180',
+ 'tan' => '210,180,140',
+ 'teal' => '0,128,128',
+ 'thistle' => '216,191,216',
+ 'tomato' => '255,99,71',
+ 'turquoise' => '64,224,208',
+ 'violet' => '238,130,238',
+ 'wheat' => '245,222,179',
+ 'white' => '255,255,255',
+ 'whitesmoke' => '245,245,245',
+ 'yellow' => '255,255,0',
+ 'yellowgreen' => '154,205,50'
+ );
+}
+
+// responsible for taking a string of LESS code and converting it into a
+// syntax tree
+class lessc_parser {
+ static protected $nextBlockId = 0; // used to uniquely identify blocks
+
+ static protected $precedence = array(
+ '=<' => 0,
+ '>=' => 0,
+ '=' => 0,
+ '<' => 0,
+ '>' => 0,
+
+ '+' => 1,
+ '-' => 1,
+ '*' => 2,
+ '/' => 2,
+ '%' => 2,
+ );
+
+ static protected $whitePattern;
+ static protected $commentMulti;
+
+ static protected $commentSingle = "//";
+ static protected $commentMultiLeft = "/*";
+ static protected $commentMultiRight = "*/";
+
+ // regex string to match any of the operators
+ static protected $operatorString;
+
+ // these properties will supress division unless it's inside parenthases
+ static protected $supressDivisionProps =
+ array('/border-radius$/i', '/^font$/i');
+
+ protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document");
+ protected $lineDirectives = array("charset");
+
+ /**
+ * if we are in parens we can be more liberal with whitespace around
+ * operators because it must evaluate to a single value and thus is less
+ * ambiguous.
+ *
+ * Consider:
+ * property1: 10 -5; // is two numbers, 10 and -5
+ * property2: (10 -5); // should evaluate to 5
+ */
+ protected $inParens = false;
+
+ // caches preg escaped literals
+ static protected $literalCache = array();
+
+ public function __construct($lessc, $sourceName = null) {
+ $this->eatWhiteDefault = true;
+ // reference to less needed for vPrefix, mPrefix, and parentSelector
+ $this->lessc = $lessc;
+
+ $this->sourceName = $sourceName; // name used for error messages
+
+ $this->writeComments = false;
+
+ if (!self::$operatorString) {
+ self::$operatorString =
+ '('.implode('|', array_map(array('lessc', 'preg_quote'),
+ array_keys(self::$precedence))).')';
+
+ $commentSingle = lessc::preg_quote(self::$commentSingle);
+ $commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft);
+ $commentMultiRight = lessc::preg_quote(self::$commentMultiRight);
+
+ self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
+ self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
+ }
+ }
+
+ public function parse($buffer) {
+ $this->count = 0;
+ $this->line = 1;
+
+ $this->env = null; // block stack
+ $this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer);
+ $this->pushSpecialBlock("root");
+ $this->eatWhiteDefault = true;
+ $this->seenComments = array();
+
+ // trim whitespace on head
+ // if (preg_match('/^\s+/', $this->buffer, $m)) {
+ // $this->line += substr_count($m[0], "\n");
+ // $this->buffer = ltrim($this->buffer);
+ // }
+ $this->whitespace();
+
+ // parse the entire file
+ $lastCount = $this->count;
+ while (false !== $this->parseChunk());
+
+ if ($this->count != strlen($this->buffer))
+ $this->throwError();
+
+ // TODO report where the block was opened
+ if (!is_null($this->env->parent))
+ throw new exception('parse error: unclosed block');
+
+ return $this->env;
+ }
+
+ /**
+ * Parse a single chunk off the head of the buffer and append it to the
+ * current parse environment.
+ * Returns false when the buffer is empty, or when there is an error.
+ *
+ * This function is called repeatedly until the entire document is
+ * parsed.
+ *
+ * This parser is most similar to a recursive descent parser. Single
+ * functions represent discrete grammatical rules for the language, and
+ * they are able to capture the text that represents those rules.
+ *
+ * Consider the function lessc::keyword(). (all parse functions are
+ * structured the same)
+ *
+ * The function takes a single reference argument. When calling the
+ * function it will attempt to match a keyword on the head of the buffer.
+ * If it is successful, it will place the keyword in the referenced
+ * argument, advance the position in the buffer, and return true. If it
+ * fails then it won't advance the buffer and it will return false.
+ *
+ * All of these parse functions are powered by lessc::match(), which behaves
+ * the same way, but takes a literal regular expression. Sometimes it is
+ * more convenient to use match instead of creating a new function.
+ *
+ * Because of the format of the functions, to parse an entire string of
+ * grammatical rules, you can chain them together using &&.
+ *
+ * But, if some of the rules in the chain succeed before one fails, then
+ * the buffer position will be left at an invalid state. In order to
+ * avoid this, lessc::seek() is used to remember and set buffer positions.
+ *
+ * Before parsing a chain, use $s = $this->seek() to remember the current
+ * position into $s. Then if a chain fails, use $this->seek($s) to
+ * go back where we started.
+ */
+ protected function parseChunk() {
+ if (empty($this->buffer)) return false;
+ $s = $this->seek();
+
+ // setting a property
+ if ($this->keyword($key) && $this->assign() &&
+ $this->propertyValue($value, $key) && $this->end())
+ {
+ $this->append(array('assign', $key, $value), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+
+ // look for special css blocks
+ if ($this->literal('@', false)) {
+ $this->count--;
+
+ // media
+ if ($this->literal('@media')) {
+ if (($this->mediaQueryList($mediaQueries) || true)
+ && $this->literal('{'))
+ {
+ $media = $this->pushSpecialBlock("media");
+ $media->queries = is_null($mediaQueries) ? array() : $mediaQueries;
+ return true;
+ } else {
+ $this->seek($s);
+ return false;
+ }
+ }
+
+ if ($this->literal("@", false) && $this->keyword($dirName)) {
+ if ($this->isDirective($dirName, $this->blockDirectives)) {
+ if (($this->openString("{", $dirValue, null, array(";")) || true) &&
+ $this->literal("{"))
+ {
+ $dir = $this->pushSpecialBlock("directive");
+ $dir->name = $dirName;
+ if (isset($dirValue)) $dir->value = $dirValue;
+ return true;
+ }
+ } elseif ($this->isDirective($dirName, $this->lineDirectives)) {
+ if ($this->propertyValue($dirValue) && $this->end()) {
+ $this->append(array("directive", $dirName, $dirValue));
+ return true;
+ }
+ }
+ }
+
+ $this->seek($s);
+ }
+
+ // setting a variable
+ if ($this->variable($var) && $this->assign() &&
+ $this->propertyValue($value) && $this->end())
+ {
+ $this->append(array('assign', $var, $value), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->import($importValue)) {
+ $this->append($importValue, $s);
+ return true;
+ }
+
+ // opening parametric mixin
+ if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) &&
+ ($this->guards($guards) || true) &&
+ $this->literal('{'))
+ {
+ $block = $this->pushBlock($this->fixTags(array($tag)));
+ $block->args = $args;
+ $block->isVararg = $isVararg;
+ if (!empty($guards)) $block->guards = $guards;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // opening a simple block
+ if ($this->tags($tags) && $this->literal('{')) {
+ $tags = $this->fixTags($tags);
+ $this->pushBlock($tags);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // closing a block
+ if ($this->literal('}', false)) {
+ try {
+ $block = $this->pop();
+ } catch (exception $e) {
+ $this->seek($s);
+ $this->throwError($e->getMessage());
+ }
+
+ $hidden = false;
+ if (is_null($block->type)) {
+ $hidden = true;
+ if (!isset($block->args)) {
+ foreach ($block->tags as $tag) {
+ if (!is_string($tag) || $tag{0} != $this->lessc->mPrefix) {
+ $hidden = false;
+ break;
+ }
+ }
+ }
+
+ foreach ($block->tags as $tag) {
+ if (is_string($tag)) {
+ $this->env->children[$tag][] = $block;
+ }
+ }
+ }
+
+ if (!$hidden) {
+ $this->append(array('block', $block), $s);
+ }
+
+ // this is done here so comments aren't bundled into he block that
+ // was just closed
+ $this->whitespace();
+ return true;
+ }
+
+ // mixin
+ if ($this->mixinTags($tags) &&
+ ($this->argumentValues($argv) || true) &&
+ ($this->keyword($suffix) || true) && $this->end())
+ {
+ $tags = $this->fixTags($tags);
+ $this->append(array('mixin', $tags, $argv, $suffix), $s);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // spare ;
+ if ($this->literal(';')) return true;
+
+ return false; // got nothing, throw error
+ }
+
+ protected function isDirective($dirname, $directives) {
+ // TODO: cache pattern in parser
+ $pattern = implode("|",
+ array_map(array("lessc", "preg_quote"), $directives));
+ $pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i';
+
+ return preg_match($pattern, $dirname);
+ }
+
+ protected function fixTags($tags) {
+ // move @ tags out of variable namespace
+ foreach ($tags as &$tag) {
+ if ($tag{0} == $this->lessc->vPrefix)
+ $tag[0] = $this->lessc->mPrefix;
+ }
+ return $tags;
+ }
+
+ // a list of expressions
+ protected function expressionList(&$exps) {
+ $values = array();
+
+ while ($this->expression($exp)) {
+ $values[] = $exp;
+ }
+
+ if (count($values) == 0) return false;
+
+ $exps = lessc::compressList($values, ' ');
+ return true;
+ }
+
+ /**
+ * Attempt to consume an expression.
+ * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code
+ */
+ protected function expression(&$out) {
+ if ($this->value($lhs)) {
+ $out = $this->expHelper($lhs, 0);
+
+ // look for / shorthand
+ if (!empty($this->env->supressedDivision)) {
+ unset($this->env->supressedDivision);
+ $s = $this->seek();
+ if ($this->literal("/") && $this->value($rhs)) {
+ $out = array("list", "",
+ array($out, array("keyword", "/"), $rhs));
+ } else {
+ $this->seek($s);
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * recursively parse infix equation with $lhs at precedence $minP
+ */
+ protected function expHelper($lhs, $minP) {
+ $this->inExp = true;
+ $ss = $this->seek();
+
+ while (true) {
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ // If there is whitespace before the operator, then we require
+ // whitespace after the operator for it to be an expression
+ $needWhite = $whiteBefore && !$this->inParens;
+
+ if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) {
+ if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) {
+ foreach (self::$supressDivisionProps as $pattern) {
+ if (preg_match($pattern, $this->env->currentProperty)) {
+ $this->env->supressedDivision = true;
+ break 2;
+ }
+ }
+ }
+
+
+ $whiteAfter = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ if (!$this->value($rhs)) break;
+
+ // peek for next operator to see what to do with rhs
+ if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) {
+ $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
+ }
+
+ $lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter);
+ $ss = $this->seek();
+
+ continue;
+ }
+
+ break;
+ }
+
+ $this->seek($ss);
+
+ return $lhs;
+ }
+
+ // consume a list of values for a property
+ public function propertyValue(&$value, $keyName = null) {
+ $values = array();
+
+ if ($keyName !== null) $this->env->currentProperty = $keyName;
+
+ $s = null;
+ while ($this->expressionList($v)) {
+ $values[] = $v;
+ $s = $this->seek();
+ if (!$this->literal(',')) break;
+ }
+
+ if ($s) $this->seek($s);
+
+ if ($keyName !== null) unset($this->env->currentProperty);
+
+ if (count($values) == 0) return false;
+
+ $value = lessc::compressList($values, ', ');
+ return true;
+ }
+
+ protected function parenValue(&$out) {
+ $s = $this->seek();
+
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") {
+ return false;
+ }
+
+ $inParens = $this->inParens;
+ if ($this->literal("(") &&
+ ($this->inParens = true) && $this->expression($exp) &&
+ $this->literal(")"))
+ {
+ $out = $exp;
+ $this->inParens = $inParens;
+ return true;
+ } else {
+ $this->inParens = $inParens;
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ // a single value
+ protected function value(&$value) {
+ $s = $this->seek();
+
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") {
+ // negation
+ if ($this->literal("-", false) &&
+ (($this->variable($inner) && $inner = array("variable", $inner)) ||
+ $this->unit($inner) ||
+ $this->parenValue($inner)))
+ {
+ $value = array("unary", "-", $inner);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+ }
+
+ if ($this->parenValue($value)) return true;
+ if ($this->unit($value)) return true;
+ if ($this->color($value)) return true;
+ if ($this->func($value)) return true;
+ if ($this->string($value)) return true;
+
+ if ($this->keyword($word)) {
+ $value = array('keyword', $word);
+ return true;
+ }
+
+ // try a variable
+ if ($this->variable($var)) {
+ $value = array('variable', $var);
+ return true;
+ }
+
+ // unquote string (should this work on any type?
+ if ($this->literal("~") && $this->string($str)) {
+ $value = array("escape", $str);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // css hack: \0
+ if ($this->literal('\\') && $this->match('([0-9]+)', $m)) {
+ $value = array('keyword', '\\'.$m[1]);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ // an import statement
+ protected function import(&$out) {
+ $s = $this->seek();
+ if (!$this->literal('@import')) return false;
+
+ // @import "something.css" media;
+ // @import url("something.css") media;
+ // @import url(something.css) media;
+
+ if ($this->propertyValue($value)) {
+ $out = array("import", $value);
+ return true;
+ }
+ }
+
+ protected function mediaQueryList(&$out) {
+ if ($this->genericList($list, "mediaQuery", ",", false)) {
+ $out = $list[2];
+ return true;
+ }
+ return false;
+ }
+
+ protected function mediaQuery(&$out) {
+ $s = $this->seek();
+
+ $expressions = null;
+ $parts = array();
+
+ if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) {
+ $prop = array("mediaType");
+ if (isset($only)) $prop[] = "only";
+ if (isset($not)) $prop[] = "not";
+ $prop[] = $mediaType;
+ $parts[] = $prop;
+ } else {
+ $this->seek($s);
+ }
+
+
+ if (!empty($mediaType) && !$this->literal("and")) {
+ // ~
+ } else {
+ $this->genericList($expressions, "mediaExpression", "and", false);
+ if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
+ }
+
+ if (count($parts) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function mediaExpression(&$out) {
+ $s = $this->seek();
+ $value = null;
+ if ($this->literal("(") &&
+ $this->keyword($feature) &&
+ ($this->literal(":") && $this->expression($value) || true) &&
+ $this->literal(")"))
+ {
+ $out = array("mediaExp", $feature);
+ if ($value) $out[] = $value;
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // an unbounded string stopped by $end
+ protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $stop = array("'", '"', "@{", $end);
+ $stop = array_map(array("lessc", "preg_quote"), $stop);
+ // $stop[] = self::$commentMulti;
+
+ if (!is_null($rejectStrs)) {
+ $stop = array_merge($stop, $rejectStrs);
+ }
+
+ $patt = '(.*?)('.implode("|", $stop).')';
+
+ $nestingLevel = 0;
+
+ $content = array();
+ while ($this->match($patt, $m, false)) {
+ if (!empty($m[1])) {
+ $content[] = $m[1];
+ if ($nestingOpen) {
+ $nestingLevel += substr_count($m[1], $nestingOpen);
+ }
+ }
+
+ $tok = $m[2];
+
+ $this->count-= strlen($tok);
+ if ($tok == $end) {
+ if ($nestingLevel == 0) {
+ break;
+ } else {
+ $nestingLevel--;
+ }
+ }
+
+ if (($tok == "'" || $tok == '"') && $this->string($str)) {
+ $content[] = $str;
+ continue;
+ }
+
+ if ($tok == "@{" && $this->interpolation($inter)) {
+ $content[] = $inter;
+ continue;
+ }
+
+ if (in_array($tok, $rejectStrs)) {
+ $count = null;
+ break;
+ }
+
+
+ $content[] = $tok;
+ $this->count+= strlen($tok);
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($content) == 0) return false;
+
+ // trim the end
+ if (is_string(end($content))) {
+ $content[count($content) - 1] = rtrim(end($content));
+ }
+
+ $out = array("string", "", $content);
+ return true;
+ }
+
+ protected function string(&$out) {
+ $s = $this->seek();
+ if ($this->literal('"', false)) {
+ $delim = '"';
+ } elseif ($this->literal("'", false)) {
+ $delim = "'";
+ } else {
+ return false;
+ }
+
+ $content = array();
+
+ // look for either ending delim , escape, or string interpolation
+ $patt = '([^\n]*?)(@\{|\\\\|' .
+ lessc::preg_quote($delim).')';
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while ($this->match($patt, $m, false)) {
+ $content[] = $m[1];
+ if ($m[2] == "@{") {
+ $this->count -= strlen($m[2]);
+ if ($this->interpolation($inter, false)) {
+ $content[] = $inter;
+ } else {
+ $this->count += strlen($m[2]);
+ $content[] = "@{"; // ignore it
+ }
+ } elseif ($m[2] == '\\') {
+ $content[] = $m[2];
+ if ($this->literal($delim, false)) {
+ $content[] = $delim;
+ }
+ } else {
+ $this->count -= strlen($delim);
+ break; // delim
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if ($this->literal($delim)) {
+ $out = array("string", $delim, $content);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function interpolation(&$out) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = true;
+
+ $s = $this->seek();
+ if ($this->literal("@{") &&
+ $this->keyword($var) &&
+ $this->literal("}", false))
+ {
+ $out = array("variable", $this->lessc->vPrefix . $var);
+ $this->eatWhiteDefault = $oldWhite;
+ if ($this->eatWhiteDefault) $this->whitespace();
+ return true;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+ $this->seek($s);
+ return false;
+ }
+
+ protected function unit(&$unit) {
+ // speed shortcut
+ if (isset($this->buffer[$this->count])) {
+ $char = $this->buffer[$this->count];
+ if (!ctype_digit($char) && $char != ".") return false;
+ }
+
+ if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) {
+ $unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]);
+ return true;
+ }
+ return false;
+ }
+
+ // a # color
+ protected function color(&$out) {
+ if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) {
+ if (strlen($m[1]) > 7) {
+ $out = array("string", "", array($m[1]));
+ } else {
+ $out = array("raw_color", $m[1]);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ // consume a list of property values delimited by ; and wrapped in ()
+ protected function argumentValues(&$args, $delim = ',') {
+ $s = $this->seek();
+ if (!$this->literal('(')) return false;
+
+ $values = array();
+ while (true) {
+ if ($this->expressionList($value)) $values[] = $value;
+ if (!$this->literal($delim)) break;
+ else {
+ if ($value == null) $values[] = null;
+ $value = null;
+ }
+ }
+
+ if (!$this->literal(')')) {
+ $this->seek($s);
+ return false;
+ }
+
+ $args = $values;
+ return true;
+ }
+
+ // consume an argument definition list surrounded by ()
+ // each argument is a variable name with optional value
+ // or at the end a ... or a variable named followed by ...
+ protected function argumentDef(&$args, &$isVararg, $delim = ',') {
+ $s = $this->seek();
+ if (!$this->literal('(')) return false;
+
+ $values = array();
+
+ $isVararg = false;
+ while (true) {
+ if ($this->literal("...")) {
+ $isVararg = true;
+ break;
+ }
+
+ if ($this->variable($vname)) {
+ $arg = array("arg", $vname);
+ $ss = $this->seek();
+ if ($this->assign() && $this->expressionList($value)) {
+ $arg[] = $value;
+ } else {
+ $this->seek($ss);
+ if ($this->literal("...")) {
+ $arg[0] = "rest";
+ $isVararg = true;
+ }
+ }
+ $values[] = $arg;
+ if ($isVararg) break;
+ continue;
+ }
+
+ if ($this->value($literal)) {
+ $values[] = array("lit", $literal);
+ }
+
+ if (!$this->literal($delim)) break;
+ }
+
+ if (!$this->literal(')')) {
+ $this->seek($s);
+ return false;
+ }
+
+ $args = $values;
+
+ return true;
+ }
+
+ // consume a list of tags
+ // this accepts a hanging delimiter
+ protected function tags(&$tags, $simple = false, $delim = ',') {
+ $tags = array();
+ while ($this->tag($tt, $simple)) {
+ $tags[] = $tt;
+ if (!$this->literal($delim)) break;
+ }
+ if (count($tags) == 0) return false;
+
+ return true;
+ }
+
+ // list of tags of specifying mixin path
+ // optionally separated by > (lazy, accepts extra >)
+ protected function mixinTags(&$tags) {
+ $s = $this->seek();
+ $tags = array();
+ while ($this->tag($tt, true)) {
+ $tags[] = $tt;
+ $this->literal(">");
+ }
+
+ if (count($tags) == 0) return false;
+
+ return true;
+ }
+
+ // a bracketed value (contained within in a tag definition)
+ protected function tagBracket(&$value) {
+ // speed shortcut
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") {
+ return false;
+ }
+
+ $s = $this->seek();
+ if ($this->literal('[') && $this->to(']', $c, true) && $this->literal(']', false)) {
+ $value = '['.$c.']';
+ // whitespace?
+ if ($this->whitespace()) $value .= " ";
+
+ // escape parent selector, (yuck)
+ $value = str_replace($this->lessc->parentSelector, "$&$", $value);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function tagExpression(&$value) {
+ $s = $this->seek();
+ if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
+ $value = array('exp', $exp);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // a single tag
+ protected function tag(&$tag, $simple = false) {
+ if ($simple)
+ $chars = '^,:;{}\][>\(\) "\'';
+ else
+ $chars = '^,;{}["\'';
+
+ if (!$simple && $this->tagExpression($tag)) {
+ return true;
+ }
+
+ $tag = '';
+ while ($this->tagBracket($first)) $tag .= $first;
+
+ while (true) {
+ if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) {
+ $tag .= $m[1];
+ if ($simple) break;
+
+ while ($this->tagBracket($brack)) $tag .= $brack;
+ continue;
+ } elseif ($this->unit($unit)) { // for keyframes
+ $tag .= $unit[1] . $unit[2];
+ continue;
+ }
+ break;
+ }
+
+
+ $tag = trim($tag);
+ if ($tag == '') return false;
+
+ return true;
+ }
+
+ // a css function
+ protected function func(&$func) {
+ $s = $this->seek();
+
+ if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) {
+ $fname = $m[1];
+
+ $sPreArgs = $this->seek();
+
+ $args = array();
+ while (true) {
+ $ss = $this->seek();
+ // this ugly nonsense is for ie filter properties
+ if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) {
+ $args[] = array("string", "", array($name, "=", $value));
+ } else {
+ $this->seek($ss);
+ if ($this->expressionList($value)) {
+ $args[] = $value;
+ }
+ }
+
+ if (!$this->literal(',')) break;
+ }
+ $args = array('list', ',', $args);
+
+ if ($this->literal(')')) {
+ $func = array('function', $fname, $args);
+ return true;
+ } elseif ($fname == 'url') {
+ // couldn't parse and in url? treat as string
+ $this->seek($sPreArgs);
+ if ($this->openString(")", $string) && $this->literal(")")) {
+ $func = array('function', $fname, $string);
+ return true;
+ }
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // consume a less variable
+ protected function variable(&$name) {
+ $s = $this->seek();
+ if ($this->literal($this->lessc->vPrefix, false) &&
+ ($this->variable($sub) || $this->keyword($name)))
+ {
+ if (!empty($sub)) {
+ $name = array('variable', $sub);
+ } else {
+ $name = $this->lessc->vPrefix.$name;
+ }
+ return true;
+ }
+
+ $name = null;
+ $this->seek($s);
+ return false;
+ }
+
+ /**
+ * Consume an assignment operator
+ * Can optionally take a name that will be set to the current property name
+ */
+ protected function assign($name = null) {
+ if ($name) $this->currentProperty = $name;
+ return $this->literal(':') || $this->literal('=');
+ }
+
+ // consume a keyword
+ protected function keyword(&$word) {
+ if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) {
+ $word = $m[1];
+ return true;
+ }
+ return false;
+ }
+
+ // consume an end of statement delimiter
+ protected function end() {
+ if ($this->literal(';')) {
+ return true;
+ } elseif ($this->count == strlen($this->buffer) || $this->buffer{$this->count} == '}') {
+ // if there is end of file or a closing block next then we don't need a ;
+ return true;
+ }
+ return false;
+ }
+
+ protected function guards(&$guards) {
+ $s = $this->seek();
+
+ if (!$this->literal("when")) {
+ $this->seek($s);
+ return false;
+ }
+
+ $guards = array();
+
+ while ($this->guardGroup($g)) {
+ $guards[] = $g;
+ if (!$this->literal(",")) break;
+ }
+
+ if (count($guards) == 0) {
+ $guards = null;
+ $this->seek($s);
+ return false;
+ }
+
+ return true;
+ }
+
+ // a bunch of guards that are and'd together
+ // TODO rename to guardGroup
+ protected function guardGroup(&$guardGroup) {
+ $s = $this->seek();
+ $guardGroup = array();
+ while ($this->guard($guard)) {
+ $guardGroup[] = $guard;
+ if (!$this->literal("and")) break;
+ }
+
+ if (count($guardGroup) == 0) {
+ $guardGroup = null;
+ $this->seek($s);
+ return false;
+ }
+
+ return true;
+ }
+
+ protected function guard(&$guard) {
+ $s = $this->seek();
+ $negate = $this->literal("not");
+
+ if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) {
+ $guard = $exp;
+ if ($negate) $guard = array("negate", $guard);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ /* raw parsing functions */
+
+ protected function literal($what, $eatWhitespace = null) {
+ if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
+
+ // shortcut on single letter
+ if (!isset($what[1]) && isset($this->buffer[$this->count])) {
+ if ($this->buffer[$this->count] == $what) {
+ if (!$eatWhitespace) {
+ $this->count++;
+ return true;
+ }
+ // goes below...
+ } else {
+ return false;
+ }
+ }
+
+ if (!isset(self::$literalCache[$what])) {
+ self::$literalCache[$what] = lessc::preg_quote($what);
+ }
+
+ return $this->match(self::$literalCache[$what], $m, $eatWhitespace);
+ }
+
+ protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
+ $s = $this->seek();
+ $items = array();
+ while ($this->$parseItem($value)) {
+ $items[] = $value;
+ if ($delim) {
+ if (!$this->literal($delim)) break;
+ }
+ }
+
+ if (count($items) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ if ($flatten && count($items) == 1) {
+ $out = $items[0];
+ } else {
+ $out = array("list", $delim, $items);
+ }
+
+ return true;
+ }
+
+
+ // advance counter to next occurrence of $what
+ // $until - don't include $what in advance
+ // $allowNewline, if string, will be used as valid char set
+ protected function to($what, &$out, $until = false, $allowNewline = false) {
+ if (is_string($allowNewline)) {
+ $validChars = $allowNewline;
+ } else {
+ $validChars = $allowNewline ? "." : "[^\n]";
+ }
+ if (!$this->match('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false;
+ if ($until) $this->count -= strlen($what); // give back $what
+ $out = $m[1];
+ return true;
+ }
+
+ // try to match something on head of buffer
+ protected function match($regex, &$out, $eatWhitespace = null) {
+ if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault;
+
+ $r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais';
+ if (preg_match($r, $this->buffer, $out, null, $this->count)) {
+ $this->count += strlen($out[0]);
+ if ($eatWhitespace && $this->writeComments) $this->whitespace();
+ return true;
+ }
+ return false;
+ }
+
+ // match some whitespace
+ protected function whitespace() {
+ if ($this->writeComments) {
+ $gotWhite = false;
+ while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
+ if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
+ $this->append(array("comment", $m[1]));
+ $this->commentsSeen[$this->count] = true;
+ }
+ $this->count += strlen($m[0]);
+ $gotWhite = true;
+ }
+ return $gotWhite;
+ } else {
+ $this->match("", $m);
+ return strlen($m[0]) > 0;
+ }
+ }
+
+ // match something without consuming it
+ protected function peek($regex, &$out = null, $from=null) {
+ if (is_null($from)) $from = $this->count;
+ $r = '/'.$regex.'/Ais';
+ $result = preg_match($r, $this->buffer, $out, null, $from);
+
+ return $result;
+ }
+
+ // seek to a spot in the buffer or return where we are on no argument
+ protected function seek($where = null) {
+ if ($where === null) return $this->count;
+ else $this->count = $where;
+ return true;
+ }
+
+ /* misc functions */
+
+ public function throwError($msg = "parse error", $count = null) {
+ $count = is_null($count) ? $this->count : $count;
+
+ $line = $this->line +
+ substr_count(substr($this->buffer, 0, $count), "\n");
+
+ if (!empty($this->sourceName)) {
+ $loc = "$this->sourceName on line $line";
+ } else {
+ $loc = "line: $line";
+ }
+
+ // TODO this depends on $this->count
+ if ($this->peek("(.*?)(\n|$)", $m, $count)) {
+ throw new exception("$msg: failed at `$m[1]` $loc");
+ } else {
+ throw new exception("$msg: $loc");
+ }
+ }
+
+ protected function pushBlock($selectors=null, $type=null) {
+ $b = new stdclass;
+ $b->parent = $this->env;
+
+ $b->type = $type;
+ $b->id = self::$nextBlockId++;
+
+ $b->isVararg = false; // TODO: kill me from here
+ $b->tags = $selectors;
+
+ $b->props = array();
+ $b->children = array();
+
+ $this->env = $b;
+ return $b;
+ }
+
+ // push a block that doesn't multiply tags
+ protected function pushSpecialBlock($type) {
+ return $this->pushBlock(null, $type);
+ }
+
+ // append a property to the current block
+ protected function append($prop, $pos = null) {
+ if ($pos !== null) $prop[-1] = $pos;
+ $this->env->props[] = $prop;
+ }
+
+ // pop something off the stack
+ protected function pop() {
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ return $old;
+ }
+
+ // remove comments from $text
+ // todo: make it work for all functions, not just url
+ protected function removeComments($text) {
+ $look = array(
+ 'url(', '//', '/*', '"', "'"
+ );
+
+ $out = '';
+ $min = null;
+ while (true) {
+ // find the next item
+ foreach ($look as $token) {
+ $pos = strpos($text, $token);
+ if ($pos !== false) {
+ if (!isset($min) || $pos < $min[1]) $min = array($token, $pos);
+ }
+ }
+
+ if (is_null($min)) break;
+
+ $count = $min[1];
+ $skip = 0;
+ $newlines = 0;
+ switch ($min[0]) {
+ case 'url(':
+ if (preg_match('/url\(.*?\)/', $text, $m, 0, $count))
+ $count += strlen($m[0]) - strlen($min[0]);
+ break;
+ case '"':
+ case "'":
+ if (preg_match('/'.$min[0].'.*?'.$min[0].'/', $text, $m, 0, $count))
+ $count += strlen($m[0]) - 1;
+ break;
+ case '//':
+ $skip = strpos($text, "\n", $count);
+ if ($skip === false) $skip = strlen($text) - $count;
+ else $skip -= $count;
+ break;
+ case '/*':
+ if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) {
+ $skip = strlen($m[0]);
+ $newlines = substr_count($m[0], "\n");
+ }
+ break;
+ }
+
+ if ($skip == 0) $count += strlen($min[0]);
+
+ $out .= substr($text, 0, $count).str_repeat("\n", $newlines);
+ $text = substr($text, $count + $skip);
+
+ $min = null;
+ }
+
+ return $out.$text;
+ }
+
+}
+
+class lessc_formatter_classic {
+ public $indentChar = " ";
+
+ public $break = "\n";
+ public $open = " {";
+ public $close = "}";
+ public $selectorSeparator = ", ";
+ public $assignSeparator = ":";
+
+ public $openSingle = " { ";
+ public $closeSingle = " }";
+
+ public $disableSingle = false;
+ public $breakSelectors = false;
+
+ public $compressColors = false;
+
+ public function __construct() {
+ $this->indentLevel = 0;
+ }
+
+ public function indentStr($n = 0) {
+ return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
+ }
+
+ public function property($name, $value) {
+ return $name . $this->assignSeparator . $value . ";";
+ }
+
+ protected function isEmpty($block) {
+ if (empty($block->lines)) {
+ foreach ($block->children as $child) {
+ if (!$this->isEmpty($child)) return false;
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ public function block($block) {
+ if ($this->isEmpty($block)) return;
+
+ $inner = $pre = $this->indentStr();
+
+ $isSingle = !$this->disableSingle &&
+ is_null($block->type) && count($block->lines) == 1;
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel++;
+
+ if ($this->breakSelectors) {
+ $selectorSeparator = $this->selectorSeparator . $this->break . $pre;
+ } else {
+ $selectorSeparator = $this->selectorSeparator;
+ }
+
+ echo $pre .
+ implode($selectorSeparator, $block->selectors);
+ if ($isSingle) {
+ echo $this->openSingle;
+ $inner = "";
+ } else {
+ echo $this->open . $this->break;
+ $inner = $this->indentStr();
+ }
+
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!$isSingle && !empty($block->children)) {
+ echo $this->break;
+ }
+ }
+
+ foreach ($block->children as $child) {
+ $this->block($child);
+ }
+
+ if (!empty($block->selectors)) {
+ if (!$isSingle && empty($block->children)) echo $this->break;
+
+ if ($isSingle) {
+ echo $this->closeSingle . $this->break;
+ } else {
+ echo $pre . $this->close . $this->break;
+ }
+
+ $this->indentLevel--;
+ }
+ }
+}
+
+class lessc_formatter_compressed extends lessc_formatter_classic {
+ public $disableSingle = true;
+ public $open = "{";
+ public $selectorSeparator = ",";
+ public $assignSeparator = ":";
+ public $break = "";
+ public $compressColors = true;
+
+ public function indentStr($n = 0) {
+ return "";
+ }
+}
+
+class lessc_formatter_lessjs extends lessc_formatter_classic {
+ public $disableSingle = true;
+ public $breakSelectors = true;
+ public $assignSeparator = ": ";
+ public $selectorSeparator = ",";
+}
+
+
diff --git a/plugins/jetpack/modules/custom-css/custom-css/preprocessors/scss.inc.php b/plugins/jetpack/modules/custom-css/custom-css/preprocessors/scss.inc.php
new file mode 100644
index 00000000..5ad188cc
--- /dev/null
+++ b/plugins/jetpack/modules/custom-css/custom-css/preprocessors/scss.inc.php
@@ -0,0 +1,3759 @@
+<?php
+
+class scssc {
+ static public $VERSION = "v0.0.4";
+
+ static protected $operatorNames = array(
+ '+' => "add",
+ '-' => "sub",
+ '*' => "mul",
+ '/' => "div",
+ '%' => "mod",
+
+ '==' => "eq",
+ '!=' => "neq",
+ '<' => "lt",
+ '>' => "gt",
+
+ '<=' => "lte",
+ '>=' => "gte",
+ );
+
+ static protected $namespaces = array(
+ "special" => "%",
+ "mixin" => "@",
+ "function" => "^",
+ );
+
+ static protected $numberPrecision = 3;
+ static protected $unitTable = array(
+ "in" => array(
+ "in" => 1,
+ "pt" => 72,
+ "pc" => 6,
+ "cm" => 2.54,
+ "mm" => 25.4,
+ "px" => 96,
+ )
+ );
+
+ static public $true = array("keyword", "true");
+ static public $false = array("keyword", "false");
+
+ static public $defaultValue = array("keyword", "");
+ static public $selfSelector = array("self");
+
+ protected $importPaths = array("");
+ protected $importCache = array();
+
+ protected $userFunctions = array();
+
+ protected $formatter = "scss_formatter_nested";
+
+ function compile($code, $name=null) {
+ $this->indentLevel = -1;
+ $this->commentsSeen = array();
+ $this->extends = array();
+ $this->extendsMap = array();
+
+ $locale = setlocale(LC_NUMERIC, 0);
+ setlocale(LC_NUMERIC, "C");
+
+ $this->parsedFiles = array();
+ $this->parser = new scss_parser($name);
+ $tree = $this->parser->parse($code);
+
+ $this->formatter = new $this->formatter();
+
+ $this->env = null;
+ $this->scope = null;
+
+ $this->compileRoot($tree);
+ $this->flattenSelectors($this->scope);
+
+ ob_start();
+ $this->formatter->block($this->scope);
+ $out = ob_get_clean();
+
+ setlocale(LC_NUMERIC, $locale);
+ return $out;
+ }
+
+ protected function pushExtends($target, $origin) {
+ $i = count($this->extends);
+ $this->extends[] = array($target, $origin);
+
+ foreach ($target as $part) {
+ if (isset($this->extendsMap[$part])) {
+ $this->extendsMap[$part][] = $i;
+ } else {
+ $this->extendsMap[$part] = array($i);
+ }
+ }
+ }
+
+ protected function makeOutputBlock($type, $selectors = null) {
+ $out = new stdclass;
+ $out->type = $type;
+ $out->lines = array();
+ $out->children = array();
+ $out->parent = $this->scope;
+ $out->selectors = $selectors;
+ $out->depth = $this->env->depth;
+
+ return $out;
+ }
+
+ protected function matchExtendsSingle($single, &$out_origin, &$out_rem) {
+ $counts = array();
+ foreach ($single as $part) {
+ if (!is_string($part)) return false; // hmm
+
+ if (isset($this->extendsMap[$part])) {
+ foreach ($this->extendsMap[$part] as $idx) {
+ $counts[$idx] =
+ isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
+ }
+ }
+ }
+
+ foreach ($counts as $idx => $count) {
+ list($target, $origin) = $this->extends[$idx];
+ // check count
+ if ($count != count($target)) continue;
+ // check if target is subset of single
+ if (array_diff(array_intersect($single, $target), $target)) continue;
+
+ $out_origin = $origin;
+ $out_rem = array_diff($single, $target);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function combineSelectorSingle($base, $other) {
+ $tag = null;
+ $out = array();
+
+ foreach (array($base, $other) as $single) {
+ foreach ($single as $part) {
+ if (preg_match('/^[^.#:]/', $part)) {
+ $tag = $part;
+ } else {
+ $out[] = $part;
+ }
+ }
+ }
+
+ if ($tag) {
+ array_unshift($out, $tag);
+ }
+
+ return $out;
+ }
+
+ protected function matchExtends($selector, &$out, $from = 0, $initial=true) {
+ foreach ($selector as $i => $part) {
+ if ($i < $from) continue;
+
+ if ($this->matchExtendsSingle($part, $origin, $rem)) {
+ $before = array_slice($selector, 0, $i);
+ $after = array_slice($selector, $i + 1);
+
+ foreach ($origin as $new) {
+ $new[count($new) - 1] =
+ $this->combineSelectorSingle(end($new), $rem);
+
+ $k = 0;
+ // remove shared parts
+ if ($initial) {
+ foreach ($before as $k => $val) {
+ if (!isset($new[$k]) || $val != $new[$k]) {
+ break;
+ }
+ }
+ }
+
+ $result = array_merge(
+ $before,
+ $k > 0 ? array_slice($new, $k) : $new,
+ $after);
+
+
+ if ($result == $selector) continue;
+ $out[] = $result;
+
+ // recursively check for more matches
+ $this->matchExtends($result, $out, $i, false);
+
+ // selector sequence merging
+ if (!empty($before) && count($new) > 1) {
+ $result2 = array_merge(
+ array_slice($new, 0, -1),
+ $k > 0 ? array_slice($before, $k) : $before,
+ array_slice($new, -1),
+ $after);
+
+ $out[] = $result2;
+ }
+ }
+ }
+ }
+ }
+
+ protected function flattenSelectors($block) {
+ if ($block->selectors) {
+ $selectors = array();
+ foreach ($block->selectors as $s) {
+ $selectors[] = $s;
+ if (!is_array($s)) continue;
+ // check extends
+ if (!empty($this->extendsMap)) {
+ $this->matchExtends($s, $selectors);
+ }
+ }
+
+ $selectors = array_map(array($this, "compileSelector"), $selectors);
+ $block->selectors = $selectors;
+ }
+
+ foreach ($block->children as $child) {
+ $this->flattenSelectors($child);
+ }
+ }
+
+ protected function compileRoot($rootBlock) {
+ $this->pushEnv($rootBlock);
+ $this->scope = $this->makeOutputBlock("root");
+ $this->compileChildren($rootBlock->children, $this->scope);
+ $this->popEnv();
+ }
+
+ protected function compileMedia($media) {
+ $this->pushEnv($media);
+ $parentScope = $this->mediaParent($this->scope);
+
+ $this->scope = $this->makeOutputBlock("media", array(
+ $this->compileMediaQuery($this->multiplyMedia($this->env)))
+ );
+
+ $parentScope->children[] = $this->scope;
+
+ $this->compileChildren($media->children, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ protected function mediaParent($scope) {
+ while (!empty($scope->parent)) {
+ if (!empty($scope->type) && $scope->type != "media") {
+ break;
+ }
+ $scope = $scope->parent;
+ }
+
+ return $scope;
+ }
+
+ // TODO refactor compileNestedBlock and compileMedia into same thing
+ protected function compileNestedBlock($block, $selectors) {
+ $this->pushEnv($block);
+
+ $this->scope = $this->makeOutputBlock($block->type, $selectors);
+ $this->scope->parent->children[] = $this->scope;
+ $this->compileChildren($block->children, $this->scope);
+
+ $this->scope = $this->scope->parent;
+ $this->popEnv();
+ }
+
+ protected function compileBlock($block) {
+ $env = $this->pushEnv($block);
+
+ $env->selectors =
+ array_map(array($this, "evalSelector"), $block->selectors);
+
+ $out = $this->makeOutputBlock(null, $this->multiplySelectors($env));
+ $this->scope->children[] = $out;
+ $this->compileChildren($block->children, $out);
+
+ $this->popEnv();
+ }
+
+ // joins together .classes and #ids
+ protected function flattenSelectorSingle($single) {
+ $joined = array();
+ foreach ($single as $part) {
+ if (empty($joined) ||
+ !is_string($part) ||
+ preg_match('/[.:#]/', $part))
+ {
+ $joined[] = $part;
+ continue;
+ }
+
+ if (is_array(end($joined))) {
+ $joined[] = $part;
+ } else {
+ $joined[count($joined) - 1] .= $part;
+ }
+ }
+
+ return $joined;
+ }
+
+ // replaces all the interpolates
+ protected function evalSelector($selector) {
+ return array_map(array($this, "evalSelectorPart"), $selector);
+ }
+
+ protected function evalSelectorPart($piece) {
+ foreach ($piece as &$p) {
+ if (!is_array($p)) continue;
+
+ switch ($p[0]) {
+ case "interpolate":
+ $p = $this->compileValue($p);
+ break;
+ }
+ }
+
+ return $this->flattenSelectorSingle($piece);
+ }
+
+ // compiles to string
+ // self(&) should have been replaced by now
+ protected function compileSelector($selector) {
+ if (!is_array($selector)) return $selector; // media and the like
+
+ return implode(" ", array_map(
+ array($this, "compileSelectorPart"), $selector));
+ }
+
+ protected function compileSelectorPart($piece) {
+ foreach ($piece as &$p) {
+ if (!is_array($p)) continue;
+
+ switch ($p[0]) {
+ case "self":
+ $p = "&";
+ break;
+ default:
+ $p = $this->compileValue($p);
+ break;
+ }
+ }
+
+ return implode($piece);
+ }
+
+ protected function compileChildren($stms, $out) {
+ foreach ($stms as $stm) {
+ $ret = $this->compileChild($stm, $out);
+ if (!is_null($ret)) return $ret;
+ }
+ }
+
+ protected function compileMediaQuery($queryList) {
+ $out = "@media";
+ $first = true;
+ foreach ($queryList as $query){
+ $parts = array();
+ foreach ($query as $q) {
+ switch ($q[0]) {
+ case "mediaType":
+ $parts[] = implode(" ", array_slice($q, 1));
+ break;
+ case "mediaExp":
+ if (isset($q[2])) {
+ $parts[] = "($q[1]" . $this->formatter->assignSeparator . $this->compileValue($q[2]) . ")";
+ } else {
+ $parts[] = "($q[1])";
+ }
+ break;
+ }
+ }
+ if (!empty($parts)) {
+ if ($first) {
+ $first = false;
+ $out .= " ";
+ } else {
+ $out .= $this->formatter->tagSeparator;
+ }
+ $out .= implode(" and ", $parts);
+ }
+ }
+ return $out;
+ }
+
+ // returns true if the value was something that could be imported
+ protected function compileImport($rawPath, $out) {
+ if ($rawPath[0] == "string") {
+ $path = $this->compileStringContent($rawPath);
+ if ($path = $this->findImport($path)) {
+ $this->importFile($path, $out);
+ return true;
+ }
+ return false;
+ } if ($rawPath[0] == "list") {
+ // handle a list of strings
+ if (count($rawPath[2]) == 0) return false;
+ foreach ($rawPath[2] as $path) {
+ if ($path[0] != "string") return false;
+ }
+
+ foreach ($rawPath[2] as $path) {
+ $this->compileImport($path, $out);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // return a value to halt execution
+ protected function compileChild($child, $out) {
+ switch ($child[0]) {
+ case "import":
+ list(,$rawPath) = $child;
+ $rawPath = $this->reduce($rawPath);
+ if (!$this->compileImport($rawPath, $out)) {
+ $out->lines[] = "@import " . $this->compileValue($rawPath) . ";";
+ }
+ break;
+ case "directive":
+ list(, $directive) = $child;
+ $s = "@" . $directive->name;
+ if (!empty($directive->value)) {
+ $s .= " " . $this->compileValue($directive->value);
+ }
+ $this->compileNestedBlock($directive, array($s));
+ break;
+ case "media":
+ $this->compileMedia($child[1]);
+ break;
+ case "block":
+ $this->compileBlock($child[1]);
+ break;
+ case "charset":
+ $out->lines[] = "@charset ".$this->compileValue($child[1]).";";
+ break;
+ case "assign":
+ list(,$name, $value) = $child;
+ if ($name[0] == "var") {
+ $isDefault = !empty($child[3]);
+ if (!$isDefault || $this->get($name[1], true) === true) {
+ $this->set($name[1], $this->reduce($value));
+ }
+ break;
+ }
+
+ $out->lines[] = $this->formatter->property(
+ $this->compileValue($child[1]),
+ $this->compileValue($child[2]));
+ break;
+ case "comment":
+ $out->lines[] = $child[1];
+ break;
+ case "mixin":
+ case "function":
+ list(,$block) = $child;
+ $this->set(self::$namespaces[$block->type] . $block->name, $block);
+ break;
+ case "extend":
+ list(, $selectors) = $child;
+ foreach ($selectors as $sel) {
+ // only use the first one
+ $sel = current($this->evalSelector($sel));
+ $this->pushExtends($sel, $out->selectors);
+ }
+ break;
+ case "if":
+ list(, $if) = $child;
+ if ($this->reduce($if->cond, true) != self::$false) {
+ return $this->compileChildren($if->children, $out);
+ } else {
+ foreach ($if->cases as $case) {
+ if ($case->type == "else" ||
+ $case->type == "elseif" && ($this->reduce($case->cond) != self::$false))
+ {
+ return $this->compileChildren($case->children, $out);
+ }
+ }
+ }
+ break;
+ case "return":
+ return $this->reduce($child[1], true);
+ case "each":
+ list(,$each) = $child;
+ $list = $this->reduce($this->coerceList($each->list));
+ foreach ($list[2] as $item) {
+ $this->pushEnv();
+ $this->set($each->var, $item);
+ // TODO: allow return from here
+ $this->compileChildren($each->children, $out);
+ $this->popEnv();
+ }
+ break;
+ case "while":
+ list(,$while) = $child;
+ while ($this->reduce($while->cond, true) != self::$false) {
+ $ret = $this->compileChildren($while->children, $out);
+ if ($ret) return $ret;
+ }
+ break;
+ case "for":
+ list(,$for) = $child;
+ $start = $this->reduce($for->start, true);
+ $start = $start[1];
+ $end = $this->reduce($for->end, true);
+ $end = $end[1];
+ $d = $start < $end ? 1 : -1;
+
+ while (true) {
+ if ((!$for->until && $start - $d == $end) ||
+ ($for->until && $start == $end))
+ {
+ break;
+ }
+
+ $this->set($for->var, array("number", $start, ""));
+ $start += $d;
+
+ $ret = $this->compileChildren($for->children, $out);
+ if ($ret) return $ret;
+ }
+
+ break;
+ case "nestedprop":
+ list(,$prop) = $child;
+ $prefixed = array();
+ $prefix = $this->compileValue($prop->prefix) . "-";
+ foreach ($prop->children as $child) {
+ if ($child[0] == "assign") {
+ array_unshift($child[1][2], $prefix);
+ }
+ if ($child[0] == "nestedprop") {
+ array_unshift($child[1]->prefix[2], $prefix);
+ }
+ $prefixed[] = $child;
+ }
+ $this->compileChildren($prefixed, $out);
+ break;
+ case "include": // including a mixin
+ list(,$name, $argValues, $content) = $child;
+ $mixin = $this->get(self::$namespaces["mixin"] . $name, false);
+ if (!$mixin) break; // throw error?
+
+ $callingScope = $this->env;
+
+ // push scope, apply args
+ $this->pushEnv();
+
+ if (!is_null($content)) {
+ $content->scope = $callingScope;
+ $this->setRaw(self::$namespaces["special"] . "content", $content);
+ }
+
+ if (!is_null($mixin->args)) {
+ $this->applyArguments($mixin->args, $argValues);
+ }
+
+ foreach ($mixin->children as $child) {
+ $this->compileChild($child, $out);
+ }
+
+ $this->popEnv();
+
+ break;
+ case "mixin_content":
+ $content = $this->get(self::$namespaces["special"] . "content");
+ if (is_null($content)) {
+ throw new \Exception("Unexpected @content inside of mixin");
+ }
+
+ $this->storeEnv = $content->scope;
+
+ foreach ($content->children as $child) {
+ $this->compileChild($child, $out);
+ }
+
+ unset($this->storeEnv);
+ break;
+ case "debug":
+ list(,$value, $pos) = $child;
+ $line = $this->parser->getLineNo($pos);
+ $value = $this->compileValue($this->reduce($value, true));
+ fwrite(STDERR, "Line $line DEBUG: $value\n");
+ break;
+ default:
+ throw new exception("unknown child type: $child[0]");
+ }
+ }
+
+ protected function expToString($exp) {
+ list(, $op, $left, $right, $inParens, $whiteLeft, $whiteRight) = $exp;
+ $content = array($left);
+ if ($whiteLeft) $content[] = " ";
+ $content[] = $op;
+ if ($whiteRight) $content[] = " ";
+ $content[] = $right;
+ return array("string", "", $content);
+ }
+
+ // should $value cause its operand to eval
+ protected function shouldEval($value) {
+ switch ($value[0]) {
+ case "exp":
+ if ($value[1] == "/") {
+ return $this->shouldEval($value[2], $value[3]);
+ }
+ case "var":
+ case "fncall":
+ return true;
+ }
+ return false;
+ }
+
+ protected function reduce($value, $inExp = false) {
+ list($type) = $value;
+ switch ($type) {
+ case "exp":
+ list(, $op, $left, $right, $inParens) = $value;
+ $opName = isset(self::$operatorNames[$op]) ? self::$operatorNames[$op] : $op;
+
+ $inExp = $inExp || $this->shouldEval($left) || $this->shouldEval($right);
+
+ $left = $this->reduce($left, true);
+ $right = $this->reduce($right, true);
+
+ // only do division in special cases
+ if ($opName == "div" && !$inParens && !$inExp) {
+ if ($left[0] != "color" && $right[0] != "color") {
+ return $this->expToString($value);
+ }
+ }
+
+ $left = $this->coerceForExpression($left);
+ $right = $this->coerceForExpression($right);
+
+ $ltype = $left[0];
+ $rtype = $right[0];
+
+ // this tries:
+ // 1. op_[op name]_[left type]_[right type]
+ // 2. op_[left type]_[right type] (passing the op as first arg
+ // 3. op_[op name]
+ $fn = "op_${opName}_${ltype}_${rtype}";
+ if (is_callable(array($this, $fn)) ||
+ (($fn = "op_${ltype}_${rtype}") &&
+ is_callable(array($this, $fn)) &&
+ $passOp = true) ||
+ (($fn = "op_${opName}") &&
+ is_callable(array($this, $fn)) &&
+ $genOp = true))
+ {
+ $unitChange = false;
+ if (!isset($genOp) &&
+ $left[0] == "number" && $right[0] == "number")
+ {
+ if ($opName == "mod" && $right[2] != "") {
+ throw new \Exception(sprintf('Cannot modulo by a number with units: %s%s.', $right[1], $right[2]));
+ }
+
+ $unitChange = true;
+ $emptyUnit = $left[2] == "" || $right[2] == "";
+ $targetUnit = "" != $left[2] ? $left[2] : $right[2];
+
+ if ($opName != "mul") {
+ $left[2] = "" != $left[2] ? $left[2] : $targetUnit;
+ $right[2] = "" != $right[2] ? $right[2] : $targetUnit;
+ }
+
+ if ($opName != "mod") {
+ $left = $this->normalizeNumber($left);
+ $right = $this->normalizeNumber($right);
+ }
+
+ if ($opName == "div" && !$emptyUnit && $left[2] == $right[2]) {
+ $targetUnit = "";
+ }
+
+ if ($opName == "mul") {
+ $left[2] = "" != $left[2] ? $left[2] : $right[2];
+ $right[2] = "" != $right[2] ? $right[2] : $left[2];
+ } elseif ($opName == "div" && $left[2] == $right[2]) {
+ $left[2] = "";
+ $right[2] = "";
+ }
+ }
+
+ $shouldEval = $inParens || $inExp;
+ if (isset($passOp)) {
+ $out = $this->$fn($op, $left, $right, $shouldEval);
+ } else {
+ $out = $this->$fn($left, $right, $shouldEval);
+ }
+
+ if (!is_null($out)) {
+ if ($unitChange && $out[0] == "number") {
+ $out = $this->coerceUnit($out, $targetUnit);
+ }
+ return $out;
+ }
+ }
+
+ return $this->expToString($value);
+ case "unary":
+ list(, $op, $exp, $inParens) = $value;
+ $inExp = $inExp || $this->shouldEval($exp);
+
+ $exp = $this->reduce($exp);
+ if ($exp[0] == "number") {
+ switch ($op) {
+ case "+":
+ return $exp;
+ case "-":
+ $exp[1] *= -1;
+ return $exp;
+ }
+ }
+
+ if ($op == "not") {
+ if ($inExp || $inParens) {
+ if ($exp == self::$false) {
+ return self::$true;
+ } else {
+ return self::$false;
+ }
+ } else {
+ $op = $op . " ";
+ }
+ }
+
+ return array("string", "", array($op, $exp));
+ case "var":
+ list(, $name) = $value;
+ return $this->reduce($this->get($name));
+ case "list":
+ foreach ($value[2] as &$item) {
+ $item = $this->reduce($item);
+ }
+ return $value;
+ case "string":
+ foreach ($value[2] as &$item) {
+ if (is_array($item)) {
+ $item = $this->reduce($item);
+ }
+ }
+ return $value;
+ case "interpolate":
+ $value[1] = $this->reduce($value[1]);
+ return $value;
+ case "fncall":
+ list(,$name, $argValues) = $value;
+
+ // user defined function?
+ $func = $this->get(self::$namespaces["function"] . $name, false);
+ if ($func) {
+ $this->pushEnv();
+
+ // set the args
+ if (isset($func->args)) {
+ $this->applyArguments($func->args, $argValues);
+ }
+
+ // throw away lines and children
+ $tmp = (object)array(
+ "lines" => array(),
+ "children" => array()
+ );
+ $ret = $this->compileChildren($func->children, $tmp);
+ $this->popEnv();
+
+ return is_null($ret) ? self::$defaultValue : $ret;
+ }
+
+ // built in function
+ if ($this->callBuiltin($name, $argValues, $returnValue)) {
+ return $returnValue;
+ }
+
+ // need to flatten the arguments into a list
+ $listArgs = array();
+ foreach ((array)$argValues as $arg) {
+ if (empty($arg[0])) {
+ $listArgs[] = $this->reduce($arg[1]);
+ }
+ }
+ return array("function", $name, array("list", ",", $listArgs));
+ default:
+ return $value;
+ }
+ }
+
+ // just does physical lengths for now
+ protected function normalizeNumber($number) {
+ list(, $value, $unit) = $number;
+ if (isset(self::$unitTable["in"][$unit])) {
+ $conv = self::$unitTable["in"][$unit];
+ return array("number", $value / $conv, "in");
+ }
+ return $number;
+ }
+
+ // $number should be normalized
+ protected function coerceUnit($number, $unit) {
+ list(, $value, $baseUnit) = $number;
+ if (isset(self::$unitTable[$baseUnit][$unit])) {
+ $value = $value * self::$unitTable[$baseUnit][$unit];
+ }
+
+ return array("number", $value, $unit);
+ }
+
+ protected function op_add_number_number($left, $right) {
+ return array("number", $left[1] + $right[1], $left[2]);
+ }
+
+ protected function op_mul_number_number($left, $right) {
+ return array("number", $left[1] * $right[1], $left[2]);
+ }
+
+ protected function op_sub_number_number($left, $right) {
+ return array("number", $left[1] - $right[1], $left[2]);
+ }
+
+ protected function op_div_number_number($left, $right) {
+ return array("number", $left[1] / $right[1], $left[2]);
+ }
+
+ protected function op_mod_number_number($left, $right) {
+ return array("number", $left[1] % $right[1], $left[2]);
+ }
+
+ // adding strings
+ protected function op_add($left, $right) {
+ if ($strLeft = $this->coerceString($left)) {
+ if ($right[0] == "string") {
+ $right[1] = "";
+ }
+ $strLeft[2][] = $right;
+ return $strLeft;
+ }
+
+ if ($strRight = $this->coerceString($right)) {
+ if ($left[0] == "string") {
+ $left[1] = "";
+ }
+ array_unshift($strRight[2], $left);
+ return $strRight;
+ }
+ }
+
+ protected function op_and($left, $right, $shouldEval) {
+ if (!$shouldEval) return;
+ if ($left != self::$false) return $right;
+ return $left;
+ }
+
+ protected function op_or($left, $right, $shouldEval) {
+ if (!$shouldEval) return;
+ if ($left != self::$false) return $left;
+ return $right;
+ }
+
+ protected function op_color_color($op, $left, $right) {
+ $out = array('color');
+ foreach (range(1, 3) as $i) {
+ $lval = isset($left[$i]) ? $left[$i] : 0;
+ $rval = isset($right[$i]) ? $right[$i] : 0;
+ switch ($op) {
+ case '+':
+ $out[] = $lval + $rval;
+ break;
+ case '-':
+ $out[] = $lval - $rval;
+ break;
+ case '*':
+ $out[] = $lval * $rval;
+ break;
+ case '%':
+ $out[] = $lval % $rval;
+ break;
+ case '/':
+ if ($rval == 0) {
+ throw new exception("color: Can't divide by zero");
+ }
+ $out[] = $lval / $rval;
+ break;
+ default:
+ throw new exception("color: unknow op $op");
+ }
+ }
+
+ if (isset($left[4])) $out[4] = $left[4];
+ elseif (isset($right[4])) $out[4] = $right[4];
+
+ return $this->fixColor($out);
+ }
+
+ protected function op_color_number($op, $left, $right) {
+ $value = $right[1];
+ return $this->op_color_color($op, $left,
+ array("color", $value, $value, $value));
+ }
+
+ protected function op_number_color($op, $left, $right) {
+ $value = $left[1];
+ return $this->op_color_color($op,
+ array("color", $value, $value, $value), $right);
+ }
+
+ protected function op_eq($left, $right) {
+ if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) {
+ $lStr[1] = "";
+ $rStr[1] = "";
+ return $this->toBool($this->compileValue($lStr) == $this->compileValue($rStr));
+ }
+
+ return $this->toBool($left == $right);
+ }
+
+ protected function op_neq($left, $right) {
+ return $this->toBool($left != $right);
+ }
+
+ protected function op_gte_number_number($left, $right) {
+ return $this->toBool($left[1] >= $right[1]);
+ }
+
+ protected function op_gt_number_number($left, $right) {
+ return $this->toBool($left[1] > $right[1]);
+ }
+
+ protected function op_lte_number_number($left, $right) {
+ return $this->toBool($left[1] <= $right[1]);
+ }
+
+ protected function op_lt_number_number($left, $right) {
+ return $this->toBool($left[1] < $right[1]);
+ }
+
+ protected function toBool($thing) {
+ return $thing ? self::$true : self::$false;
+ }
+
+ protected function compileValue($value) {
+ $value = $this->reduce($value);
+
+ list($type) = $value;
+ switch ($type) {
+ case "keyword":
+ return $value[1];
+ case "color":
+ // [1] - red component (either number for a %)
+ // [2] - green component
+ // [3] - blue component
+ // [4] - optional alpha component
+ list(, $r, $g, $b) = $value;
+
+ $r = round($r);
+ $g = round($g);
+ $b = round($b);
+
+ if (count($value) == 5 && $value[4] != 1) { // rgba
+ return 'rgba('.$r.', '.$g.', '.$b.', '.$value[4].')';
+ }
+
+ $h = sprintf("#%02x%02x%02x", $r, $g, $b);
+
+ // Converting hex color to short notation (e.g. #003399 to #039)
+ if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) {
+ $h = '#' . $h[1] . $h[3] . $h[5];
+ }
+
+ return $h;
+ case "number":
+ return round($value[1], self::$numberPrecision) . $value[2];
+ case "string":
+ return $value[1] . $this->compileStringContent($value) . $value[1];
+ case "function":
+ $args = !empty($value[2]) ? $this->compileValue($value[2]) : "";
+ return "$value[1]($args)";
+ case "list":
+ $value = $this->extractInterpolation($value);
+ if ($value[0] != "list") return $this->compileValue($value);
+
+ list(, $delim, $items) = $value;
+ foreach ($items as &$item) {
+ $item = $this->compileValue($item);
+ }
+ return implode("$delim ", $items);
+ case "interpolated": # node created by extractInterpolation
+ list(, $interpolate, $left, $right) = $value;
+ list(,, $whiteLeft, $whiteRight) = $interpolate;
+
+ $left = count($left[2]) > 0 ?
+ $this->compileValue($left).$whiteLeft : "";
+
+ $right = count($right[2]) > 0 ?
+ $whiteRight.$this->compileValue($right) : "";
+
+ return $left.$this->compileValue($interpolate).$right;
+
+ case "interpolate": # raw parse node
+ list(, $exp) = $value;
+
+ // strip quotes if it's a string
+ $reduced = $this->reduce($exp);
+ if ($reduced[0] == "string") {
+ $reduced = array("keyword",
+ $this->compileStringContent($reduced));
+ }
+
+ return $this->compileValue($reduced);
+ default:
+ throw new exception("unknown value type: $type");
+ }
+ }
+
+ protected function compileStringContent($string) {
+ $parts = array();
+ foreach ($string[2] as $part) {
+ if (is_array($part)) {
+ $parts[] = $this->compileValue($part);
+ } else {
+ $parts[] = $part;
+ }
+ }
+
+ return implode($parts);
+ }
+
+ // doesn't need to be recursive, compileValue will handle that
+ protected function extractInterpolation($list) {
+ $items = $list[2];
+ foreach ($items as $i => $item) {
+ if ($item[0] == "interpolate") {
+ $before = array("list", $list[1], array_slice($items, 0, $i));
+ $after = array("list", $list[1], array_slice($items, $i + 1));
+ return array("interpolated", $item, $before, $after);
+ }
+ }
+ return $list;
+ }
+
+ // find the final set of selectors
+ protected function multiplySelectors($env, $childSelectors = null) {
+ if (is_null($env)) {
+ return $childSelectors;
+ }
+
+ // skip env, has no selectors
+ if (empty($env->selectors)) {
+ return $this->multiplySelectors($env->parent, $childSelectors);
+ }
+
+ if (is_null($childSelectors)) {
+ $selectors = $env->selectors;
+ } else {
+ $selectors = array();
+ foreach ($env->selectors as $parent) {
+ foreach ($childSelectors as $child) {
+ $selectors[] = $this->joinSelectors($parent, $child);
+ }
+ }
+ }
+
+ return $this->multiplySelectors($env->parent, $selectors);
+ }
+
+ // looks for & to replace, or append parent before child
+ protected function joinSelectors($parent, $child) {
+ $setSelf = false;
+ $out = array();
+ foreach ($child as $part) {
+ $newPart = array();
+ foreach ($part as $p) {
+ if ($p == self::$selfSelector) {
+ $setSelf = true;
+ foreach ($parent as $i => $parentPart) {
+ if ($i > 0) {
+ $out[] = $newPart;
+ $newPart = array();
+ }
+
+ foreach ($parentPart as $pp) {
+ $newPart[] = $pp;
+ }
+ }
+ } else {
+ $newPart[] = $p;
+ }
+ }
+
+ $out[] = $newPart;
+ }
+
+ return $setSelf ? $out : array_merge($parent, $child);
+ }
+
+ protected function multiplyMedia($env, $childQueries = null) {
+ if (is_null($env) ||
+ !empty($env->block->type) && $env->block->type != "media")
+ {
+ return $childQueries;
+ }
+
+ // plain old block, skip
+ if (empty($env->block->type)) {
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ $parentQueries = $env->block->queryList;
+ if ($childQueries == null) {
+ $childQueries = $parentQueries;
+ } else {
+ $originalQueries = $childQueries;
+ $childQueries = array();
+
+ foreach ($parentQueries as $parentQuery){
+ foreach ($originalQueries as $childQuery) {
+ $childQueries []= array_merge($parentQuery, $childQuery);
+ }
+ }
+ }
+
+ return $this->multiplyMedia($env->parent, $childQueries);
+ }
+
+ // convert something to list
+ protected function coerceList($item, $delim = ",") {
+ if (!is_null($item) && $item[0] == "list") {
+ return $item;
+ }
+
+ return array("list", $delim, is_null($item) ? array(): array($item));
+ }
+
+ protected function applyArguments($argDef, $argValues) {
+ $argValues = (array)$argValues;
+
+ $keywordArgs = array();
+ $remaining = array();
+
+ // assign the keyword args
+ foreach ($argValues as $arg) {
+ if (!empty($arg[0])) {
+ $keywordArgs[$arg[0][1]] = $arg[1];
+ } else {
+ $remaining[] = $arg[1];
+ }
+ }
+
+ foreach ($argDef as $i => $arg) {
+ list($name, $default) = $arg;
+
+ if (isset($remaining[$i])) {
+ $val = $remaining[$i];
+ } elseif (isset($keywordArgs[$name])) {
+ $val = $keywordArgs[$name];
+ } elseif (!empty($default)) {
+ $val = $default;
+ } else {
+ $val = self::$defaultValue;
+ }
+
+ $this->set($name, $this->reduce($val, true), true);
+ }
+ }
+
+ protected function pushEnv($block=null) {
+ $env = new stdclass;
+ $env->parent = $this->env;
+ $env->store = array();
+ $env->block = $block;
+ $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0;
+
+ $this->env = $env;
+ return $env;
+ }
+
+ protected function normalizeName($name) {
+ return str_replace("-", "_", $name);
+ }
+
+ protected function getStoreEnv() {
+ return isset($this->storeEnv) ? $this->storeEnv : $this->env;
+ }
+
+ protected function set($name, $value, $shadow=false) {
+ $name = $this->normalizeName($name);
+ if ($shadow) {
+ $this->setRaw($name, $value);
+ } else {
+ $this->setExisting($name, $value);
+ }
+ }
+
+ // todo: this is bugged?
+ protected function setExisting($name, $value, $env = null) {
+ if (is_null($env)) $env = $this->getStoreEnv();
+
+ if (isset($env->store[$name])) {
+ $env->store[$name] = $value;
+ } elseif (!is_null($env->parent)) {
+ $this->setExisting($name, $value, $env->parent);
+ } else {
+ $this->env->store[$name] = $value;
+ }
+ }
+
+ protected function setRaw($name, $value) {
+ $this->env->store[$name] = $value;
+ }
+
+ protected function get($name, $defaultValue = null, $env = null) {
+ $name = $this->normalizeName($name);
+
+ if (is_null($env)) $env = $this->getStoreEnv();
+ if (is_null($defaultValue)) $defaultValue = self::$defaultValue;
+
+ if (isset($env->store[$name])) {
+ return $env->store[$name];
+ } elseif (!is_null($env->parent)) {
+ return $this->get($name, $defaultValue, $env->parent);
+ }
+
+ return $defaultValue; // found nothing
+ }
+
+ protected function popEnv() {
+ $env = $this->env;
+ $this->env = $this->env->parent;
+ return $env;
+ }
+
+ public function getParsedFiles() {
+ return $this->parsedFiles;
+ }
+
+ public function addImportPath($path) {
+ $this->importPaths[] = $path;
+ }
+
+ public function setImportPaths($path) {
+ $this->importPaths = (array)$path;
+ }
+
+ public function setFormatter($formatterName) {
+ $this->formatter = $formatterName;
+ }
+
+ public function registerFunction($name, $func) {
+ $this->userFunctions[$this->normalizeName($name)] = $func;
+ }
+
+ public function unregisterFunction($name) {
+ unset($this->userFunctions[$this->normalizeName($name)]);
+ }
+
+ protected function importFile($path, $out) {
+ // see if tree is cached
+ $realPath = realpath($path);
+ if (isset($this->importCache[$realPath])) {
+ $tree = $this->importCache[$realPath];
+ } else {
+ $code = file_get_contents($path);
+ $parser = new scss_parser($path);
+ $tree = $parser->parse($code);
+ $this->parsedFiles[] = $path;
+
+ $this->importCache[$realPath] = $tree;
+ }
+
+ $pi = pathinfo($path);
+ array_unshift($this->importPaths, $pi['dirname']);
+ $this->compileChildren($tree->children, $out);
+ array_shift($this->importPaths);
+ }
+
+ // results the file path for an import url if it exists
+ protected function findImport($url) {
+ $urls = array();
+
+ // for "normal" scss imports (ignore vanilla css and external requests)
+ if (!preg_match('/\.css|^http:\/\/$/', $url)) {
+ // try both normal and the _partial filename
+ $urls = array($url, preg_replace('/[^\/]+$/', '_\0', $url));
+ }
+
+ foreach ($this->importPaths as $dir) {
+ if (is_string($dir)) {
+ // check urls for normal import paths
+ foreach ($urls as $full) {
+ $full = $dir .
+ (!empty($dir) && substr($dir, -1) != '/' ? '/' : '') .
+ $full;
+
+ if ($this->fileExists($file = $full.'.scss') ||
+ $this->fileExists($file = $full))
+ {
+ return $file;
+ }
+ }
+ } else {
+ // check custom callback for import path
+ $file = call_user_func($dir,$url,$this);
+ if ($file !== null) {
+ return $file;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ protected function fileExists($name) {
+ return is_file($name);
+ }
+
+ protected function callBuiltin($name, $args, &$returnValue) {
+ // try a lib function
+ $name = $this->normalizeName($name);
+ $libName = "lib_".$name;
+ $f = array($this, $libName);
+ $prototype = isset(self::$$libName) ? self::$$libName : null;
+
+ if (is_callable($f)) {
+ $sorted = $this->sortArgs($prototype, $args);
+ foreach ($sorted as &$val) {
+ $val = $this->reduce($val, true);
+ }
+ $returnValue = call_user_func($f, $sorted, $this);
+ } else if (isset($this->userFunctions[$name])) {
+ // see if we can find a user function
+ $fn = $this->userFunctions[$name];
+
+ foreach ($args as &$val) {
+ $val = $this->reduce($val[1], true);
+ }
+
+ $returnValue = call_user_func($fn, $args, $this);
+ }
+
+ if (isset($returnValue)) {
+ // coerce a php value into a scss one
+ if (is_numeric($returnValue)) {
+ $returnValue = array('number', $returnValue, "");
+ } elseif (is_bool($returnValue)) {
+ $returnValue = $returnValue ? self::$true : self::$false;
+ } elseif (!is_array($returnValue)) {
+ $returnValue = array('keyword', $returnValue);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // sorts any keyword arguments
+ // TODO: merge with apply arguments
+ protected function sortArgs($prototype, $args) {
+ $keyArgs = array();
+ $posArgs = array();
+
+ foreach ($args as $arg) {
+ list($key, $value) = $arg;
+ $key = $key[1];
+ if (empty($key)) {
+ $posArgs[] = $value;
+ } else {
+ $keyArgs[$key] = $value;
+ }
+ }
+
+ if (is_null($prototype)) return $posArgs;
+
+ $finalArgs = array();
+ foreach ($prototype as $i => $names) {
+ if (isset($posArgs[$i])) {
+ $finalArgs[] = $posArgs[$i];
+ continue;
+ }
+
+ $set = false;
+ foreach ((array)$names as $name) {
+ if (isset($keyArgs[$name])) {
+ $finalArgs[] = $keyArgs[$name];
+ $set = true;
+ break;
+ }
+ }
+
+ if (!$set) {
+ $finalArgs[] = null;
+ }
+ }
+
+ return $finalArgs;
+ }
+
+ protected function coerceForExpression($value) {
+ if ($color = $this->coerceColor($value)) {
+ return $color;
+ }
+
+ return $value;
+ }
+
+ protected function coerceColor($value) {
+ switch ($value[0]) {
+ case "color": return $value;
+ case "keyword":
+ $name = $value[1];
+ if (isset(self::$cssColors[$name])) {
+ list($r, $g, $b) = explode(',', self::$cssColors[$name]);
+ return array('color', $r, $g, $b);
+ }
+ return null;
+ }
+
+ return null;
+ }
+
+ protected function coerceString($value) {
+ switch ($value[0]) {
+ case "string":
+ return $value;
+ case "keyword":
+ return array("string", "", array($value[1]));
+ }
+ return null;
+ }
+
+ protected function assertColor($value) {
+ if ($color = $this->coerceColor($value)) return $color;
+ throw new exception("expecting color");
+ }
+
+ protected function assertNumber($value) {
+ if ($value[0] != "number")
+ throw new exception("expecting number");
+ return $value[1];
+ }
+
+ protected function coercePercent($value) {
+ if ($value[0] == "number") {
+ if ($value[2] == "%") {
+ return $value[1] / 100;
+ }
+ return $value[1];
+ }
+ return 0;
+ }
+
+ // make sure a color's components don't go out of bounds
+ protected function fixColor($c) {
+ foreach (range(1, 3) as $i) {
+ if ($c[$i] < 0) $c[$i] = 0;
+ if ($c[$i] > 255) $c[$i] = 255;
+ }
+
+ return $c;
+ }
+
+ function toHSL($r, $g, $b) {
+ $r = $r / 255;
+ $g = $g / 255;
+ $b = $b / 255;
+
+ $min = min($r, $g, $b);
+ $max = max($r, $g, $b);
+
+ $L = ($min + $max) / 2;
+ if ($min == $max) {
+ $S = $H = 0;
+ } else {
+ if ($L < 0.5)
+ $S = ($max - $min)/($max + $min);
+ else
+ $S = ($max - $min)/(2.0 - $max - $min);
+
+ if ($r == $max) $H = ($g - $b)/($max - $min);
+ elseif ($g == $max) $H = 2.0 + ($b - $r)/($max - $min);
+ elseif ($b == $max) $H = 4.0 + ($r - $g)/($max - $min);
+
+ }
+
+ return array('hsl',
+ ($H < 0 ? $H + 6 : $H)*60,
+ $S*100,
+ $L*100,
+ );
+ }
+
+ function toRGB_helper($comp, $temp1, $temp2) {
+ if ($comp < 0) $comp += 1.0;
+ elseif ($comp > 1) $comp -= 1.0;
+
+ if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp;
+ if (2 * $comp < 1) return $temp2;
+ if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6;
+
+ return $temp1;
+ }
+
+ // H from 0 to 360, S and L from 0 to 100
+ function toRGB($H, $S, $L) {
+ $H = $H % 360;
+ if ($H < 0) $H += 360;
+
+ $S = min(100, max(0, $S));
+ $L = min(100, max(0, $L));
+
+ $H = $H / 360;
+ $S = $S / 100;
+ $L = $L / 100;
+
+ if ($S == 0) {
+ $r = $g = $b = $L;
+ } else {
+ $temp2 = $L < 0.5 ?
+ $L*(1.0 + $S) :
+ $L + $S - $L * $S;
+
+ $temp1 = 2.0 * $L - $temp2;
+
+ $r = $this->toRGB_helper($H + 1/3, $temp1, $temp2);
+ $g = $this->toRGB_helper($H, $temp1, $temp2);
+ $b = $this->toRGB_helper($H - 1/3, $temp1, $temp2);
+ }
+
+ $out = array('color', $r*255, $g*255, $b*255);
+ return $out;
+ }
+
+ // Built in functions
+
+ protected static $lib_if = array("condition", "if-true", "if-false");
+ protected function lib_if($args) {
+ list($cond,$t, $f) = $args;
+ if ($cond == self::$false) return $f;
+ return $t;
+ }
+
+ protected static $lib_rgb = array("red", "green", "blue");
+ protected function lib_rgb($args) {
+ list($r,$g,$b) = $args;
+ return array("color", $r[1], $g[1], $b[1]);
+ }
+
+ protected static $lib_rgba = array(
+ array("red", "color"),
+ "green", "blue", "alpha");
+ protected function lib_rgba($args) {
+ if ($color = $this->coerceColor($args[0])) {
+ $num = is_null($args[1]) ? $args[3] : $args[1];
+ $alpha = $this->assertNumber($num);
+ $color[4] = $alpha;
+ return $color;
+ }
+
+ list($r,$g,$b, $a) = $args;
+ return array("color", $r[1], $g[1], $b[1], $a[1]);
+ }
+
+ // helper function for adjust_color, change_color, and scale_color
+ protected function alter_color($args, $fn) {
+ $color = $this->assertColor($args[0]);
+
+ foreach (array(1,2,3,7) as $i) {
+ if (!is_null($args[$i])) {
+ $val = $this->assertNumber($args[$i]);
+ $ii = $i == 7 ? 4 : $i; // alpha
+ $color[$ii] =
+ $this->$fn(isset($color[$ii]) ? $color[$ii] : 0, $val, $i);
+ }
+ }
+
+ if (!is_null($args[4]) || !is_null($args[5]) || !is_null($args[6])) {
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ foreach (array(4,5,6) as $i) {
+ if (!is_null($args[$i])) {
+ $val = $this->assertNumber($args[$i]);
+ $hsl[$i - 3] = $this->$fn($hsl[$i - 3], $val, $i);
+ }
+ }
+
+ $rgb = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
+ if (isset($color[4])) $rgb[4] = $color[4];
+ $color = $rgb;
+ }
+
+ return $color;
+ }
+
+ protected static $lib_adjust_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function adjust_color_helper($base, $alter, $i) {
+ return $base += $alter;
+ }
+ protected function lib_adjust_color($args) {
+ return $this->alter_color($args, "adjust_color_helper");
+ }
+
+ protected static $lib_change_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function change_color_helper($base, $alter, $i) {
+ return $alter;
+ }
+ protected function lib_change_color($args) {
+ return $this->alter_color($args, "change_color_helper");
+ }
+
+ protected static $lib_scale_color = array(
+ "color", "red", "green", "blue",
+ "hue", "saturation", "lightness", "alpha"
+ );
+ protected function scale_color_helper($base, $scale, $i) {
+ // 1,2,3 - rgb
+ // 4, 5, 6 - hsl
+ // 7 - a
+ switch ($i) {
+ case 1:
+ case 2:
+ case 3:
+ $max = 255; break;
+ case 4:
+ $max = 360; break;
+ case 7:
+ $max = 1; break;
+ default:
+ $max = 100;
+ }
+
+ $scale = $scale / 100;
+ if ($scale < 0) {
+ return $base * $scale + $base;
+ } else {
+ return ($max - $base) * $scale + $base;
+ }
+ }
+ protected function lib_scale_color($args) {
+ return $this->alter_color($args, "scale_color_helper");
+ }
+
+ protected static $lib_ie_hex_str = array("color");
+ protected function lib_ie_hex_str($args) {
+ $color = $this->coerceColor($args[0]);
+ $color[4] = isset($color[4]) ? round(255*$color[4]) : 255;
+
+ return sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3]);
+ }
+
+ protected static $lib_red = array("color");
+ protected function lib_red($args) {
+ list($color) = $args;
+ return $color[1];
+ }
+
+ protected static $lib_green = array("color");
+ protected function lib_green($args) {
+ list($color) = $args;
+ return $color[2];
+ }
+
+ protected static $lib_blue = array("color");
+ protected function lib_blue($args) {
+ list($color) = $args;
+ return $color[3];
+ }
+
+ protected static $lib_alpha = array("color");
+ protected function lib_alpha($args) {
+ if ($color = $this->coerceColor($args[0])) {
+ return isset($color[4]) ? $color[4] : 1;
+ }
+
+ // this might be the IE function, so return value unchanged
+ return array("function", "alpha", array("list", ",", $args));
+ }
+
+ protected static $lib_opacity = array("color");
+ protected function lib_opacity($args) {
+ return $this->lib_alpha($args);
+ }
+
+ // mix two colors
+ protected static $lib_mix = array("color-1", "color-2", "weight");
+ protected function lib_mix($args) {
+ list($first, $second, $weight) = $args;
+ $first = $this->assertColor($first);
+ $second = $this->assertColor($second);
+
+ if (is_null($weight)) {
+ $weight = 0.5;
+ } else {
+ $weight = $this->coercePercent($weight);
+ }
+
+ $first_a = isset($first[4]) ? $first[4] : 1;
+ $second_a = isset($second[4]) ? $second[4] : 1;
+
+ $w = $weight * 2 - 1;
+ $a = $first_a - $second_a;
+
+ $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0;
+ $w2 = 1.0 - $w1;
+
+ $new = array('color',
+ $w1 * $first[1] + $w2 * $second[1],
+ $w1 * $first[2] + $w2 * $second[2],
+ $w1 * $first[3] + $w2 * $second[3],
+ );
+
+ if ($first_a != 1.0 || $second_a != 1.0) {
+ $new[] = $first_a * $weight + $second_a * ($weight - 1);
+ }
+
+ return $this->fixColor($new);
+ }
+
+ protected static $lib_hsl = array("hue", "saturation", "lightness");
+ protected function lib_hsl($args) {
+ list($h, $s, $l) = $args;
+ return $this->toRGB($h[1], $s[1], $l[1]);
+ }
+
+ protected static $lib_hsla = array("hue", "saturation",
+ "lightness", "alpha");
+ protected function lib_hsla($args) {
+ list($h, $s, $l, $a) = $args;
+ $color = $this->toRGB($h[1], $s[1], $l[1]);
+ $color[4] = $a[1];
+ return $color;
+ }
+
+ protected static $lib_hue = array("color");
+ protected function lib_hue($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[1], "deg");
+ }
+
+ protected static $lib_saturation = array("color");
+ protected function lib_saturation($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[2], "%");
+ }
+
+ protected static $lib_lightness = array("color");
+ protected function lib_lightness($args) {
+ $color = $this->assertColor($args[0]);
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ return array("number", $hsl[3], "%");
+ }
+
+
+ protected function adjustHsl($color, $idx, $amount) {
+ $hsl = $this->toHSL($color[1], $color[2], $color[3]);
+ $hsl[$idx] += $amount;
+ $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]);
+ if (isset($color[4])) $out[4] = $color[4];
+ return $out;
+ }
+
+ protected static $lib_adjust_hue = array("color", "degrees");
+ protected function lib_adjust_hue($args) {
+ $color = $this->assertColor($args[0]);
+ $degrees = $this->assertNumber($args[1]);
+ return $this->adjustHsl($color, 1, $degrees);
+ }
+
+ protected static $lib_lighten = array("color", "amount");
+ protected function lib_lighten($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 3, $amount);
+ }
+
+ protected static $lib_darken = array("color", "amount");
+ protected function lib_darken($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 3, -$amount);
+ }
+
+ protected static $lib_saturate = array("color", "amount");
+ protected function lib_saturate($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 2, $amount);
+ }
+
+ protected static $lib_desaturate = array("color", "amount");
+ protected function lib_desaturate($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = 100*$this->coercePercent($args[1]);
+ return $this->adjustHsl($color, 2, -$amount);
+ }
+
+ protected static $lib_grayscale = array("color");
+ protected function lib_grayscale($args) {
+ return $this->adjustHsl($this->assertColor($args[0]), 2, -100);
+ }
+
+ protected static $lib_complement = array("color");
+ protected function lib_complement($args) {
+ return $this->adjustHsl($this->assertColor($args[0]), 1, 180);
+ }
+
+ protected static $lib_invert = array("color");
+ protected function lib_invert($args) {
+ $color = $this->assertColor($args[0]);
+ $color[1] = 255 - $color[1];
+ $color[2] = 255 - $color[2];
+ $color[3] = 255 - $color[3];
+ return $color;
+ }
+
+
+ // increases opacity by amount
+ protected static $lib_opacify = array("color", "amount");
+ protected function lib_opacify($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = $this->coercePercent($args[1]);
+
+ $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount;
+ $color[4] = min(1, max(0, $color[4]));
+ return $color;
+ }
+
+ protected static $lib_fade_in = array("color", "amount");
+ protected function lib_fade_in($args) {
+ return $this->lib_opacify($args);
+ }
+
+ // decreases opacity by amount
+ protected static $lib_transparentize = array("color", "amount");
+ protected function lib_transparentize($args) {
+ $color = $this->assertColor($args[0]);
+ $amount = $this->coercePercent($args[1]);
+
+ $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount;
+ $color[4] = min(1, max(0, $color[4]));
+ return $color;
+ }
+
+ protected static $lib_fade_out = array("color", "amount");
+ protected function lib_fade_out($args) {
+ return $this->lib_transparentize($args);
+ }
+
+ protected static $lib_unquote = array("string");
+ protected function lib_unquote($args) {
+ $str = $args[0];
+ if ($str[0] == "string") $str[1] = "";
+ return $str;
+ }
+
+ protected static $lib_quote = array("string");
+ protected function lib_quote($args) {
+ $value = $args[0];
+ if ($value[0] == "string" && !empty($value[1]))
+ return $value;
+ return array("string", '"', array($value));
+ }
+
+ protected static $lib_percentage = array("value");
+ protected function lib_percentage($args) {
+ return array("number",
+ $this->coercePercent($args[0]) * 100,
+ "%");
+ }
+
+ protected static $lib_round = array("value");
+ protected function lib_round($args) {
+ $num = $args[0];
+ $num[1] = round($num[1]);
+ return $num;
+ }
+
+ protected static $lib_floor = array("value");
+ protected function lib_floor($args) {
+ $num = $args[0];
+ $num[1] = floor($num[1]);
+ return $num;
+ }
+
+ protected static $lib_ceil = array("value");
+ protected function lib_ceil($args) {
+ $num = $args[0];
+ $num[1] = ceil($num[1]);
+ return $num;
+ }
+
+ protected static $lib_abs = array("value");
+ protected function lib_abs($args) {
+ $num = $args[0];
+ $num[1] = abs($num[1]);
+ return $num;
+ }
+
+ protected function lib_min($args) {
+ $numbers = $this->getNormalizedNumbers($args);
+ $min = null;
+ foreach ($numbers as $key => $number) {
+ if (null === $min || $number <= $min[1]) {
+ $min = array($key, $number);
+ }
+ }
+
+ return $args[$min[0]];
+ }
+
+ protected function lib_max($args) {
+ $numbers = $this->getNormalizedNumbers($args);
+ $max = null;
+ foreach ($numbers as $key => $number) {
+ if (null === $max || $number >= $max[1]) {
+ $max = array($key, $number);
+ }
+ }
+
+ return $args[$max[0]];
+ }
+
+ protected function getNormalizedNumbers($args) {
+ $unit = null;
+ $originalUnit = null;
+ $numbers = array();
+ foreach ($args as $key => $item) {
+ if ('number' != $item[0]) {
+ throw new Exception(sprintf('%s is not a number', $item[0]));
+ }
+ $number = $this->normalizeNumber($item);
+
+ if (null === $unit) {
+ $unit = $number[2];
+ } elseif ($unit !== $number[2]) {
+ throw new \Exception(sprintf('Incompatible units: "%s" and "%s".', $originalUnit, $item[2]));
+ }
+
+ $originalUnit = $item[2];
+ $numbers[$key] = $number[1];
+ }
+
+ return $numbers;
+ }
+
+ protected static $lib_length = array("list");
+ protected function lib_length($args) {
+ $list = $this->coerceList($args[0]);
+ return count($list[2]);
+ }
+
+ protected static $lib_nth = array("list", "n");
+ protected function lib_nth($args) {
+ $list = $this->coerceList($args[0]);
+ $n = $this->assertNumber($args[1]) - 1;
+ return isset($list[2][$n]) ? $list[2][$n] : self::$defaultValue;
+ }
+
+
+ protected function listSeparatorForJoin($list1, $sep) {
+ if (is_null($sep)) return $list1[1];
+ switch ($this->compileValue($sep)) {
+ case "comma":
+ return ",";
+ case "space":
+ return "";
+ default:
+ return $list1[1];
+ }
+ }
+
+ protected static $lib_join = array("list1", "list2", "separator");
+ protected function lib_join($args) {
+ list($list1, $list2, $sep) = $args;
+ $list1 = $this->coerceList($list1, " ");
+ $list2 = $this->coerceList($list2, " ");
+ $sep = $this->listSeparatorForJoin($list1, $sep);
+ return array("list", $sep, array_merge($list1[2], $list2[2]));
+ }
+
+ protected static $lib_append = array("list", "val", "separator");
+ protected function lib_append($args) {
+ list($list1, $value, $sep) = $args;
+ $list1 = $this->coerceList($list1, " ");
+ $sep = $this->listSeparatorForJoin($list1, $sep);
+ return array("list", $sep, array_merge($list1[2], array($value)));
+ }
+
+
+ protected static $lib_type_of = array("value");
+ protected function lib_type_of($args) {
+ $value = $args[0];
+ switch ($value[0]) {
+ case "keyword":
+ if ($value == self::$true || $value == self::$false) {
+ return "bool";
+ }
+
+ if ($this->coerceColor($value)) {
+ return "color";
+ }
+
+ return "string";
+ default:
+ return $value[0];
+ }
+ }
+
+ protected static $lib_unit = array("number");
+ protected function lib_unit($args) {
+ $num = $args[0];
+ if ($num[0] == "number") {
+ return array("string", '"', array($num[2]));
+ }
+ return "";
+ }
+
+ protected static $lib_unitless = array("number");
+ protected function lib_unitless($args) {
+ $value = $args[0];
+ return $value[0] == "number" && empty($value[2]);
+ }
+
+
+ protected static $lib_comparable = array("number-1", "number-2");
+ protected function lib_comparable($args) {
+ return true; // TODO: THIS
+ }
+
+ static protected $cssColors = array(
+ 'aliceblue' => '240,248,255',
+ 'antiquewhite' => '250,235,215',
+ 'aqua' => '0,255,255',
+ 'aquamarine' => '127,255,212',
+ 'azure' => '240,255,255',
+ 'beige' => '245,245,220',
+ 'bisque' => '255,228,196',
+ 'black' => '0,0,0',
+ 'blanchedalmond' => '255,235,205',
+ 'blue' => '0,0,255',
+ 'blueviolet' => '138,43,226',
+ 'brown' => '165,42,42',
+ 'burlywood' => '222,184,135',
+ 'cadetblue' => '95,158,160',
+ 'chartreuse' => '127,255,0',
+ 'chocolate' => '210,105,30',
+ 'coral' => '255,127,80',
+ 'cornflowerblue' => '100,149,237',
+ 'cornsilk' => '255,248,220',
+ 'crimson' => '220,20,60',
+ 'cyan' => '0,255,255',
+ 'darkblue' => '0,0,139',
+ 'darkcyan' => '0,139,139',
+ 'darkgoldenrod' => '184,134,11',
+ 'darkgray' => '169,169,169',
+ 'darkgreen' => '0,100,0',
+ 'darkgrey' => '169,169,169',
+ 'darkkhaki' => '189,183,107',
+ 'darkmagenta' => '139,0,139',
+ 'darkolivegreen' => '85,107,47',
+ 'darkorange' => '255,140,0',
+ 'darkorchid' => '153,50,204',
+ 'darkred' => '139,0,0',
+ 'darksalmon' => '233,150,122',
+ 'darkseagreen' => '143,188,143',
+ 'darkslateblue' => '72,61,139',
+ 'darkslategray' => '47,79,79',
+ 'darkslategrey' => '47,79,79',
+ 'darkturquoise' => '0,206,209',
+ 'darkviolet' => '148,0,211',
+ 'deeppink' => '255,20,147',
+ 'deepskyblue' => '0,191,255',
+ 'dimgray' => '105,105,105',
+ 'dimgrey' => '105,105,105',
+ 'dodgerblue' => '30,144,255',
+ 'firebrick' => '178,34,34',
+ 'floralwhite' => '255,250,240',
+ 'forestgreen' => '34,139,34',
+ 'fuchsia' => '255,0,255',
+ 'gainsboro' => '220,220,220',
+ 'ghostwhite' => '248,248,255',
+ 'gold' => '255,215,0',
+ 'goldenrod' => '218,165,32',
+ 'gray' => '128,128,128',
+ 'green' => '0,128,0',
+ 'greenyellow' => '173,255,47',
+ 'grey' => '128,128,128',
+ 'honeydew' => '240,255,240',
+ 'hotpink' => '255,105,180',
+ 'indianred' => '205,92,92',
+ 'indigo' => '75,0,130',
+ 'ivory' => '255,255,240',
+ 'khaki' => '240,230,140',
+ 'lavender' => '230,230,250',
+ 'lavenderblush' => '255,240,245',
+ 'lawngreen' => '124,252,0',
+ 'lemonchiffon' => '255,250,205',
+ 'lightblue' => '173,216,230',
+ 'lightcoral' => '240,128,128',
+ 'lightcyan' => '224,255,255',
+ 'lightgoldenrodyellow' => '250,250,210',
+ 'lightgray' => '211,211,211',
+ 'lightgreen' => '144,238,144',
+ 'lightgrey' => '211,211,211',
+ 'lightpink' => '255,182,193',
+ 'lightsalmon' => '255,160,122',
+ 'lightseagreen' => '32,178,170',
+ 'lightskyblue' => '135,206,250',
+ 'lightslategray' => '119,136,153',
+ 'lightslategrey' => '119,136,153',
+ 'lightsteelblue' => '176,196,222',
+ 'lightyellow' => '255,255,224',
+ 'lime' => '0,255,0',
+ 'limegreen' => '50,205,50',
+ 'linen' => '250,240,230',
+ 'magenta' => '255,0,255',
+ 'maroon' => '128,0,0',
+ 'mediumaquamarine' => '102,205,170',
+ 'mediumblue' => '0,0,205',
+ 'mediumorchid' => '186,85,211',
+ 'mediumpurple' => '147,112,219',
+ 'mediumseagreen' => '60,179,113',
+ 'mediumslateblue' => '123,104,238',
+ 'mediumspringgreen' => '0,250,154',
+ 'mediumturquoise' => '72,209,204',
+ 'mediumvioletred' => '199,21,133',
+ 'midnightblue' => '25,25,112',
+ 'mintcream' => '245,255,250',
+ 'mistyrose' => '255,228,225',
+ 'moccasin' => '255,228,181',
+ 'navajowhite' => '255,222,173',
+ 'navy' => '0,0,128',
+ 'oldlace' => '253,245,230',
+ 'olive' => '128,128,0',
+ 'olivedrab' => '107,142,35',
+ 'orange' => '255,165,0',
+ 'orangered' => '255,69,0',
+ 'orchid' => '218,112,214',
+ 'palegoldenrod' => '238,232,170',
+ 'palegreen' => '152,251,152',
+ 'paleturquoise' => '175,238,238',
+ 'palevioletred' => '219,112,147',
+ 'papayawhip' => '255,239,213',
+ 'peachpuff' => '255,218,185',
+ 'peru' => '205,133,63',
+ 'pink' => '255,192,203',
+ 'plum' => '221,160,221',
+ 'powderblue' => '176,224,230',
+ 'purple' => '128,0,128',
+ 'red' => '255,0,0',
+ 'rosybrown' => '188,143,143',
+ 'royalblue' => '65,105,225',
+ 'saddlebrown' => '139,69,19',
+ 'salmon' => '250,128,114',
+ 'sandybrown' => '244,164,96',
+ 'seagreen' => '46,139,87',
+ 'seashell' => '255,245,238',
+ 'sienna' => '160,82,45',
+ 'silver' => '192,192,192',
+ 'skyblue' => '135,206,235',
+ 'slateblue' => '106,90,205',
+ 'slategray' => '112,128,144',
+ 'slategrey' => '112,128,144',
+ 'snow' => '255,250,250',
+ 'springgreen' => '0,255,127',
+ 'steelblue' => '70,130,180',
+ 'tan' => '210,180,140',
+ 'teal' => '0,128,128',
+ 'thistle' => '216,191,216',
+ 'tomato' => '255,99,71',
+ 'turquoise' => '64,224,208',
+ 'violet' => '238,130,238',
+ 'wheat' => '245,222,179',
+ 'white' => '255,255,255',
+ 'whitesmoke' => '245,245,245',
+ 'yellow' => '255,255,0',
+ 'yellowgreen' => '154,205,50'
+ );
+}
+
+class scss_parser {
+ static protected $precedence = array(
+ "or" => 0,
+ "and" => 1,
+
+ '==' => 2,
+ '!=' => 2,
+ '<=' => 2,
+ '>=' => 2,
+ '=' => 2,
+ '<' => 3,
+ '>' => 2,
+
+ '+' => 3,
+ '-' => 3,
+ '*' => 4,
+ '/' => 4,
+ '%' => 4,
+ );
+
+ static protected $operators = array("+", "-", "*", "/", "%",
+ "==", "!=", "<=", ">=", "<", ">", "and", "or");
+
+ static protected $operatorStr;
+ static protected $whitePattern;
+ static protected $commentMulti;
+
+ static protected $commentSingle = "//";
+ static protected $commentMultiLeft = "/*";
+ static protected $commentMultiRight = "*/";
+
+ function __construct($sourceName = null) {
+ $this->sourceName = $sourceName;
+
+ if (empty(self::$operatorStr)) {
+ self::$operatorStr = $this->makeOperatorStr(self::$operators);
+
+ $commentSingle = $this->preg_quote(self::$commentSingle);
+ $commentMultiLeft = $this->preg_quote(self::$commentMultiLeft);
+ $commentMultiRight = $this->preg_quote(self::$commentMultiRight);
+ self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight;
+ self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais';
+ }
+ }
+
+ static protected function makeOperatorStr($operators) {
+ return '('.implode('|', array_map(array('scss_parser','preg_quote'),
+ $operators)).')';
+ }
+
+ function parse($buffer) {
+ $this->count = 0;
+ $this->env = null;
+ $this->inParens = false;
+ $this->pushBlock(null); // root block
+ $this->eatWhiteDefault = true;
+ $this->insertComments = true;
+
+ $this->buffer = $buffer;
+
+ $this->whitespace();
+ while (false !== $this->parseChunk());
+
+ if ($this->count != strlen($this->buffer))
+ $this->throwParseError();
+
+ if (!empty($this->env->parent)) {
+ $this->throwParseError("unclosed block");
+ }
+
+ $this->env->isRoot = true;
+ return $this->env;
+ }
+
+ protected function parseChunk() {
+ $s = $this->seek();
+
+ // the directives
+ if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") {
+ if ($this->literal("@media") && $this->mediaQueryList($mediaQueryList) && $this->literal("{")) {
+ $media = $this->pushSpecialBlock("media");
+ $media->queryList = $mediaQueryList[2];
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@mixin") &&
+ $this->keyword($mixinName) &&
+ ($this->argumentDef($args) || true) &&
+ $this->literal("{"))
+ {
+ $mixin = $this->pushSpecialBlock("mixin");
+ $mixin->name = $mixinName;
+ $mixin->args = $args;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@include") &&
+ $this->keyword($mixinName) &&
+ ($this->literal("(") &&
+ ($this->argValues($argValues) || true) &&
+ $this->literal(")") || true) &&
+ ($this->end() ||
+ $this->literal("{") && $hasBlock = true))
+ {
+ $child = array("include",
+ $mixinName, isset($argValues) ? $argValues : null, null);
+
+ if (!empty($hasBlock)) {
+ $include = $this->pushSpecialBlock("include");
+ $include->child = $child;
+ } else {
+ $this->append($child);
+ }
+
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@import") &&
+ $this->valueList($importPath) &&
+ $this->end())
+ {
+ $this->append(array("import", $importPath));
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@extend") &&
+ $this->selectors($selector) &&
+ $this->end())
+ {
+ $this->append(array("extend", $selector));
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@function") &&
+ $this->keyword($fn_name) &&
+ $this->argumentDef($args) &&
+ $this->literal("{"))
+ {
+ $func = $this->pushSpecialBlock("function");
+ $func->name = $fn_name;
+ $func->args = $args;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@return") && $this->valueList($retVal) && $this->end()) {
+ $this->append(array("return", $retVal));
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@each") &&
+ $this->variable($varName) &&
+ $this->literal("in") &&
+ $this->valueList($list) &&
+ $this->literal("{"))
+ {
+ $each = $this->pushSpecialBlock("each");
+ $each->var = $varName[1];
+ $each->list = $list;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@while") &&
+ $this->expression($cond) &&
+ $this->literal("{"))
+ {
+ $while = $this->pushSpecialBlock("while");
+ $while->cond = $cond;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@for") &&
+ $this->variable($varName) &&
+ $this->literal("from") &&
+ $this->expression($start) &&
+ ($this->literal("through") ||
+ ($forUntil = true && $this->literal("to"))) &&
+ $this->expression($end) &&
+ $this->literal("{"))
+ {
+ $for = $this->pushSpecialBlock("for");
+ $for->var = $varName[1];
+ $for->start = $start;
+ $for->end = $end;
+ $for->until = isset($forUntil);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@if") && $this->valueList($cond) && $this->literal("{")) {
+ $if = $this->pushSpecialBlock("if");
+ $if->cond = $cond;
+ $if->cases = array();
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if (($this->literal("@debug") || $this->literal("@warn")) &&
+ $this->valueList($value) &&
+ $this->end()) {
+ $this->append(array("debug", $value, $s));
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("@content") && $this->end()) {
+ $this->append(array("mixin_content"));
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ $last = $this->last();
+ if (!is_null($last) && $last[0] == "if") {
+ list(, $if) = $last;
+ if ($this->literal("@else")) {
+ if ($this->literal("{")) {
+ $else = $this->pushSpecialBlock("else");
+ } elseif ($this->literal("if") && $this->valueList($cond) && $this->literal("{")) {
+ $else = $this->pushSpecialBlock("elseif");
+ $else->cond = $cond;
+ }
+
+ if (isset($else)) {
+ $else->dontAppend = true;
+ $if->cases[] = $else;
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ }
+
+ if ($this->literal("@charset") &&
+ $this->valueList($charset) && $this->end())
+ {
+ $this->append(array("charset", $charset));
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // doesn't match built in directive, do generic one
+ if ($this->literal("@", false) && $this->keyword($dirName) &&
+ ($this->openString("{", $dirValue) || true) &&
+ $this->literal("{"))
+ {
+ $directive = $this->pushSpecialBlock("directive");
+ $directive->name = $dirName;
+ if (isset($dirValue)) $directive->value = $dirValue;
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ // property shortcut
+ // captures most properties before having to parse a selector
+ if ($this->keyword($name, false) &&
+ $this->literal(": ") &&
+ $this->valueList($value) &&
+ $this->end())
+ {
+ $name = array("string", "", array($name));
+ $this->append(array("assign", $name, $value));
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // variable assigns
+ if ($this->variable($name) &&
+ $this->literal(":") &&
+ $this->valueList($value) && $this->end())
+ {
+ $defaultVar = false;
+ // check for !default
+ if ($value[0] == "list") {
+ $def = end($value[2]);
+ if ($def[0] == "keyword" && $def[1] == "!default") {
+ array_pop($value[2]);
+ $value = $this->flattenList($value);
+ $defaultVar = true;
+ }
+ }
+ $this->append(array("assign", $name, $value, $defaultVar));
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // misc
+ if ($this->literal("-->")) {
+ return true;
+ }
+
+ // opening css block
+ $oldComments = $this->insertComments;
+ $this->insertComments = false;
+ if ($this->selectors($selectors) && $this->literal("{")) {
+ $this->pushBlock($selectors);
+ $this->insertComments = $oldComments;
+ return true;
+ } else {
+ $this->seek($s);
+ }
+ $this->insertComments = $oldComments;
+
+ // property assign, or nested assign
+ if ($this->propertyName($name) && $this->literal(":")) {
+ $foundSomething = false;
+ if ($this->valueList($value)) {
+ $this->append(array("assign", $name, $value));
+ $foundSomething = true;
+ }
+
+ if ($this->literal("{")) {
+ $propBlock = $this->pushSpecialBlock("nestedprop");
+ $propBlock->prefix = $name;
+ $foundSomething = true;
+ } elseif ($foundSomething) {
+ $foundSomething = $this->end();
+ }
+
+ if ($foundSomething) {
+ return true;
+ }
+
+ $this->seek($s);
+ } else {
+ $this->seek($s);
+ }
+
+ // closing a block
+ if ($this->literal("}")) {
+ $block = $this->popBlock();
+ if (isset($block->type) && $block->type == "include") {
+ $include = $block->child;
+ unset($block->child);
+ $include[3] = $block;
+ $this->append($include);
+ } else if (empty($block->dontAppend)) {
+ $type = isset($block->type) ? $block->type : "block";
+ $this->append(array($type, $block));
+ }
+ return true;
+ }
+
+ // extra stuff
+ if ($this->literal(";") ||
+ $this->literal("<!--"))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function literal($what, $eatWhitespace = null) {
+ if (is_null($eatWhitespace)) $eatWhitespace = $this->eatWhiteDefault;
+
+ // this is here mainly prevent notice from { } string accessor
+ if ($this->count >= strlen($this->buffer)) return false;
+
+ // shortcut on single letter
+ if (!$eatWhitespace && strlen($what) == 1) {
+ if ($this->buffer{$this->count} == $what) {
+ $this->count++;
+ return true;
+ }
+ else return false;
+ }
+
+ return $this->match($this->preg_quote($what), $m, $eatWhitespace);
+ }
+
+ // tree builders
+
+ protected function pushBlock($selectors) {
+ $b = new stdclass;
+ $b->parent = $this->env; // not sure if we need this yet
+
+ $b->selectors = $selectors;
+ $b->children = array();
+
+ $this->env = $b;
+ return $b;
+ }
+
+ protected function pushSpecialBlock($type) {
+ $block = $this->pushBlock(null);
+ $block->type = $type;
+ return $block;
+ }
+
+ protected function popBlock() {
+ if (empty($this->env->parent)) {
+ $this->throwParseError("unexpected }");
+ }
+
+ $old = $this->env;
+ $this->env = $this->env->parent;
+ unset($old->parent);
+ return $old;
+ }
+
+ protected function append($statement) {
+ $this->env->children[] = $statement;
+ }
+
+ // last child that was appended
+ protected function last() {
+ $i = count($this->env->children) - 1;
+ if (isset($this->env->children[$i]))
+ return $this->env->children[$i];
+ }
+
+ // high level parsers (they return parts of ast)
+
+ protected function mediaQueryList(&$out) {
+ return $this->genericList($out, "mediaQuery", ",", false);
+ }
+
+ protected function mediaQuery(&$out) {
+ $s = $this->seek();
+
+ $expressions = null;
+ $parts = array();
+
+ if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) {
+ $prop = array("mediaType");
+ if (isset($only)) $prop[] = "only";
+ if (isset($not)) $prop[] = "not";
+ $prop[] = $mediaType;
+ $parts[] = $prop;
+ } else {
+ $this->seek($s);
+ }
+
+
+ if (!empty($mediaType) && !$this->literal("and")) {
+ // ~
+ } else {
+ $this->genericList($expressions, "mediaExpression", "and", false);
+ if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]);
+ }
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function mediaExpression(&$out) {
+ $s = $this->seek();
+ $value = null;
+ if ($this->literal("(") &&
+ $this->keyword($feature) &&
+ ($this->literal(":") && $this->expression($value) || true) &&
+ $this->literal(")"))
+ {
+ $out = array("mediaExp", $feature);
+ if ($value) $out[] = $value;
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function argValues(&$out) {
+ if ($this->genericList($list, "argValue", ",", false)) {
+ $out = $list[2];
+ return true;
+ }
+ return false;
+ }
+
+ protected function argValue(&$out) {
+ $s = $this->seek();
+
+ $keyword = null;
+ if (!$this->variable($keyword) || !$this->literal(":")) {
+ $this->seek($s);
+ $keyword = null;
+ }
+
+ if ($this->genericList($value, "expression")) {
+ $out = array($keyword, $value);
+ return true;
+ }
+
+ return false;
+ }
+
+
+ protected function valueList(&$out) {
+ return $this->genericList($out, "commaList");
+ }
+
+ protected function commaList(&$out) {
+ return $this->genericList($out, "expression", ",");
+ }
+
+ protected function genericList(&$out, $parseItem, $delim="", $flatten=true) {
+ $s = $this->seek();
+ $items = array();
+ while ($this->$parseItem($value)) {
+ $items[] = $value;
+ if ($delim) {
+ if (!$this->literal($delim)) break;
+ }
+ }
+
+ if (count($items) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ if ($flatten && count($items) == 1) {
+ $out = $items[0];
+ } else {
+ $out = array("list", $delim, $items);
+ }
+
+ return true;
+ }
+
+ protected function expression(&$out) {
+ $s = $this->seek();
+
+ if ($this->literal("(")) {
+ if ($this->literal(")")) {
+ $out = array("list", "", array());
+ return true;
+ }
+
+ if ($this->valueList($out) && $this->literal(')') && $out[0] == "list") {
+ return true;
+ }
+
+ $this->seek($s);
+ }
+
+ if ($this->value($lhs)) {
+ $out = $this->expHelper($lhs, 0);
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function expHelper($lhs, $minP) {
+ $opstr = self::$operatorStr;
+
+ $ss = $this->seek();
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+ while ($this->match($opstr, $m) && self::$precedence[$m[1]] >= $minP) {
+ $whiteAfter = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+
+ $op = $m[1];
+
+ // don't turn negative numbers into expressions
+ if ($op == "-" && $whiteBefore) {
+ if (!$whiteAfter) break;
+ }
+
+ if (!$this->value($rhs)) break;
+
+ // peek and see if rhs belongs to next operator
+ if ($this->peek($opstr, $next) && self::$precedence[$next[1]] > self::$precedence[$op]) {
+ $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]);
+ }
+
+ $lhs = array("exp", $op, $lhs, $rhs, $this->inParens, $whiteBefore, $whiteAfter);
+ $ss = $this->seek();
+ $whiteBefore = isset($this->buffer[$this->count - 1]) &&
+ ctype_space($this->buffer[$this->count - 1]);
+ }
+
+ $this->seek($ss);
+ return $lhs;
+ }
+
+ protected function value(&$out) {
+ $s = $this->seek();
+
+ if ($this->literal("not", false) && $this->whitespace() && $this->value($inner)) {
+ $out = array("unary", "not", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->literal("+") && $this->value($inner)) {
+ $out = array("unary", "+", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ // negation
+ if ($this->literal("-", false) &&
+ ($this->variable($inner) ||
+ $this->unit($inner) ||
+ $this->parenValue($inner)))
+ {
+ $out = array("unary", "-", $inner, $this->inParens);
+ return true;
+ } else {
+ $this->seek($s);
+ }
+
+ if ($this->parenValue($out)) return true;
+ if ($this->interpolation($out)) return true;
+ if ($this->variable($out)) return true;
+ if ($this->color($out)) return true;
+ if ($this->unit($out)) return true;
+ if ($this->string($out)) return true;
+ if ($this->func($out)) return true;
+ if ($this->progid($out)) return true;
+
+ if ($this->keyword($keyword)) {
+ $out = array("keyword", $keyword);
+ return true;
+ }
+
+ return false;
+ }
+
+ // value wrappen in parentheses
+ protected function parenValue(&$out) {
+ $s = $this->seek();
+
+ $inParens = $this->inParens;
+ if ($this->literal("(") &&
+ ($this->inParens = true) && $this->expression($exp) &&
+ $this->literal(")"))
+ {
+ $out = $exp;
+ $this->inParens = $inParens;
+ return true;
+ } else {
+ $this->inParens = $inParens;
+ $this->seek($s);
+ }
+
+ return false;
+ }
+
+ protected function progid(&$out) {
+ $s = $this->seek();
+ if ($this->literal("progid:", false) &&
+ $this->openString("(", $fn) &&
+ $this->literal("("))
+ {
+ $this->openString(")", $args, "(");
+ if ($this->literal(")")) {
+ $out = array("string", "", array(
+ "progid:", $fn, "(", $args, ")"
+ ));
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function func(&$func) {
+ $s = $this->seek();
+
+ if ($this->keyword($name, false) &&
+ $this->literal("("))
+ {
+ if ($name != "expression" && false == preg_match("/^(-[a-z]+-)?calc$/", $name)) {
+ $ss = $this->seek();
+ if ($this->argValues($args) && $this->literal(")")) {
+ $func = array("fncall", $name, $args);
+ return true;
+ }
+ $this->seek($ss);
+ }
+
+ if (($this->openString(")", $str, "(") || true ) &&
+ $this->literal(")"))
+ {
+ $args = array();
+ if (!empty($str)) {
+ $args[] = array(null, array("string", "", array($str)));
+ }
+
+ $func = array("fncall", $name, $args);
+ return true;
+ }
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function argumentDef(&$out) {
+ $s = $this->seek();
+ $this->literal("(");
+
+ $args = array();
+ while ($this->variable($var)) {
+ $arg = array($var[1], null);
+
+ $ss = $this->seek();
+ if ($this->literal(":") && $this->expression($defaultVal)) {
+ $arg[1] = $defaultVal;
+ } else {
+ $this->seek($ss);
+ }
+
+ $args[] = $arg;
+ if (!$this->literal(",")) break;
+ }
+
+ if (!$this->literal(")")) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $args;
+ return true;
+ }
+
+ protected function color(&$out) {
+ $color = array('color');
+
+ if ($this->match('(#([0-9a-f]{6})|#([0-9a-f]{3}))', $m)) {
+ if (isset($m[3])) {
+ $num = $m[3];
+ $width = 16;
+ } else {
+ $num = $m[2];
+ $width = 256;
+ }
+
+ $num = hexdec($num);
+ foreach (array(3,2,1) as $i) {
+ $t = $num % $width;
+ $num /= $width;
+
+ $color[$i] = $t * (256/$width) + $t * floor(16/$width);
+ }
+
+ $out = $color;
+ return true;
+ }
+
+ return false;
+ }
+
+ protected function unit(&$unit) {
+ if ($this->match('([0-9]*(\.)?[0-9]+)([%a-zA-Z]+)?', $m)) {
+ $unit = array("number", $m[1], empty($m[3]) ? "" : $m[3]);
+ return true;
+ }
+ return false;
+ }
+
+ protected function string(&$out) {
+ $s = $this->seek();
+ if ($this->literal('"', false)) {
+ $delim = '"';
+ } elseif ($this->literal("'", false)) {
+ $delim = "'";
+ } else {
+ return false;
+ }
+
+ $content = array();
+
+ // look for either ending delim , escape, or string interpolation
+ $patt = '([^\n]*?)(#\{|\\\\|' .
+ $this->preg_quote($delim).')';
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while ($this->match($patt, $m, false)) {
+ $content[] = $m[1];
+ if ($m[2] == "#{") {
+ $this->count -= strlen($m[2]);
+ if ($this->interpolation($inter, false)) {
+ $content[] = $inter;
+ } else {
+ $this->count += strlen($m[2]);
+ $content[] = "#{"; // ignore it
+ }
+ } elseif ($m[2] == '\\') {
+ $content[] = $m[2];
+ if ($this->literal($delim, false)) {
+ $content[] = $delim;
+ }
+ } else {
+ $this->count -= strlen($delim);
+ break; // delim
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if ($this->literal($delim)) {
+ $out = array("string", $delim, $content);
+ return true;
+ }
+
+ $this->seek($s);
+ return false;
+ }
+
+ protected function mixedKeyword(&$out) {
+ $s = $this->seek();
+
+ $parts = array();
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while (true) {
+ if ($this->keyword($key)) {
+ $parts[] = $key;
+ continue;
+ }
+
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ continue;
+ }
+
+ break;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($parts) == 0) return false;
+
+ $out = $parts;
+ return true;
+ }
+
+ // an unbounded string stopped by $end
+ protected function openString($end, &$out, $nestingOpen=null) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $stop = array("'", '"', "#{", $end);
+ $stop = array_map(array($this, "preg_quote"), $stop);
+ $stop[] = self::$commentMulti;
+
+ $patt = '(.*?)('.implode("|", $stop).')';
+
+ $nestingLevel = 0;
+
+ $content = array();
+ while ($this->match($patt, $m, false)) {
+ if (!empty($m[1])) {
+ $content[] = $m[1];
+ if ($nestingOpen) {
+ $nestingLevel += substr_count($m[1], $nestingOpen);
+ }
+ }
+
+ $tok = $m[2];
+
+ $this->count-= strlen($tok);
+ if ($tok == $end) {
+ if ($nestingLevel == 0) {
+ break;
+ } else {
+ $nestingLevel--;
+ }
+ }
+
+ if (($tok == "'" || $tok == '"') && $this->string($str)) {
+ $content[] = $str;
+ continue;
+ }
+
+ if ($tok == "#{" && $this->interpolation($inter)) {
+ $content[] = $inter;
+ continue;
+ }
+
+ $content[] = $tok;
+ $this->count+= strlen($tok);
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($content) == 0) return false;
+
+ // trim the end
+ if (is_string(end($content))) {
+ $content[count($content) - 1] = rtrim(end($content));
+ }
+
+ $out = array("string", "", $content);
+ return true;
+ }
+
+ // $lookWhite: save information about whitespace before and after
+ protected function interpolation(&$out, $lookWhite=true) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = true;
+
+ $s = $this->seek();
+ if ($this->literal("#{") && $this->valueList($value) && $this->literal("}", false)) {
+
+ // TODO: don't error if out of bounds
+
+ if ($lookWhite) {
+ $left = preg_match('/\s/', $this->buffer[$s - 1]) ? " " : "";
+ $right = preg_match('/\s/', $this->buffer[$this->count]) ? " ": "";
+ } else {
+ $left = $right = false;
+ }
+
+ $out = array("interpolate", $value, $left, $right);
+ $this->eatWhiteDefault = $oldWhite;
+ if ($this->eatWhiteDefault) $this->whitespace();
+ return true;
+ }
+
+ $this->seek($s);
+ $this->eatWhiteDefault = $oldWhite;
+ return false;
+ }
+
+ // low level parsers
+
+ // returns an array of parts or a string
+ protected function propertyName(&$out) {
+ $s = $this->seek();
+ $parts = array();
+
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ while (true) {
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ } elseif ($this->keyword($text)) {
+ $parts[] = $text;
+ } elseif (count($parts) == 0 && $this->match('[:.#]', $m, false)) {
+ // css hacks
+ $parts[] = $m[0];
+ } else {
+ break;
+ }
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+ if (count($parts) == 0) return false;
+
+ // match comment hack
+ if (preg_match(self::$whitePattern,
+ $this->buffer, $m, null, $this->count))
+ {
+ if (!empty($m[0])) {
+ $parts[] = $m[0];
+ $this->count += strlen($m[0]);
+ }
+ }
+
+ $this->whitespace(); // get any extra whitespace
+
+ $out = array("string", "", $parts);
+ return true;
+ }
+
+ // comma separated list of selectors
+ protected function selectors(&$out) {
+ $s = $this->seek();
+ $selectors = array();
+ while ($this->selector($sel)) {
+ $selectors[] = $sel;
+ if (!$this->literal(",")) break;
+ while ($this->literal(",")); // ignore extra
+ }
+
+ if (count($selectors) == 0) {
+ $this->seek($s);
+ return false;
+ }
+
+ $out = $selectors;
+ return true;
+ }
+
+ // whitepsace separated list of selectorSingle
+ protected function selector(&$out) {
+ $selector = array();
+
+ while (true) {
+ if ($this->match('[>+~]+', $m)) {
+ $selector[] = array($m[0]);
+ } elseif ($this->selectorSingle($part)) {
+ $selector[] = $part;
+ $this->whitespace();
+ } else {
+ break;
+ }
+
+ }
+
+ if (count($selector) == 0) {
+ return false;
+ }
+
+ $out = $selector;
+ return true;
+ }
+
+ // the parts that make up
+ // div[yes=no]#something.hello.world:nth-child(-2n+1)
+ protected function selectorSingle(&$out) {
+ $oldWhite = $this->eatWhiteDefault;
+ $this->eatWhiteDefault = false;
+
+ $parts = array();
+
+ if ($this->literal("*", false)) {
+ $parts[] = "*";
+ }
+
+ while (true) {
+ // see if we can stop early
+ if ($this->match("\s*[{,]", $m)) {
+ $this->count--;
+ break;
+ }
+
+ $s = $this->seek();
+ // self
+ if ($this->literal("&", false)) {
+ $parts[] = scssc::$selfSelector;
+ continue;
+ }
+
+ if ($this->literal(".", false)) {
+ $parts[] = ".";
+ continue;
+ }
+
+ if ($this->literal("|", false)) {
+ $parts[] = "|";
+ continue;
+ }
+
+ // for keyframes
+ if ($this->unit($unit)) {
+ $parts[] = $unit;
+ continue;
+ }
+
+ if ($this->keyword($name)) {
+ $parts[] = $name;
+ continue;
+ }
+
+ if ($this->interpolation($inter)) {
+ $parts[] = $inter;
+ continue;
+ }
+
+ if ($this->literal("#", false)) {
+ $parts[] = "#";
+ continue;
+ }
+
+ // a pseudo selector
+ if ($this->match("::?", $m) && $this->mixedKeyword($nameParts)) {
+ $parts[] = $m[0];
+ foreach ($nameParts as $sub) {
+ $parts[] = $sub;
+ }
+
+ $ss = $this->seek();
+ if ($this->literal("(") &&
+ ($this->openString(")", $str, "(") || true ) &&
+ $this->literal(")"))
+ {
+ $parts[] = "(";
+ if (!empty($str)) $parts[] = $str;
+ $parts[] = ")";
+ } else {
+ $this->seek($ss);
+ }
+
+ continue;
+ } else {
+ $this->seek($s);
+ }
+
+ // attribute selector
+ // TODO: replace with open string?
+ if ($this->literal("[", false)) {
+ $attrParts = array("[");
+ // keyword, string, operator
+ while (true) {
+ if ($this->literal("]", false)) {
+ $this->count--;
+ break; // get out early
+ }
+
+ if ($this->match('\s+', $m)) {
+ $attrParts[] = " ";
+ continue;
+ }
+ if ($this->string($str)) {
+ $attrParts[] = $str;
+ continue;
+ }
+
+ if ($this->keyword($word)) {
+ $attrParts[] = $word;
+ continue;
+ }
+
+ if ($this->interpolation($inter, false)) {
+ $attrParts[] = $inter;
+ continue;
+ }
+
+ // operator, handles attr namespace too
+ if ($this->match('[|-~\$\*\^=]+', $m)) {
+ $attrParts[] = $m[0];
+ continue;
+ }
+
+ break;
+ }
+
+ if ($this->literal("]", false)) {
+ $attrParts[] = "]";
+ foreach ($attrParts as $part) {
+ $parts[] = $part;
+ }
+ continue;
+ }
+ $this->seek($s);
+ // should just break here?
+ }
+
+ break;
+ }
+
+ $this->eatWhiteDefault = $oldWhite;
+
+ if (count($parts) == 0) return false;
+
+ $out = $parts;
+ return true;
+ }
+
+ protected function variable(&$out) {
+ $s = $this->seek();
+ if ($this->literal("$", false) && $this->keyword($name)) {
+ $out = array("var", $name);
+ return true;
+ }
+ $this->seek($s);
+ return false;
+ }
+
+ protected function keyword(&$word, $eatWhitespace = null) {
+ if ($this->match('([\w_\-\*!"\'\\\\][\w\-_"\'\\\\]*)',
+ $m, $eatWhitespace))
+ {
+ $word = $m[1];
+ return true;
+ }
+ return false;
+ }
+
+ // consume an end of statement delimiter
+ protected function end() {
+ if ($this->literal(';')) {
+ return true;
+ } elseif ($this->count == strlen($this->buffer) || $this->buffer{$this->count} == '}') {
+ // if there is end of file or a closing block next then we don't need a ;
+ return true;
+ }
+ return false;
+ }
+
+ // advance counter to next occurrence of $what
+ // $until - don't include $what in advance
+ // $allowNewline, if string, will be used as valid char set
+ protected function to($what, &$out, $until = false, $allowNewline = false) {
+ if (is_string($allowNewline)) {
+ $validChars = $allowNewline;
+ } else {
+ $validChars = $allowNewline ? "." : "[^\n]";
+ }
+ if (!$this->match('('.$validChars.'*?)'.$this->preg_quote($what), $m, !$until)) return false;
+ if ($until) $this->count -= strlen($what); // give back $what
+ $out = $m[1];
+ return true;
+ }
+
+ protected function throwParseError($msg = "parse error", $count = null) {
+ $count = is_null($count) ? $this->count : $count;
+
+ $line = $this->getLineNo($count);
+
+ if (!empty($this->sourceName)) {
+ $loc = "$this->sourceName on line $line";
+ } else {
+ $loc = "line: $line";
+ }
+
+ if ($this->peek("(.*?)(\n|$)", $m, $count)) {
+ throw new exception("$msg: failed at `$m[1]` $loc");
+ } else {
+ throw new exception("$msg: $loc");
+ }
+ }
+
+ public function getLineNo($pos) {
+ return 1 + substr_count(substr($this->buffer, 0, $pos), "\n");
+ }
+
+ // try to match something on head of buffer
+ protected function match($regex, &$out, $eatWhitespace = null) {
+ if (is_null($eatWhitespace)) $eatWhitespace = $this->eatWhiteDefault;
+
+ $r = '/'.$regex.'/Ais';
+ if (preg_match($r, $this->buffer, $out, null, $this->count)) {
+ $this->count += strlen($out[0]);
+ if ($eatWhitespace) $this->whitespace();
+ return true;
+ }
+ return false;
+ }
+
+ // match some whitespace
+ protected function whitespace() {
+ $gotWhite = false;
+ while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) {
+ if ($this->insertComments) {
+ if (isset($m[1]) && empty($this->commentsSeen[$this->count])) {
+ $this->append(array("comment", $m[1]));
+ $this->commentsSeen[$this->count] = true;
+ }
+ }
+ $this->count += strlen($m[0]);
+ $gotWhite = true;
+ }
+ return $gotWhite;
+ }
+
+ protected function peek($regex, &$out, $from=null) {
+ if (is_null($from)) $from = $this->count;
+
+ $r = '/'.$regex.'/Ais';
+ $result = preg_match($r, $this->buffer, $out, null, $from);
+
+ return $result;
+ }
+
+ protected function seek($where = null) {
+ if ($where === null) return $this->count;
+ else $this->count = $where;
+ return true;
+ }
+
+ static function preg_quote($what) {
+ return preg_quote($what, '/');
+ }
+
+ protected function show() {
+ if ($this->peek("(.*?)(\n|$)", $m, $this->count)) {
+ return $m[1];
+ }
+ return "";
+ }
+
+ // turn list of length 1 into value type
+ protected function flattenList($value) {
+ if ($value[0] == "list" && count($value[2]) == 1) {
+ return $this->flattenList($value[2][0]);
+ }
+ return $value;
+ }
+}
+
+class scss_formatter {
+ public $indentChar = " ";
+
+ public $break = "\n";
+ public $open = " {";
+ public $close = "}";
+ public $tagSeparator = ", ";
+ public $assignSeparator = ": ";
+
+ public function __construct() {
+ $this->indentLevel = 0;
+ }
+
+ public function indentStr($n = 0) {
+ return str_repeat($this->indentChar, max($this->indentLevel + $n, 0));
+ }
+
+ public function property($name, $value) {
+ return $name . $this->assignSeparator . $value . ";";
+ }
+
+ public function block($block) {
+ if (empty($block->lines) && empty($block->children)) return;
+
+ $inner = $pre = $this->indentStr();
+
+ if (!empty($block->selectors)) {
+ echo $pre .
+ implode($this->tagSeparator, $block->selectors) .
+ $this->open . $this->break;
+ $this->indentLevel++;
+ $inner = $this->indentStr();
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!empty($block->children)) {
+ echo $this->break;
+ }
+ }
+
+ foreach ($block->children as $child) {
+ $this->block($child);
+ }
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel--;
+ if (empty($block->children)) echo $this->break;
+ echo $pre . $this->close . $this->break;
+ }
+ }
+}
+
+
+class scss_formatter_nested extends scss_formatter {
+ public $close = " }";
+
+ // adjust the depths of all children, depth first
+ public function adjustAllChildren($block) {
+ // flatten empty nested blocks
+ $children = array();
+ foreach ($block->children as $i => $child) {
+ if (empty($child->lines) && empty($child->children)) {
+ if (isset($block->children[$i + 1])) {
+ $block->children[$i + 1]->depth = $child->depth;
+ }
+ continue;
+ }
+ $children[] = $child;
+ }
+ $block->children = $children;
+
+ // make relative to parent
+ foreach ($block->children as $child) {
+ $this->adjustAllChildren($child);
+ $child->depth = $child->depth - $block->depth;
+ }
+ }
+
+ public function block($block) {
+ if ($block->type == "root") {
+ $this->adjustAllChildren($block);
+ }
+
+ $inner = $pre = $this->indentStr($block->depth - 1);
+ if (!empty($block->selectors)) {
+ echo $pre .
+ implode($this->tagSeparator, $block->selectors) .
+ $this->open . $this->break;
+ $this->indentLevel++;
+ $inner = $this->indentStr($block->depth - 1);
+ }
+
+ if (!empty($block->lines)) {
+ $glue = $this->break.$inner;
+ echo $inner . implode($glue, $block->lines);
+ if (!empty($block->children)) echo $this->break;
+ }
+
+ foreach ($block->children as $i => $child) {
+ // echo "*** block: ".$block->depth." child: ".$child->depth."\n";
+ $this->block($child);
+ if ($i < count($block->children) - 1) {
+ echo $this->break;
+
+ if (isset($block->children[$i + 1])) {
+ $next = $block->children[$i + 1];
+ if ($next->depth == max($block->depth, 1) && $child->depth >= $next->depth) {
+ echo $this->break;
+ }
+ }
+ }
+ }
+
+ if (!empty($block->selectors)) {
+ $this->indentLevel--;
+ echo $this->close;
+ }
+
+ if ($block->type == "root") {
+ echo $this->break;
+ }
+ }
+}
+
+class scss_formatter_compressed extends scss_formatter {
+ public $open = "{";
+ public $tagSeparator = ",";
+ public $assignSeparator = ":";
+ public $break = "";
+
+ public function indentStr($n = 0) {
+ return "";
+ }
+}
+
+class scss_server {
+
+ protected function join($left, $right) {
+ return rtrim($left, "/") . "/" . ltrim($right, "/");
+ }
+
+ protected function inputName() {
+ if (isset($_GET["p"])) return $_GET["p"];
+
+ if (isset($_SERVER["PATH_INFO"])) return $_SERVER["PATH_INFO"];
+ if (isset($_SERVER["DOCUMENT_URI"])) {
+ return substr($_SERVER["DOCUMENT_URI"], strlen($_SERVER["SCRIPT_NAME"]));
+ }
+ }
+
+ protected function findInput() {
+ if ($input = $this->inputName()) {
+ $name = $this->join($this->dir, $input);
+ if (is_readable($name)) return $name;
+ }
+ return false;
+ }
+
+ protected function cacheName($fname) {
+ return $this->join($this->cacheDir, md5($fname) . ".css");
+ }
+
+ protected function importsCacheName($out) {
+ return $out . ".imports";
+ }
+
+ protected function needsCompile($in, $out) {
+ if (!is_file($out)) return true;
+
+ $mtime = filemtime($out);
+ if (filemtime($in) > $mtime) return true;
+
+ // look for modified imports
+ $icache = $this->importsCacheName($out);
+ if (is_readable($icache)) {
+ $imports = unserialize(file_get_contents($icache));
+ foreach ($imports as $import) {
+ if (filemtime($import) > $mtime) return true;
+ }
+ }
+ return false;
+ }
+
+ protected function compile($in, $out) {
+ $start = microtime(true);
+ $css = $this->scss->compile(file_get_contents($in), $in);
+ $elapsed = round((microtime(true) - $start), 4);
+
+ $v = scssc::$VERSION;
+ $t = date("r");
+ $css = "/* compiled by scssphp $v on $t (${elapsed}s) */\n\n" . $css;
+
+ file_put_contents($out, $css);
+ file_put_contents($this->importsCacheName($out),
+ serialize($this->scss->getParsedFiles()));
+ return $css;
+ }
+
+ public function serve() {
+ if ($input = $this->findInput()) {
+ $output = $this->cacheName($input);
+ header("Content-type: text/css");
+
+ if ($this->needsCompile($input, $output)) {
+ try {
+ echo $this->compile($input, $output);
+ } catch (exception $e) {
+ header('HTTP/1.1 500 Internal Server Error');
+ echo "Parse error: " . $e->getMessage() . "\n";
+ }
+ } else {
+ header('X-SCSS-Cache: true');
+ echo file_get_contents($output);
+ }
+
+ return;
+ }
+
+ header('HTTP/1.0 404 Not Found');
+ header("Content-type: text");
+ $v = scssc::$VERSION;
+ echo "/* INPUT NOT FOUND scss $v */\n";
+ }
+
+ public function __construct($dir, $cacheDir=null, $scss=null) {
+ $this->dir = $dir;
+
+ if (is_null($cacheDir)) {
+ $cacheDir = $this->join($dir, "scss_cache");
+ }
+
+ $this->cacheDir = $cacheDir;
+ if (!is_dir($this->cacheDir)) mkdir($this->cacheDir);
+
+ if (is_null($scss)) {
+ $scss = new scssc();
+ $scss->setImportPaths($this->dir);
+ }
+ $this->scss = $scss;
+ }
+
+ static public function serveFrom($path) {
+ $server = new self($path);
+ $server->serve();
+ }
+}
+
+
diff --git a/plugins/jetpack/modules/enhanced-distribution.php b/plugins/jetpack/modules/enhanced-distribution.php
index c3bc7aaf..b2a80155 100644
--- a/plugins/jetpack/modules/enhanced-distribution.php
+++ b/plugins/jetpack/modules/enhanced-distribution.php
@@ -6,4 +6,25 @@
* First Introduced: 1.2
*/
-// Stub
+Jetpack_Sync::sync_posts( __FILE__ );
+Jetpack_Sync::sync_comments( __FILE__ );
+
+function jetpack_enhanced_distribution_activate() {
+ Jetpack::check_privacy( __FILE__ );
+}
+
+
+// In case it's active prior to upgrading to 1.9
+function jetpack_enhanced_distribution_before_activate_default_modules() {
+ $old_version = Jetpack::get_option( 'old_version' );
+ list( $old_version ) = explode( ':', $old_version );
+
+ if ( version_compare( $old_version, '1.9-something', '>=' ) ) {
+ return;
+ }
+
+ Jetpack::check_privacy( __FILE__ );
+}
+
+add_action( 'jetpack_activate_module_enhanced-distribution', 'jetpack_enhanced_distribution_activate' );
+add_action( 'jetpack_before_activate_default_modules', 'jetpack_enhanced_distribution_before_activate_default_modules' );
diff --git a/plugins/jetpack/modules/featured-content/featured-content.php b/plugins/jetpack/modules/featured-content/featured-content.php
new file mode 100644
index 00000000..9cd511ed
--- /dev/null
+++ b/plugins/jetpack/modules/featured-content/featured-content.php
@@ -0,0 +1,454 @@
+<?php
+
+/**
+ * Featured Content.
+ *
+ * This module will allow users to define a subset of posts
+ * to be displayed in a theme-designated featured content area.
+ *
+ * This feature will only be activated for themes that declare
+ * that they support it. This can be done by adding code similar
+ * to the following during the "after_setup_theme" action:
+ *
+ * add_theme_support( 'featured-content', array(
+ * 'featured_content_filter' => 'mytheme_get_featured_content',
+ * 'description' => 'Describe the featured content area.',
+ * 'max_posts' => 20,
+ * ) );
+ *
+ * For maximum compatibility with different methods of posting
+ * users will designate a featured post tag to associate posts
+ * to. Since this tag now has special meaning beyond that of a
+ * normal tags, users will have the ability to hide it from the
+ * front-end of their site.
+ */
+class Featured_Content {
+
+ /**
+ * The maximum number of posts that a featured content
+ * area can contain. We define a default value here but
+ * themes can override this by defining a "max_posts"
+ * entry in the second parameter passed in the call to
+ * add_theme_support( 'featured-content' ).
+ *
+ * @see Featured_Content::init()
+ */
+ public static $max_posts = 15;
+
+ /**
+ * Instantiate.
+ *
+ * All custom functionality will be hooked into the "init" action.
+ */
+ public static function setup() {
+ add_action( 'init', array( __class__, 'init' ) );
+ }
+
+ /**
+ * Conditionally Hook into WordPress.
+ *
+ * Themes must declare that they support this module by adding
+ * add_theme_support( 'featured-content' ); during after_setup_theme.
+ *
+ * If no theme support is found there is no need to hook into
+ * WordPress. We'll just return early instead.
+ *
+ * @uses Featured_Content::$max_posts
+ */
+ public static function init() {
+ $theme_support = get_theme_support( 'featured-content' );
+
+ // Return early if theme does not support featured content.
+ if ( ! $theme_support )
+ return;
+
+ // An array of named arguments must be passed as
+ // the second parameter of add_theme_support().
+ if ( ! isset( $theme_support[0] ) )
+ return;
+
+ // Return early if "featured_content_filter" has not been defined.
+ if ( ! isset( $theme_support[0]['featured_content_filter'] ) )
+ return;
+
+ $filter = $theme_support[0]['featured_content_filter'];
+
+ // Themes can override the number of max posts.
+ if ( isset( $theme_support[0]['max_posts'] ) )
+ self::$max_posts = absint( $theme_support[0]['max_posts'] );
+
+ add_filter( $filter, array( __CLASS__, 'get_featured_posts' ) );
+ add_action( 'admin_init', array( __CLASS__, 'register_setting' ) );
+ add_action( 'save_post', array( __CLASS__, 'delete_transient' ) );
+ add_action( 'delete_post_tag', array( __CLASS__, 'delete_post_tag' ) );
+ add_action( 'pre_get_posts', array( __CLASS__, 'pre_get_posts' ) );
+
+ // Hide "featured" tag from the front-end.
+ if ( self::get_setting( 'hide-tag' ) ) {
+ add_filter( 'get_terms', array( __CLASS__, 'hide_featured_term' ), 10, 2 );
+ add_filter( 'get_the_terms', array( __CLASS__, 'hide_the_featured_term' ), 10, 3 );
+ }
+ }
+
+ /**
+ * Get Featured Posts.
+ *
+ * This method is not intended to be called directly.
+ * Theme developers should place a filter directly in
+ * their theme and then pass its name as a value of the
+ * "featured_content_filter" key in the array passed as
+ * the $args parameter during the call to:
+ * add_theme_support( 'featured-content', $args ).
+ *
+ * @uses Featured_Content::get_featured_post_ids()
+ *
+ * @return array|bool
+ */
+ public static function get_featured_posts() {
+ $post_ids = self::get_featured_post_ids();
+
+ // User has disabled Featured Content.
+ if ( false === $post_ids )
+ return false;
+
+ // No need to query if there is are no featured posts.
+ if ( empty( $post_ids ) )
+ return array();
+
+ $featured_posts = get_posts( array(
+ 'include' => $post_ids,
+ 'posts_per_page' => count( $post_ids )
+ ) );
+
+ return $featured_posts;
+ }
+
+ /**
+ * Get Featured Post IDs.
+ *
+ * This function will return the an array containing the
+ * post IDs of all featured posts.
+ *
+ * Sets the "featured_content_ids" transient.
+ *
+ * @return array|false Array of post IDs. false if user has disabled this feature.
+ */
+ public static function get_featured_post_ids() {
+ $settings = self::get_setting();
+
+ // Return false if the user has disabled this feature.
+ $tag = $settings['tag-id'];
+ if ( empty( $tag ) )
+ return false;
+
+ // Return array of cached results if they exist.
+ $featured_ids = get_transient( 'featured_content_ids' );
+ if ( ! empty( $featured_ids ) )
+ return array_map( 'absint', (array) $featured_ids );
+
+ // Query for featured posts.
+ $featured = get_posts( array(
+ 'numberposts' => $settings['quantity'],
+ 'tax_query' => array(
+ array(
+ 'field' => 'term_id',
+ 'taxonomy' => 'post_tag',
+ 'terms' => $tag,
+ ),
+ ),
+ ) );
+
+ // Return empty array if no featured content exists.
+ if ( ! $featured )
+ return array();
+
+ // Ensure correct format before save/return.
+ $featured_ids = wp_list_pluck( (array) $featured, 'ID' );
+ $featured_ids = array_map( 'absint', $featured_ids );
+
+ set_transient( 'featured_content_ids', $featured_ids );
+
+ return $featured_ids;
+ }
+
+ /**
+ * Delete Transient.
+ *
+ * Hooks in the "save_post" action.
+ * @see Featured_Content::validate_settings().
+ */
+ public static function delete_transient() {
+ delete_transient( 'featured_content_ids' );
+ }
+
+ /**
+ * Exclude featured posts from the blog query when the blog is the front-page.
+ *
+ * Filter the home page posts, and remove any featured post ID's from it. Hooked
+ * onto the 'pre_get_posts' action, this changes the parameters of the query
+ * before it gets any posts.
+ *
+ * @uses Featured_Content::get_featured_post_ids();
+ * @param WP_Query $query
+ * @return WP_Query Possibly modified WP_query
+ */
+ public static function pre_get_posts( $query = false ) {
+
+ // Bail if not home, not a query, not main query.
+ if ( ! is_home() || ! is_a( $query, 'WP_Query' ) || ! $query->is_main_query() )
+ return;
+
+ $page_on_front = get_option( 'page_on_front' );
+
+ // Bail if the blog page is not the front page.
+ if ( ! empty( $page_on_front ) )
+ return;
+
+ $featured = self::get_featured_post_ids();
+
+ // Bail if no featured posts.
+ if ( ! $featured )
+ return;
+
+ // We need to respect post ids already in the blacklist.
+ $post__not_in = $query->get( 'post__not_in' );
+
+ if ( ! empty( $post__not_in ) ) {
+ $featured = array_merge( (array) $post__not_in, $featured );
+ $featured = array_unique( $featured );
+ }
+
+ $query->set( 'post__not_in', $featured );
+ }
+
+ /**
+ * Reset tag option when the saved tag is deleted.
+ *
+ * It's important to mention that the transient needs
+ * to be deleted too. While it may not be obvious by
+ * looking at the function alone, the transient is
+ * deleted by Featured_Content::validate_settings().
+ *
+ * @param int $tag_id the term_id of the tag that has been deleted.
+ *
+ * Hooks in the "delete_post_tag" action.
+ * @see Featured_Content::validate_settings().
+ */
+ public static function delete_post_tag( $tag_id ) {
+ $settings = self::get_setting();
+
+ if ( empty( $settings['tag-id'] ) )
+ return;
+
+ if ( $tag_id != $settings['tag-id'] )
+ return;
+
+ $settings['tag-id'] = 0;
+ $settings = self::validate_settings( $settings );
+ update_option( 'featured-content', $settings );
+ }
+
+ /**
+ * Hide featured tag from displaying when global terms are queried from the front-end.
+ *
+ * Hooks into the "get_terms" filter.
+ *
+ * @param array $terms A list of term objects. This is the return value of get_terms().
+ * @param array $taxonomies An array of taxonomy slugs.
+ *
+ * @uses Featured_Content::get_setting()
+ */
+ public static function hide_featured_term( $terms, $taxonomies ) {
+
+ // This filter is only appropriate on the front-end.
+ if ( is_admin() )
+ return $terms;
+
+ // We only want to hide the featured tag.
+ if ( ! in_array( 'post_tag', $taxonomies ) )
+ return $terms;
+
+ // Bail if no terms were returned.
+ if ( empty( $terms ) )
+ return $terms;
+
+ foreach( $terms as $order => $term ) {
+ if ( self::get_setting( 'tag-id' ) == $term->term_id && 'post_tag' == $term->taxonomy )
+ unset( $terms[$order] );
+ }
+
+ return $terms;
+ }
+
+ /**
+ * Hide featured tag from displaying when terms associated with
+ * a post object are queried from the front-end.
+ *
+ * Hooks into the "get_the_terms" filter.
+ *
+ * @param array $terms A list of term objects. This is the return value of get_the_terms().
+ * @param int $id The ID field for the post object that terms are associated with.
+ * @param array $taxonomy An array of taxonomy slugs.
+ *
+ * @uses Featured_Content::get_setting()
+ */
+ public static function hide_the_featured_term( $terms, $id, $taxonomy ) {
+
+ // This filter is only appropriate on the front-end.
+ if ( is_admin() )
+ return $terms;
+
+ // Make sure we are in the correct taxonomy.
+ if ( ! 'post_tag' == $taxonomy )
+ return $terms;
+
+ // No terms? Return early!
+ if ( empty( $terms ) )
+ return $terms;
+
+ foreach( $terms as $order => $term ) {
+ if ( self::get_setting( 'tag-id' ) == $term->term_id )
+ unset( $terms[$term->term_id] );
+ }
+
+ return $terms;
+ }
+
+ /**
+ * Register custom setting on the Settings -> Reading screen.
+ *
+ * @uses Featured_Content::render_form()
+ * @uses Featured_Content::validate_settings()
+ */
+ public static function register_setting() {
+ add_settings_field( 'featured-content', __( 'Featured content', 'jetpack' ), array( __class__, 'render_form' ), 'reading' );
+ register_setting( 'reading', 'featured-content', array( __class__, 'validate_settings' ) );
+ }
+
+ /**
+ * Renders all form fields on the Settings -> Reading screen.
+ */
+ public static function render_form() {
+ $settings = self::get_setting();
+
+ $tag_name = '';
+ if ( ! empty( $settings['tag-id'] ) ) {
+ $tag = get_term( $settings['tag-id'], 'post_tag' );
+ if ( ! is_wp_error( $tag ) && isset( $tag->name ) )
+ $tag_name = $tag->name;
+ }
+ ?>
+ <div id="featured-content-ui">
+ <p>
+ <label for="featured-content-tag-name"><?php echo _e( 'Tag name:', 'jetpack' ); ?></label>
+ <input type="text" id="featured-content-tag-name" name="featured-content[tag-name]" value="<?php echo esc_attr( $tag_name ); ?>">
+ <input type="hidden" id="featured-content-tag-id" name="featured-content[tag-id]" value="<?php echo esc_attr( $settings['tag-id'] ); ?>">
+ </p>
+ <p>
+ <label for="featured-content-quantity"><?php _e( 'Number of posts:', 'jetpack' ); ?></label>
+ <input class="small-text" type="number" step="1" min="1" max="<?php echo esc_attr( self::$max_posts ); ?>" id="featured-content-quantity" name="featured-content[quantity]" value="<?php echo esc_attr( $settings['quantity'] ); ?>">
+ </p>
+ <p>
+ <input type="checkbox" id="featured-content-hide-tag" name="featured-content[hide-tag]" <?php checked( $settings['hide-tag'], 1 ); ?>">
+ <label for="featured-content-hide-tag"><?php _e( 'Hide tag from displaying in post meta and tag clouds.', 'jetpack' ); ?></label>
+ </p>
+ </div>
+ <?php
+ }
+
+ /**
+ * Get Settings.
+ *
+ * Get all settings recognized by this module. This
+ * function will return all settings whether or not
+ * they have been stored in the database yet. This
+ * ensures that all keys are available at all times.
+ *
+ * In the event that you only require one setting, you
+ * may pass its name as the first parameter to the function
+ * and only that value will be returned.
+ *
+ * @uses Featured_Content::self::sanitize_quantity()
+ *
+ * @param string $key The key of a recognized setting.
+ * @return mixed Array of all settings by default. A single value if passed as first parameter.
+ */
+ public static function get_setting( $key = 'all' ) {
+ $saved = (array) get_option( 'featured-content' );
+
+ $defaults = array(
+ 'hide-tag' => 1,
+ 'quantity' => 5,
+ 'tag-id' => 0,
+ );
+
+ $options = wp_parse_args( $saved, $defaults );
+ $options = array_intersect_key( $options, $defaults );
+ $options['quantity'] = self::sanitize_quantity( $options['quantity'] );
+
+ if ( 'all' != $key ) {
+ if ( isset( $options[$key] ) )
+ return $options[$key];
+ else
+ return false;
+ }
+
+ return $options;
+ }
+
+ /**
+ * Validate Settings.
+ *
+ * Make sure that all user supplied content is in an
+ * expected format before saving to the database. This
+ * function will also delete the transient set in
+ * Featured_Content::get_featured_content().
+ *
+ * @uses Featured_Content::self::sanitize_quantity()
+ * @uses Featured_Content::self::delete_transient()
+ */
+ function validate_settings( $input ) {
+ $output = array();
+
+ if ( isset( $input['tag-id'] ) )
+ $output['tag-id'] = absint( $input['tag-id'] );
+
+ if ( isset( $input['tag-name'] ) ) {
+ $new_tag = wp_create_tag( $input['tag-name'] );
+ if ( ! is_wp_error( $new_tag ) && isset( $new_tag['term_id'] ) )
+ $tag = get_term( $new_tag['term_id'], 'post_tag' );
+ if ( isset( $tag->term_id ) )
+ $output['tag-id'] = $tag->term_id;
+ }
+
+ if ( isset( $input['quantity'] ) )
+ $output['quantity'] = self::sanitize_quantity( $input['quantity'] );
+
+ $output['hide-tag'] = ( isset( $input['hide-tag'] ) ) ? 1 : 0;
+
+ self::delete_transient();
+
+ return $output;
+ }
+
+ /**
+ * Sanitize Quantity
+ *
+ * @param int $input The value to sanitize.
+ * @output int A number between 1 and FeaturedContent::$max_posts.
+ *
+ * @uses Featured_Content::$max_posts
+ */
+ public static function sanitize_quantity( $input ) {
+ $quantity = absint( $input );
+
+ if ( $quantity > self::$max_posts )
+ $quantity = self::$max_posts;
+ else if ( 1 > $quantity )
+ $quantity = 1;
+
+ return $quantity;
+ }
+}
+
+Featured_Content::setup();
diff --git a/plugins/jetpack/modules/gravatar-hovercards.php b/plugins/jetpack/modules/gravatar-hovercards.php
index 3678837f..9edd15a5 100644
--- a/plugins/jetpack/modules/gravatar-hovercards.php
+++ b/plugins/jetpack/modules/gravatar-hovercards.php
@@ -6,13 +6,13 @@
* First Introduced: 1.1
*/
-define( 'GROFILES__CACHE_BUSTER', 'aa' ); // Break CDN cache, increment when gravatar.com/js/gprofiles.js changes
+define( 'GROFILES__CACHE_BUSTER', gmdate( 'YM' ) . 'aa' ); // Break CDN cache, increment when gravatar.com/js/gprofiles.js changes
function grofiles_hovercards_init() {
- add_filter( 'get_avatar', 'grofiles_get_avatar', 10, 2 );
- add_action( 'wp_footer', 'grofiles_attach_cards' );
- add_action( 'wp_footer', 'grofiles_extra_data' );
- add_action( 'admin_init', 'grofiles_add_settings' );
+ add_filter( 'get_avatar', 'grofiles_get_avatar', 10, 2 );
+ add_action( 'wp_enqueue_scripts', 'grofiles_attach_cards' );
+ add_action( 'wp_footer', 'grofiles_extra_data' );
+ add_action( 'admin_init', 'grofiles_add_settings' );
add_action( 'load-index.php', 'grofiles_admin_cards' );
add_action( 'load-users.php', 'grofiles_admin_cards' );
@@ -141,7 +141,7 @@ function grofiles_get_avatar( $avatar, $author ) {
if ( false !== strpos( $author, '@' ) ) {
grofiles_gravatars_to_append( $author );
} else {
- if ( $user = get_userdatabylogin( $author ) )
+ if ( $user = get_user_by( 'slug', $author ) )
grofiles_gravatars_to_append( $user->ID );
}
} else if ( isset( $author->comment_type ) ) {
@@ -171,8 +171,8 @@ function grofiles_attach_cards() {
if ( 'disabled' == get_option( 'gravatar_disable_hovercards' ) )
return;
- wp_enqueue_script( 'grofiles-cards', ( is_ssl() ? 'https://secure' : 'http://s' ) . '.gravatar.com/js/gprofiles.js?' . GROFILES__CACHE_BUSTER, array( 'jquery' ) );
- wp_enqueue_script( 'wpgroho', plugins_url( 'wpgroho.js', __FILE__ ), array( 'grofiles-cards' ) );
+ wp_enqueue_script( 'grofiles-cards', ( is_ssl() ? 'https://secure' : 'http://s' ) . '.gravatar.com/js/gprofiles.js', array( 'jquery' ), GROFILES__CACHE_BUSTER, true );
+ wp_enqueue_script( 'wpgroho', plugins_url( 'wpgroho.js', __FILE__ ), array( 'grofiles-cards' ), false, true );
if ( is_user_logged_in() ) {
$cu = wp_get_current_user();
$my_hash = md5( $cu->user_email );
@@ -182,7 +182,6 @@ function grofiles_attach_cards() {
$my_hash = '';
}
wp_localize_script( 'wpgroho', 'WPGroHo', compact( 'my_hash' ) );
- wp_print_scripts( 'wpgroho' );
}
function grofiles_attach_cards_forced() {
diff --git a/plugins/jetpack/modules/holiday-snow.php b/plugins/jetpack/modules/holiday-snow.php
new file mode 100644
index 00000000..93e3f9cf
--- /dev/null
+++ b/plugins/jetpack/modules/holiday-snow.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * Holiday Snow
+ * Adds falling snow to a blog starting December 1 and ending January 3.
+ * Not a module that is activated/deactivated
+ * First Introduced: 2.0.3 ??
+ */
+
+class Jetpack_Holiday_Snow_Settings {
+ function __construct() {
+ add_filter( 'admin_init' , array( &$this , 'register_fields' ) );
+ }
+
+ public function register_fields() {
+ register_setting( 'general', jetpack_holiday_snow_option_name(), 'esc_attr' );
+ add_settings_field( jetpack_holiday_snow_option_name(), '<label for="' . esc_attr( jetpack_holiday_snow_option_name() ) . '">' . __( 'Snow' , 'jetpack') . '</label>' , array( &$this, 'blog_field_html' ) , 'general' );
+ add_action( 'update_option_' . jetpack_holiday_snow_option_name(), array( &$this, 'holiday_snow_option_updated' ) );
+ }
+
+ public function blog_field_html() {
+ $id = esc_attr( jetpack_holiday_snow_option_name() );
+ ?>
+ <label for="<?php echo $id; ?>">
+ <input type="checkbox" name="<?php echo $id; ?>" id="<?php echo $id; ?>" value="letitsnow"<?php checked( get_option( jetpack_holiday_snow_option_name() ), 'letitsnow' ); ?> />
+ <span><?php _e( 'Show falling snow on my blog until January 4<sup>th</sup>.' , 'jetpack'); ?></span>
+ </label>
+ <?php
+ }
+
+ public function holiday_snow_option_updated() {
+ do_action( 'jetpack_holiday_snow_option_updated' );
+ }
+}
+
+function jetpack_holiday_snow_script() {
+ if ( ! apply_filters( 'jetpack_holiday_chance_of_snow', true ) )
+ return;
+
+ do_action( 'jetpack_holiday_snowing' );
+
+ $snowstorm_url = apply_filters( 'jetpack_holiday_snow_js_url', plugins_url( 'holiday-snow/snowstorm.js', __FILE__ ) );
+ wp_enqueue_script( 'snowstorm', $snowstorm_url, array(), '1.43.20111201' );
+}
+
+function jetpack_maybe_holiday_snow() {
+ if ( ! jetpack_is_holiday_snow_season() )
+ return;
+
+ if ( is_admin() ) {
+ global $jetpack_holiday_snow;
+ $jetpack_holiday_snow = new Jetpack_Holiday_Snow_Settings();
+ } elseif ( get_option( jetpack_holiday_snow_option_name() ) ) {
+ add_action( 'init', 'jetpack_holiday_snow_script' );
+ }
+}
+
+function jetpack_holiday_snow_option_name() {
+ return apply_filters( 'jetpack_holiday_snow_option_name', 'jetpack_holiday_snow_enabled' );
+}
+
+function jetpack_is_holiday_snow_season() {
+ $today = time();
+ $first_snow_day = mktime( 0, 0, 0, 12, 1 );
+ $last_snow_day = mktime( 0, 0, 0, 1, 4 );
+
+ $snow = ( $today >= $first_snow_day || $today < $last_snow_day );
+
+ return apply_filters( 'jetpack_is_holiday_snow_season', $snow );
+}
+
+jetpack_maybe_holiday_snow();
diff --git a/plugins/jetpack/modules/holiday-snow/snowstorm.js b/plugins/jetpack/modules/holiday-snow/snowstorm.js
new file mode 100644
index 00000000..96fd609d
--- /dev/null
+++ b/plugins/jetpack/modules/holiday-snow/snowstorm.js
@@ -0,0 +1,539 @@
+/** @license
+ * DHTML Snowstorm! JavaScript-based Snow for web pages
+ * --------------------------------------------------------
+ * Version 1.43.20111201 (Previous rev: 1.42.20111120)
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.
+ * Code provided under the BSD License:
+ * http://schillmania.com/projects/snowstorm/license.txt
+ */
+
+/*global window, document, navigator, clearInterval, setInterval */
+/*jslint white: false, onevar: true, plusplus: false, undef: true, nomen: true, eqeqeq: true, bitwise: true, regexp: true, newcap: true, immed: true */
+
+var snowStorm = (function(window, document) {
+
+ // --- common properties ---
+
+ this.autoStart = true; // Whether the snow should start automatically or not.
+ this.flakesMax = 60; // Limit total amount of snow made (falling + sticking)
+ this.flakesMaxActive = 60; // Limit amount of snow falling at once (less = lower CPU use)
+ this.animationInterval = 40; // Theoretical "miliseconds per frame" measurement. 20 = fast + smooth, but high CPU use. 50 = more conservative, but slower
+ this.excludeMobile = true; // Snow is likely to be bad news for mobile phones' CPUs (and batteries.) By default, be nice.
+ this.flakeBottom = null; // Integer for Y axis snow limit, 0 or null for "full-screen" snow effect
+ this.followMouse = true; // Snow movement can respond to the user's mouse
+ this.snowColor = '#fff'; // Don't eat (or use?) yellow snow.
+ this.snowCharacter = '&bull;'; // &bull; = bullet, &middot; is square on some systems etc.
+ this.snowStick = false; // Whether or not snow should "stick" at the bottom. When off, will never collect.
+ this.targetElement = null; // element which snow will be appended to (null = document.body) - can be an element ID eg. 'myDiv', or a DOM node reference
+ this.useMeltEffect = true; // When recycling fallen snow (or rarely, when falling), have it "melt" and fade out if browser supports it
+ this.useTwinkleEffect = false; // Allow snow to randomly "flicker" in and out of view while falling
+ this.usePositionFixed = false; // true = snow does not shift vertically when scrolling. May increase CPU load, disabled by default - if enabled, used only where supported
+
+ // --- less-used bits ---
+
+ this.freezeOnBlur = true; // Only snow when the window is in focus (foreground.) Saves CPU.
+ this.flakeLeftOffset = 0; // Left margin/gutter space on edge of container (eg. browser window.) Bump up these values if seeing horizontal scrollbars.
+ this.flakeRightOffset = 0; // Right margin/gutter space on edge of container
+ this.flakeWidth = 5; // Max pixel width reserved for snow element
+ this.flakeHeight = 5; // Max pixel height reserved for snow element
+ this.vMaxX = 2.5; // Maximum X velocity range for snow
+ this.vMaxY = 2.5; // Maximum Y velocity range for snow
+ this.zIndex = 100000; // CSS stacking order applied to each snowflake
+
+ // --- End of user section ---
+
+ var s = this, storm = this, i,
+ // UA sniffing and backCompat rendering mode checks for fixed position, etc.
+ isIE = navigator.userAgent.match(/msie/i),
+ isIE6 = navigator.userAgent.match(/msie 6/i),
+ isWin98 = navigator.appVersion.match(/windows 98/i),
+ isMobile = navigator.userAgent.match(/mobile|opera m(ob|in)/i),
+ isBackCompatIE = (isIE && document.compatMode === 'BackCompat'),
+ noFixed = (isMobile || isBackCompatIE || isIE6),
+ screenX = null, screenX2 = null, screenY = null, scrollY = null, vRndX = null, vRndY = null,
+ windOffset = 1,
+ windMultiplier = 2,
+ flakeTypes = 6,
+ fixedForEverything = false,
+ opacitySupported = (function(){
+ try {
+ document.createElement('div').style.opacity = '0.5';
+ } catch(e) {
+ return false;
+ }
+ return true;
+ }()),
+ didInit = false,
+ docFrag = document.createDocumentFragment();
+
+ this.timers = [];
+ this.flakes = [];
+ this.disabled = false;
+ this.active = false;
+ this.meltFrameCount = 20;
+ this.meltFrames = [];
+
+ this.events = (function() {
+
+ var old = (!window.addEventListener && window.attachEvent), slice = Array.prototype.slice,
+ evt = {
+ add: (old?'attachEvent':'addEventListener'),
+ remove: (old?'detachEvent':'removeEventListener')
+ };
+
+ function getArgs(oArgs) {
+ var args = slice.call(oArgs), len = args.length;
+ if (old) {
+ args[1] = 'on' + args[1]; // prefix
+ if (len > 3) {
+ args.pop(); // no capture
+ }
+ } else if (len === 3) {
+ args.push(false);
+ }
+ return args;
+ }
+
+ function apply(args, sType) {
+ var element = args.shift(),
+ method = [evt[sType]];
+ if (old) {
+ element[method](args[0], args[1]);
+ } else {
+ element[method].apply(element, args);
+ }
+ }
+
+ function addEvent() {
+ apply(getArgs(arguments), 'add');
+ }
+
+ function removeEvent() {
+ apply(getArgs(arguments), 'remove');
+ }
+
+ return {
+ add: addEvent,
+ remove: removeEvent
+ };
+
+ }());
+
+ function rnd(n,min) {
+ if (isNaN(min)) {
+ min = 0;
+ }
+ return (Math.random()*n)+min;
+ }
+
+ function plusMinus(n) {
+ return (parseInt(rnd(2),10)===1?n*-1:n);
+ }
+
+ this.randomizeWind = function() {
+ var i;
+ vRndX = plusMinus(rnd(s.vMaxX,0.2));
+ vRndY = rnd(s.vMaxY,0.2);
+ if (this.flakes) {
+ for (i=0; i<this.flakes.length; i++) {
+ if (this.flakes[i].active) {
+ this.flakes[i].setVelocities();
+ }
+ }
+ }
+ };
+
+ this.scrollHandler = function() {
+ var i;
+ // "attach" snowflakes to bottom of window if no absolute bottom value was given
+ scrollY = (s.flakeBottom?0:parseInt(window.scrollY||document.documentElement.scrollTop||document.body.scrollTop,10));
+ if (isNaN(scrollY)) {
+ scrollY = 0; // Netscape 6 scroll fix
+ }
+ if (!fixedForEverything && !s.flakeBottom && s.flakes) {
+ for (i=s.flakes.length; i--;) {
+ if (s.flakes[i].active === 0) {
+ s.flakes[i].stick();
+ }
+ }
+ }
+ };
+
+ this.resizeHandler = function() {
+ if (window.innerWidth || window.innerHeight) {
+ screenX = window.innerWidth-16-s.flakeRightOffset;
+ screenY = (s.flakeBottom?s.flakeBottom:window.innerHeight);
+ } else {
+ screenX = (document.documentElement.clientWidth||document.body.clientWidth||document.body.scrollWidth)-(!isIE?8:0)-s.flakeRightOffset;
+ screenY = s.flakeBottom?s.flakeBottom:(document.documentElement.clientHeight||document.body.clientHeight||document.body.scrollHeight);
+ }
+ screenX2 = parseInt(screenX/2,10);
+ };
+
+ this.resizeHandlerAlt = function() {
+ screenX = s.targetElement.offsetLeft+s.targetElement.offsetWidth-s.flakeRightOffset;
+ screenY = s.flakeBottom?s.flakeBottom:s.targetElement.offsetTop+s.targetElement.offsetHeight;
+ screenX2 = parseInt(screenX/2,10);
+ };
+
+ this.freeze = function() {
+ // pause animation
+ var i;
+ if (!s.disabled) {
+ s.disabled = 1;
+ } else {
+ return false;
+ }
+ for (i=s.timers.length; i--;) {
+ clearInterval(s.timers[i]);
+ }
+ };
+
+ this.resume = function() {
+ if (s.disabled) {
+ s.disabled = 0;
+ } else {
+ return false;
+ }
+ s.timerInit();
+ };
+
+ this.toggleSnow = function() {
+ if (!s.flakes.length) {
+ // first run
+ s.start();
+ } else {
+ s.active = !s.active;
+ if (s.active) {
+ s.show();
+ s.resume();
+ } else {
+ s.stop();
+ s.freeze();
+ }
+ }
+ };
+
+ this.stop = function() {
+ var i;
+ this.freeze();
+ for (i=this.flakes.length; i--;) {
+ this.flakes[i].o.style.display = 'none';
+ }
+ s.events.remove(window,'scroll',s.scrollHandler);
+ s.events.remove(window,'resize',s.resizeHandler);
+ if (s.freezeOnBlur) {
+ if (isIE) {
+ s.events.remove(document,'focusout',s.freeze);
+ s.events.remove(document,'focusin',s.resume);
+ } else {
+ s.events.remove(window,'blur',s.freeze);
+ s.events.remove(window,'focus',s.resume);
+ }
+ }
+ };
+
+ this.show = function() {
+ var i;
+ for (i=this.flakes.length; i--;) {
+ this.flakes[i].o.style.display = 'block';
+ }
+ };
+
+ this.SnowFlake = function(parent,type,x,y) {
+ var s = this, storm = parent;
+ this.type = type;
+ this.x = x||parseInt(rnd(screenX-20),10);
+ this.y = (!isNaN(y)?y:-rnd(screenY)-12);
+ this.vX = null;
+ this.vY = null;
+ this.vAmpTypes = [1,1.2,1.4,1.6,1.8]; // "amplification" for vX/vY (based on flake size/type)
+ this.vAmp = this.vAmpTypes[this.type];
+ this.melting = false;
+ this.meltFrameCount = storm.meltFrameCount;
+ this.meltFrames = storm.meltFrames;
+ this.meltFrame = 0;
+ this.twinkleFrame = 0;
+ this.active = 1;
+ this.fontSize = (10+(this.type/5)*10);
+ this.o = document.createElement('div');
+ this.o.innerHTML = storm.snowCharacter;
+ this.o.style.color = storm.snowColor;
+ this.o.style.position = (fixedForEverything?'fixed':'absolute');
+ this.o.style.width = storm.flakeWidth+'px';
+ this.o.style.height = storm.flakeHeight+'px';
+ this.o.style.fontFamily = 'arial,verdana';
+ this.o.style.cursor = 'default';
+ this.o.style.overflow = 'hidden';
+ this.o.style.fontWeight = 'normal';
+ this.o.style.zIndex = storm.zIndex;
+ docFrag.appendChild(this.o);
+
+ this.refresh = function() {
+ if (isNaN(s.x) || isNaN(s.y)) {
+ // safety check
+ return false;
+ }
+ s.o.style.left = s.x+'px';
+ s.o.style.top = s.y+'px';
+ };
+
+ this.stick = function() {
+ if (noFixed || (storm.targetElement !== document.documentElement && storm.targetElement !== document.body)) {
+ s.o.style.top = (screenY+scrollY-storm.flakeHeight)+'px';
+ } else if (storm.flakeBottom) {
+ s.o.style.top = storm.flakeBottom+'px';
+ } else {
+ s.o.style.display = 'none';
+ s.o.style.top = 'auto';
+ s.o.style.bottom = '0px';
+ s.o.style.position = 'fixed';
+ s.o.style.display = 'block';
+ }
+ };
+
+ this.vCheck = function() {
+ if (s.vX>=0 && s.vX<0.2) {
+ s.vX = 0.2;
+ } else if (s.vX<0 && s.vX>-0.2) {
+ s.vX = -0.2;
+ }
+ if (s.vY>=0 && s.vY<0.2) {
+ s.vY = 0.2;
+ }
+ };
+
+ this.move = function() {
+ var vX = s.vX*windOffset, yDiff;
+ s.x += vX;
+ s.y += (s.vY*s.vAmp);
+ if (s.x >= screenX || screenX-s.x < storm.flakeWidth) { // X-axis scroll check
+ s.x = 0;
+ } else if (vX < 0 && s.x-storm.flakeLeftOffset < -storm.flakeWidth) {
+ s.x = screenX-storm.flakeWidth-1; // flakeWidth;
+ }
+ s.refresh();
+ yDiff = screenY+scrollY-s.y;
+ if (yDiff<storm.flakeHeight) {
+ s.active = 0;
+ if (storm.snowStick) {
+ s.stick();
+ } else {
+ s.recycle();
+ }
+ } else {
+ if (storm.useMeltEffect && s.active && s.type < 3 && !s.melting && Math.random()>0.998) {
+ // ~1/1000 chance of melting mid-air, with each frame
+ s.melting = true;
+ s.melt();
+ // only incrementally melt one frame
+ // s.melting = false;
+ }
+ if (storm.useTwinkleEffect) {
+ if (!s.twinkleFrame) {
+ if (Math.random()>0.9) {
+ s.twinkleFrame = parseInt(Math.random()*20,10);
+ }
+ } else {
+ s.twinkleFrame--;
+ s.o.style.visibility = (s.twinkleFrame && s.twinkleFrame%2===0?'hidden':'visible');
+ }
+ }
+ }
+ };
+
+ this.animate = function() {
+ // main animation loop
+ // move, check status, die etc.
+ s.move();
+ };
+
+ this.setVelocities = function() {
+ s.vX = vRndX+rnd(storm.vMaxX*0.12,0.1);
+ s.vY = vRndY+rnd(storm.vMaxY*0.12,0.1);
+ };
+
+ this.setOpacity = function(o,opacity) {
+ if (!opacitySupported) {
+ return false;
+ }
+ o.style.opacity = opacity;
+ };
+
+ this.melt = function() {
+ if (!storm.useMeltEffect || !s.melting) {
+ s.recycle();
+ } else {
+ if (s.meltFrame < s.meltFrameCount) {
+ s.setOpacity(s.o,s.meltFrames[s.meltFrame]);
+ s.o.style.fontSize = s.fontSize-(s.fontSize*(s.meltFrame/s.meltFrameCount))+'px';
+ s.o.style.lineHeight = storm.flakeHeight+2+(storm.flakeHeight*0.75*(s.meltFrame/s.meltFrameCount))+'px';
+ s.meltFrame++;
+ } else {
+ s.recycle();
+ }
+ }
+ };
+
+ this.recycle = function() {
+ s.o.style.display = 'none';
+ s.o.style.position = (fixedForEverything?'fixed':'absolute');
+ s.o.style.bottom = 'auto';
+ s.setVelocities();
+ s.vCheck();
+ s.meltFrame = 0;
+ s.melting = false;
+ s.setOpacity(s.o,1);
+ s.o.style.padding = '0px';
+ s.o.style.margin = '0px';
+ s.o.style.fontSize = s.fontSize+'px';
+ s.o.style.lineHeight = (storm.flakeHeight+2)+'px';
+ s.o.style.textAlign = 'center';
+ s.o.style.verticalAlign = 'baseline';
+ s.x = parseInt(rnd(screenX-storm.flakeWidth-20),10);
+ s.y = parseInt(rnd(screenY)*-1,10)-storm.flakeHeight;
+ s.refresh();
+ s.o.style.display = 'block';
+ s.active = 1;
+ };
+
+ this.recycle(); // set up x/y coords etc.
+ this.refresh();
+
+ };
+
+ this.snow = function() {
+ var active = 0, used = 0, waiting = 0, flake = null, i;
+ for (i=s.flakes.length; i--;) {
+ if (s.flakes[i].active === 1) {
+ s.flakes[i].move();
+ active++;
+ } else if (s.flakes[i].active === 0) {
+ used++;
+ } else {
+ waiting++;
+ }
+ if (s.flakes[i].melting) {
+ s.flakes[i].melt();
+ }
+ }
+ if (active<s.flakesMaxActive) {
+ flake = s.flakes[parseInt(rnd(s.flakes.length),10)];
+ if (flake.active === 0) {
+ flake.melting = true;
+ }
+ }
+ };
+
+ this.mouseMove = function(e) {
+ if (!s.followMouse) {
+ return true;
+ }
+ var x = parseInt(e.clientX,10);
+ if (x<screenX2) {
+ windOffset = -windMultiplier+(x/screenX2*windMultiplier);
+ } else {
+ x -= screenX2;
+ windOffset = (x/screenX2)*windMultiplier;
+ }
+ };
+
+ this.createSnow = function(limit,allowInactive) {
+ var i;
+ for (i=0; i<limit; i++) {
+ s.flakes[s.flakes.length] = new s.SnowFlake(s,parseInt(rnd(flakeTypes),10));
+ if (allowInactive || i>s.flakesMaxActive) {
+ s.flakes[s.flakes.length-1].active = -1;
+ }
+ }
+ storm.targetElement.appendChild(docFrag);
+ };
+
+ this.timerInit = function() {
+ s.timers = (!isWin98?[setInterval(s.snow,s.animationInterval)]:[setInterval(s.snow,s.animationInterval*3),setInterval(s.snow,s.animationInterval)]);
+ };
+
+ this.init = function() {
+ var i;
+ for (i=0; i<s.meltFrameCount; i++) {
+ s.meltFrames.push(1-(i/s.meltFrameCount));
+ }
+ s.randomizeWind();
+ s.createSnow(s.flakesMax); // create initial batch
+ s.events.add(window,'resize',s.resizeHandler);
+ s.events.add(window,'scroll',s.scrollHandler);
+ if (s.freezeOnBlur) {
+ if (isIE) {
+ s.events.add(document,'focusout',s.freeze);
+ s.events.add(document,'focusin',s.resume);
+ } else {
+ s.events.add(window,'blur',s.freeze);
+ s.events.add(window,'focus',s.resume);
+ }
+ }
+ s.resizeHandler();
+ s.scrollHandler();
+ if (s.followMouse) {
+ s.events.add(isIE?document:window,'mousemove',s.mouseMove);
+ }
+ s.animationInterval = Math.max(20,s.animationInterval);
+ s.timerInit();
+ };
+
+ this.start = function(bFromOnLoad) {
+ if (!didInit) {
+ didInit = true;
+ } else if (bFromOnLoad) {
+ // already loaded and running
+ return true;
+ }
+ if (typeof s.targetElement === 'string') {
+ var targetID = s.targetElement;
+ s.targetElement = document.getElementById(targetID);
+ if (!s.targetElement) {
+ throw new Error('Snowstorm: Unable to get targetElement "'+targetID+'"');
+ }
+ }
+ if (!s.targetElement) {
+ s.targetElement = (!isIE?(document.documentElement?document.documentElement:document.body):document.body);
+ }
+ if (s.targetElement !== document.documentElement && s.targetElement !== document.body) {
+ s.resizeHandler = s.resizeHandlerAlt; // re-map handler to get element instead of screen dimensions
+ }
+ s.resizeHandler(); // get bounding box elements
+ s.usePositionFixed = (s.usePositionFixed && !noFixed); // whether or not position:fixed is supported
+ fixedForEverything = s.usePositionFixed;
+ if (screenX && screenY && !s.disabled) {
+ s.init();
+ s.active = true;
+ }
+ };
+
+ function doDelayedStart() {
+ window.setTimeout(function() {
+ s.start(true);
+ }, 20);
+ // event cleanup
+ s.events.remove(isIE?document:window,'mousemove',doDelayedStart);
+ }
+
+ function doStart() {
+ if (!s.excludeMobile || !isMobile) {
+ if (s.freezeOnBlur) {
+ s.events.add(isIE?document:window,'mousemove',doDelayedStart);
+ } else {
+ doDelayedStart();
+ }
+ }
+ // event cleanup
+ s.events.remove(window, 'load', doStart);
+ }
+
+ // hooks for starting the snow
+ if (s.autoStart) {
+ s.events.add(window, 'load', doStart, false);
+ }
+
+ return this;
+
+}(window, document)); \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll.php b/plugins/jetpack/modules/infinite-scroll.php
new file mode 100644
index 00000000..857ac6e0
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Module Name: Infinite Scroll
+ * Module Description: Automatically pull the next set of posts into view when the reader approaches the bottom of the page.
+ * Sort Order: 14
+ * First Introduced: 2.0
+ */
+
+/**
+ * Jetpack-specific elements of Infinite Scroll
+ */
+class Jetpack_Infinite_Scroll_Extras {
+ /**
+ * Class variables
+ */
+ // Oh look, a singleton
+ private static $__instance = null;
+
+ // Option names
+ private $option_name_google_analytics = 'infinite_scroll_google_analytics';
+
+ /**
+ * Singleton implementation
+ *
+ * @return object
+ */
+ public static function instance() {
+ if ( ! is_a( self::$__instance, 'Jetpack_Infinite_Scroll_Extras' ) )
+ self::$__instance = new Jetpack_Infinite_Scroll_Extras;
+
+ return self::$__instance;
+ }
+
+ /**
+ * Register actions and filters
+ *
+ * @uses add_action, add_filter
+ * @return null
+ */
+ private function __construct() {
+ add_action( 'jetpack_modules_loaded', array( $this, 'action_jetpack_modules_loaded' ) );
+
+ add_action( 'admin_init', array( $this, 'action_admin_init' ), 11 );
+
+ add_action( 'after_setup_theme', array( $this, 'action_after_setup_theme' ), 5 );
+
+ add_filter( 'infinite_scroll_js_settings', array( $this, 'filter_infinite_scroll_js_settings' ) );
+
+ add_action( 'wp_enqueue_scripts', array( $this, 'action_wp_enqueue_scripts' ) );
+ }
+
+ /**
+ * Enable "Configure" button on module card
+ *
+ * @uses Jetpack::enable_module_configurable, Jetpack::module_configuration_load
+ * @action jetpack_modules_loaded
+ * @return null
+ */
+ public function action_jetpack_modules_loaded() {
+ Jetpack::enable_module_configurable( __FILE__ );
+ Jetpack::module_configuration_load( __FILE__, array( $this, 'module_configuration_load' ) );
+ }
+
+ /**
+ * Redirect configure button to Settings > Reading
+ *
+ * @uses wp_safe_redirect, admin_url
+ * @return null
+ */
+ public function module_configuration_load() {
+ wp_safe_redirect( admin_url( 'options-reading.php#infinite-scroll-options' ) );
+ exit;
+ }
+
+ /**
+ * Register Google Analytics setting
+ *
+ * @uses add_settings_field, __, register_setting
+ * @action admin_init
+ * @return null
+ */
+ public function action_admin_init() {
+ add_settings_field( $this->option_name_google_analytics, '<span id="infinite-scroll-google-analytics">' . __( 'Use Google Analytics with Infinite Scroll', 'jetpack' ) . '</span>', array( $this, 'setting_google_analytics' ), 'reading' );
+ register_setting( 'reading', $this->option_name_google_analytics, array( $this, 'sanitize_boolean_value' ) );
+ }
+
+ /**
+ * Render Google Analytics option
+ *
+ * @uses checked, get_option, __
+ * @return html
+ */
+ public function setting_google_analytics() {
+ echo '<label><input name="infinite_scroll_google_analytics" type="checkbox" value="1" ' . checked( true, (bool) get_option( $this->option_name_google_analytics, false ), false ) . ' /> ' . __( 'Track each Infinite Scroll post load as a page view in Google Analytics', 'jetpack' ) . '</br><small>' . __( 'By checking the box above, each new set of posts loaded via Infinite Scroll will be recorded as a page view in Google Analytics.', 'jetpack' ) . '</small>' . '</label>';
+ }
+
+ /**
+ * Sanitize value as a boolean
+ *
+ * @param mixed $value
+ * @return bool
+ */
+ public function sanitize_boolean_value( $value ) {
+ return (bool) $value;
+ }
+
+ /**
+ * Load theme's infinite scroll annotation file, if present in the IS plugin.
+ * The `setup_theme` action is used because the annotation files should be using `after_setup_theme` to register support for IS.
+ *
+ * As released in Jetpack 2.0, a child theme's parent wasn't checked for in the plugin's bundled support, hence the convoluted way the parent is checked for now.
+ *
+ * @uses is_admin, wp_get_theme, get_theme, get_current_theme, apply_filters
+ * @action setup_theme
+ * @return null
+ */
+ function action_after_setup_theme() {
+ $theme = function_exists( 'wp_get_theme' ) ? wp_get_theme() : get_theme( get_current_theme() );
+
+ if ( ! is_a( $theme, 'WP_Theme' ) && ! is_array( $theme ) )
+ return;
+
+ $customization_file = apply_filters( 'infinite_scroll_customization_file', dirname( __FILE__ ) . "/infinite-scroll/themes/{$theme['Stylesheet']}.php", $theme['Stylesheet'] );
+
+ if ( is_readable( $customization_file ) ) {
+ require_once( $customization_file );
+ }
+ elseif ( ! empty( $theme['Template'] ) ) {
+ $customization_file = dirname( __FILE__ ) . "/infinite-scroll/themes/{$theme['Template']}.php";
+
+ if ( is_readable( $customization_file ) )
+ require_once( $customization_file );
+ }
+ }
+
+ /**
+ * Modify Infinite Scroll configuration information
+ *
+ * @uses Jetpack::get_active_modules, is_user_logged_in, stats_get_options, Jetpack::get_option, get_option, JETPACK__API_VERSION, JETPACK__VERSION
+ * @filter infinite_scroll_js_settings
+ * @return array
+ */
+ public function filter_infinite_scroll_js_settings( $settings ) {
+ // Provide WP Stats info for tracking Infinite Scroll loads
+ // Abort if Stats module isn't active
+ if ( in_array( 'stats', Jetpack::get_active_modules() ) ) {
+ // Abort if user is logged in but logged-in users shouldn't be tracked.
+ if ( is_user_logged_in() ) {
+ $stats_options = stats_get_options();
+ $track_loggedin_users = isset( $stats_options['reg_users'] ) ? (bool) $stats_options['reg_users'] : false;
+
+ if ( ! $track_loggedin_users )
+ return $settings;
+ }
+
+ // We made it this far, so gather the data needed to track IS views
+ $settings['stats'] = 'blog=' . Jetpack::get_option( 'id' ) . '&host=' . parse_url( get_option( 'home' ), PHP_URL_HOST ) . '&v=ext&j=' . JETPACK__API_VERSION . ':' . JETPACK__VERSION;
+
+ // Pagetype parameter
+ $settings['stats'] .= '&x_pagetype=infinite';
+ if ( 'click' == $settings['type'] )
+ $settings['stats'] .= '-click';
+
+ $settings['stats'] .= '-jetpack';
+ }
+
+ // Check if Google Analytics tracking is requested
+ $settings['google_analytics'] = (bool) get_option( $this->option_name_google_analytics );
+
+ return $settings;
+ }
+
+ /**
+ * Load VideoPress scripts if plugin is active.
+ *
+ * @global $videopress
+ * @action wp_enqueue_scripts
+ * @return null
+ */
+ public function action_wp_enqueue_scripts() {
+ global $videopress;
+ if ( ! empty( $videopress ) && The_Neverending_Home_Page::archive_supports_infinity() && is_a( $videopress, 'VideoPress' ) && method_exists( $videopress, 'enqueue_scripts' ) )
+ $videopress->enqueue_scripts();
+ }
+}
+Jetpack_Infinite_Scroll_Extras::instance();
+
+/**
+ * Load main IS file
+ */
+require_once( dirname( __FILE__ ) . "/infinite-scroll/infinity.php" );
+
+/**
+ * Remove the IS annotation loading function bundled with the IS plugin in favor of the Jetpack-specific version in Jetpack_Infinite_Scroll_Extras::action_after_setup_theme();
+ */
+remove_action( 'after_setup_theme', 'the_neverending_home_page_theme_support', 5 ); \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll/infinity.css b/plugins/jetpack/modules/infinite-scroll/infinity.css
new file mode 100644
index 00000000..dd39179e
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/infinity.css
@@ -0,0 +1,137 @@
+/* =Infinity Styles
+-------------------------------------------------------------- */
+
+.infinite-wrap {
+/* border-top: 2px solid #444;
+ border-top: 2px solid rgba(68,68,68,0.8);
+ padding: 20px 0 0; */
+}
+.infinite-loader {
+ color: #000;
+ display: block;
+ height: 28px;
+ margin: 10px;
+ text-indent: -9999px;
+}
+#infinite-handle span {
+ background: #333;
+ border-radius: 1px;
+ color: #eee;
+ cursor: pointer;
+ font-size: 13px;
+ padding: 6px 16px;
+}
+
+/**
+ * For smaller viewports, remove the down-arrow icon and turn
+ * the button into a block element, spanning the content's full width.
+ */
+@media (max-width: 800px) {
+ #infinite-handle span:before {
+ display: none;
+ }
+ #infinite-handle span {
+ display: block;
+ }
+}
+
+/**
+ * Footer
+ */
+#infinite-footer {
+ position: fixed;
+ bottom: -50px;
+ left: 0;
+ width: 100%;
+}
+#infinite-footer a {
+ text-decoration: none;
+}
+#infinite-footer .blog-info a:hover,
+#infinite-footer .blog-credits a:hover {
+ color: #444;
+ text-decoration: underline;
+}
+#infinite-footer .container {
+ background: rgba( 255, 255, 255, 0.8 );
+ border-color: #ccc;
+ border-color: rgba( 0, 0, 0, 0.1 );
+ border-style: solid;
+ border-width: 1px 0 0;
+ box-sizing: border-box;
+ margin: 0 auto;
+ overflow: hidden;
+ padding: 1px 20px;
+ width: 640px;
+}
+#infinite-footer .blog-info,
+#infinite-footer .blog-credits {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ line-height: 25px;
+}
+#infinite-footer .blog-info {
+ float: left;
+ overflow: hidden;
+ text-align: left;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ width: 40%;
+}
+#infinite-footer .blog-credits {
+ font-weight: normal;
+ float: right;
+ width: 60%;
+}
+#infinite-footer .blog-info a {
+ color: #111;
+ font-size: 14px;
+ font-weight: bold;
+}
+#infinite-footer .blog-credits {
+ color: #888;
+ font-size: 12px;
+ text-align: right;
+}
+#infinite-footer .blog-credits a {
+ color: #666;
+}
+
+/**
+ * Hooks to infinity-end body class to restore footer
+ */
+.infinity-end.neverending #infinite-footer {
+ display: none;
+}
+
+/**
+ * Responsive structure for the footer
+ */
+@media (max-width: 640px) {
+ #infinite-footer .container {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ }
+ #infinite-footer .blog-info {
+ width: 30%;
+ }
+ #infinite-footer .blog-credits {
+ width: 70%;
+ }
+ #infinite-footer .blog-info a,
+ #infinite-footer .blog-credits {
+ font-size: 10px;
+ }
+}
+
+/**
+ * No fixed footer on small viewports
+ */
+@media ( max-width: 640px ) {
+ #infinite-footer {
+ position: static;
+ }
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll/infinity.js b/plugins/jetpack/modules/infinite-scroll/infinity.js
new file mode 100644
index 00000000..7a76d8f2
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/infinity.js
@@ -0,0 +1,490 @@
+(function($){ // Open closure
+
+// Local vars
+var Scroller, ajaxurl, stats, type, text, totop, timer;
+
+// IE requires special handling
+var isIE = ( -1 != navigator.userAgent.search( 'MSIE' ) );
+if ( isIE ) {
+ var IEVersion = navigator.userAgent.match(/MSIE\s?(\d+)\.?\d*;/);
+ var IEVersion = parseInt( IEVersion[1] );
+}
+
+/**
+ * Loads new posts when users scroll near the bottom of the page.
+ */
+Scroller = function( settings ) {
+ var self = this;
+
+ // Initialize our variables
+ this.id = settings.id;
+ this.body = $( document.body );
+ this.window = $( window );
+ this.element = $( '#' + settings.id );
+ this.wrapperClass = settings.wrapper_class;
+ this.ready = true;
+ this.disabled = false;
+ this.page = 1;
+ this.offset = settings.offset;
+ this.order = settings.order;
+ this.throttle = false;
+ this.handle = '<div id="infinite-handle"><span>' + text.replace( '\\', '' ) + '</span></div>';
+ this.google_analytics = settings.google_analytics;
+ this.history = settings.history;
+ this.origURL = window.location.href;
+
+ // Footer settings
+ this.footer = $( '#infinite-footer' );
+ this.footer.wrap = settings.footer;
+
+ // We have two type of infinite scroll
+ // cases 'scroll' and 'click'
+
+ if ( type == 'scroll' ) {
+ // Bind refresh to the scroll event
+ // Throttle to check for such case every 300ms
+
+ // On event the case becomes a fact
+ this.window.bind( 'scroll.infinity', function() {
+ this.throttle = true;
+ });
+
+ // Go back top method
+ self.gotop();
+
+ setInterval( function() {
+ if ( this.throttle ) {
+ // Once the case is the case, the action occurs and the fact is no more
+ this.throttle = false;
+ // Reveal or hide footer
+ self.thefooter();
+ // Fire the refresh
+ self.refresh();
+ }
+ }, 300 );
+
+ // Ensure that enough posts are loaded to fill the initial viewport, to compensate for short posts and large displays.
+ self.ensureFilledViewport();
+ this.body.bind( 'post-load', { self: self }, self.checkViewportOnLoad );
+ } else if ( type == 'click' ) {
+ this.element.append( self.handle );
+ this.element.delegate( '#infinite-handle', 'click.infinity', function() {
+ // Handle the handle
+ $( '#infinite-handle' ).remove();
+ // Fire the refresh
+ self.refresh();
+ });
+ }
+};
+
+/**
+ * Check whether we should fetch any additional posts.
+ *
+ * By default, checks whether the bottom of the viewport is within one
+ * viewport-height of the bottom of the content.
+ */
+Scroller.prototype.check = function() {
+ var bottom = this.window.scrollTop() + this.window.height(),
+ threshold = this.element.offset().top + this.element.outerHeight(false) - this.window.height();
+
+ return bottom > threshold;
+};
+
+/**
+ * Renders the results from a successful response.
+ */
+Scroller.prototype.render = function( response ) {
+ this.body.addClass( 'infinity-success' );
+
+ // Check if we can wrap the html
+ this.element.append( response.html );
+
+ this.body.trigger( 'post-load' );
+ this.ready = true;
+};
+
+/**
+ * Returns the object used to query for new posts.
+ */
+Scroller.prototype.query = function() {
+ return {
+ page: this.page,
+ order: this.order,
+ scripts: window.infiniteScroll.settings.scripts,
+ styles: window.infiniteScroll.settings.styles
+ };
+};
+
+/**
+ * Scroll back to top.
+ */
+Scroller.prototype.gotop = function() {
+ var blog = $( '#infinity-blog-title' );
+
+ blog.attr( 'title', totop );
+
+ // Scroll to top on blog title
+ blog.bind( 'click', function( e ) {
+ $( 'html, body' ).animate( { scrollTop: 0 }, 'fast' );
+ e.preventDefault();
+ });
+};
+
+
+/**
+ * The infinite footer.
+ */
+Scroller.prototype.thefooter = function() {
+ var self = this,
+ width;
+
+ // Check if we have an id for the page wrapper
+ if ( $.type( this.footer.wrap ) === "string" ) {
+ width = $( 'body #' + this.footer.wrap ).outerWidth( false );
+
+ // Make the footer match the width of the page
+ if ( width > 479 )
+ this.footer.find( '.container' ).css( 'width', width );
+ }
+
+ // Reveal footer
+ if ( this.window.scrollTop() >= 350 )
+ self.footer.animate( { 'bottom': 0 }, 'fast' );
+ else if ( this.window.scrollTop() < 350 )
+ self.footer.animate( { 'bottom': '-50px' }, 'fast' );
+};
+
+
+/**
+ * Controls the flow of the refresh. Don't mess.
+ */
+Scroller.prototype.refresh = function() {
+ var self = this,
+ query, jqxhr, load, loader, color;
+
+ // If we're disabled, ready, or don't pass the check, bail.
+ if ( this.disabled || ! this.ready || ! this.check() )
+ return;
+
+ // Let's get going -- set ready to false to prevent
+ // multiple refreshes from occurring at once.
+ this.ready = false;
+
+ // Create a loader element to show it's working.
+ loader = '<span class="infinite-loader"></span>';
+ this.element.append( loader );
+
+ loader = this.element.find( '.infinite-loader' );
+ color = loader.css( 'color' );
+
+ try {
+ loader.spin( 'medium-left', color );
+ } catch ( error ) { }
+
+ // Generate our query vars.
+ query = $.extend({
+ action: 'infinite_scroll'
+ }, this.query() );
+
+ // Fire the ajax request.
+ jqxhr = $.get( infiniteScroll.settings.ajaxurl, query );
+
+ // Allow refreshes to occur again if an error is triggered.
+ jqxhr.fail( function() {
+ loader.hide();
+ self.ready = true;
+ });
+
+ // Success handler
+ jqxhr.done( function( response ) {
+
+ // On success, let's hide the loader circle.
+ loader.hide();
+
+ // Check for and parse our response.
+ if ( ! response )
+ return;
+
+ response = $.parseJSON( response );
+
+ if ( ! response || ! response.type )
+ return;
+
+ // If there are no remaining posts...
+ if ( response.type == 'empty' ) {
+ // Disable the scroller.
+ self.disabled = true;
+ // Update body classes, allowing the footer to return to static positioning
+ self.body.addClass( 'infinity-end' ).removeClass( 'infinity-success' );
+
+ // If we've succeeded...
+ } else if ( response.type == 'success' ) {
+ // If additional scripts are required by the incoming set of posts, parse them
+ if ( response.scripts ) {
+ $( response.scripts ).each( function() {
+ // Add script handle to list of those already parsed
+ window.infiniteScroll.settings.scripts.push( this.handle );
+
+ // Output extra data, if present
+ if ( this.extra_data ) {
+ var data = document.createElement('script'),
+ dataContent = document.createTextNode( "//<![CDATA[ \n" + this.extra_data + "\n//]]>" );
+
+ data.type = 'text/javascript';
+ data.appendChild( dataContent );
+
+ document.getElementsByTagName( this.footer ? 'body' : 'head' )[0].appendChild(data);
+ }
+
+ // Build script tag and append to DOM in requested location
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = this.src;
+ script.id = this.handle;
+ document.getElementsByTagName( this.footer ? 'body' : 'head' )[0].appendChild(script);
+ } );
+ }
+
+ // If additional stylesheets are required by the incoming set of posts, parse them
+ if ( response.styles ) {
+ $( response.styles ).each( function() {
+ // Add stylesheet handle to list of those already parsed
+ window.infiniteScroll.settings.styles.push( this.handle );
+
+ // Build link tag
+ var style = document.createElement('link');
+ style.rel = 'stylesheet';
+ style.href = this.src;
+ style.id = this.handle + '-css';
+
+ // Destroy link tag if a conditional statement is present and either the browser isn't IE, or the conditional doesn't evaluate true
+ if ( this.conditional && ( ! isIE || ! eval( this.conditional.replace( /%ver/g, IEVersion ) ) ) )
+ var style = false;
+
+ // Append link tag if necessary
+ if ( style )
+ document.getElementsByTagName('head')[0].appendChild(style);
+ } );
+ }
+
+ // Increment the page number
+ self.page++;
+
+ // Record pageview in WP Stats, if available.
+ if ( stats )
+ new Image().src = document.location.protocol + '//stats.wordpress.com/g.gif?' + stats + '&post=0&baba=' + Math.random();
+
+ // Add new posts to the postflair object
+ if ( 'object' == typeof response.postflair && 'object' == typeof WPCOM_sharing_counts )
+ WPCOM_sharing_counts = $.extend( WPCOM_sharing_counts, response.postflair );
+
+ // Render the results
+ self.render.apply( self, arguments );
+
+ // If 'click' type, add back the handle
+ if ( type == 'click' )
+ self.element.append( self.handle );
+
+ // Fire Google Analytics pageview
+ if ( self.google_analytics && 'object' == typeof _gaq )
+ _gaq.push(['_trackPageview', self.history.path.replace( /%d/, self.page ) ]);
+ }
+ });
+
+ return jqxhr;
+};
+
+/**
+ * Trigger IS to load additional posts if the initial posts don't fill the window.
+ * On large displays, or when posts are very short, the viewport may not be filled with posts, so we overcome this by loading additional posts when IS initializes.
+ */
+Scroller.prototype.ensureFilledViewport = function() {
+ var self = this,
+ windowHeight = self.window.height(),
+ postsHeight = self.element.height()
+ aveSetHeight = 0,
+ wrapperQty = 0;
+
+ // Account for situations where postsHeight is 0 because child list elements are floated
+ if ( postsHeight === 0 ) {
+ $( self.element.selector + ' > li' ).each( function() {
+ postsHeight += $( this ).height();
+ } );
+
+ if ( postsHeight === 0 ) {
+ self.body.unbind( 'post-load', self.checkViewportOnLoad );
+ return;
+ }
+ }
+
+ // Calculate average height of a set of posts to prevent more posts than needed from being loaded.
+ $( '.' + self.wrapperClass ).each( function() {
+ aveSetHeight += $( this ).height();
+ wrapperQty++;
+ } );
+
+ if ( wrapperQty > 0 )
+ aveSetHeight = aveSetHeight / wrapperQty;
+ else
+ aveSetHeight = 0;
+
+ // Load more posts if space permits, otherwise stop checking for a full viewport
+ if ( postsHeight < windowHeight && ( postsHeight + aveSetHeight < windowHeight ) ) {
+ self.ready = true;
+ self.refresh();
+ }
+ else {
+ self.body.unbind( 'post-load', self.checkViewportOnLoad );
+ }
+}
+
+/**
+ * Event handler for ensureFilledViewport(), tied to the post-load trigger.
+ * Necessary to ensure that the variable `this` contains the scroller when used in ensureFilledViewport(). Since this function is tied to an event, `this` becomes the DOM element the event is tied to.
+ */
+Scroller.prototype.checkViewportOnLoad = function( ev ) {
+ ev.data.self.ensureFilledViewport();
+}
+
+/**
+ * Identify archive page that corresponds to majority of posts shown in the current browser window.
+ */
+Scroller.prototype.determineURL = function () {
+ var self = window.infiniteScroll.scroller,
+ windowTop = $( window ).scrollTop(),
+ windowBottom = windowTop + $( window ).height(),
+ windowSize = windowBottom - windowTop,
+ setsInView = [],
+ pageNum = false;
+
+ // Find out which sets are in view
+ $( '.' + self.wrapperClass ).each( function() {
+ var id = $( this ).attr( 'id' ),
+ setTop = $( this ).offset().top,
+ setHeight = $( this ).outerHeight( false ),
+ setBottom = 0,
+ setPageNum = $( this ).data( 'page-num' );
+
+ // Account for containers that have no height because their children are floated elements.
+ if ( 0 == setHeight ) {
+ $( '> *', this ).each( function() {
+ setHeight += $( this ).outerHeight( false );
+ } );
+ }
+
+ // Determine position of bottom of set by adding its height to the scroll position of its top.
+ setBottom = setTop + setHeight;
+
+ // Populate setsInView object. While this logic could all be combined into a single conditional statement, this is easier to understand.
+ if ( setTop < windowTop && setBottom > windowBottom ) { // top of set is above window, bottom is below
+ setsInView.push({'id': id, 'top': setTop, 'bottom': setBottom, 'pageNum': setPageNum });
+ }
+ else if( setTop > windowTop && setTop < windowBottom ) { // top of set is between top (gt) and bottom (lt)
+ setsInView.push({'id': id, 'top': setTop, 'bottom': setBottom, 'pageNum': setPageNum });
+ }
+ else if( setBottom > windowTop && setBottom < windowBottom ) { // bottom of set is between top (gt) and bottom (lt)
+ setsInView.push({'id': id, 'top': setTop, 'bottom': setBottom, 'pageNum': setPageNum });
+ }
+ } );
+
+ // Parse number of sets found in view in an attempt to update the URL to match the set that comprises the majority of the window.
+ if ( 0 == setsInView.length ) {
+ pageNum = -1;
+ }
+ else if ( 1 == setsInView.length ) {
+ var setData = setsInView.pop();
+
+ // If the first set of IS posts is in the same view as the posts loaded in the template by WordPress, determine how much of the view is comprised of IS-loaded posts
+ if ( ( ( windowBottom - setData.top ) / windowSize ) < 0.5 )
+ pageNum = -1;
+ else
+ pageNum = setData.pageNum;
+ }
+ else {
+ var majorityPercentageInView = 0;
+
+ // Identify the IS set that comprises the majority of the current window and set the URL to it.
+ $.each( setsInView, function( i, setData ) {
+ var topInView = 0,
+ bottomInView = 0,
+ percentOfView = 0;
+
+ // Figure percentage of view the current set represents
+ if ( setData.top > windowTop && setData.top < windowBottom )
+ topInView = ( windowBottom - setData.top ) / windowSize;
+
+ if ( setData.bottom > windowTop && setData.bottom < windowBottom )
+ bottomInView = ( setData.bottom - windowTop ) / windowSize;
+
+ // Figure out largest percentage of view for current set
+ if ( topInView >= bottomInView )
+ percentOfView = topInView;
+ else if ( bottomInView >= topInView )
+ percentOfView = bottomInView;
+
+ // Does current set's percentage of view supplant the largest previously-found set?
+ if ( percentOfView > majorityPercentageInView ) {
+ pageNum = setData.pageNum;
+ majorityPercentageInView = percentOfView;
+ }
+ } );
+ }
+
+ // If a page number could be determined, update the URL
+ // -1 indicates that the original requested URL should be used.
+ if ( 'number' == typeof pageNum ) {
+ if ( pageNum != -1 )
+ pageNum += ( 0 == self.offset ) ? 1 : self.offset;
+
+ self.updateURL( pageNum );
+ }
+}
+
+/**
+ * Update address bar to reflect archive page URL for a given page number.
+ * Checks if URL is different to prevent polution of browser history.
+ */
+Scroller.prototype.updateURL = function( page ) {
+ var self = this,
+ pageSlug = -1 == page ? self.origURL : window.location.protocol + '//' + self.history.host + self.history.path.replace( /%d/, page );
+
+ if ( window.location.href != pageSlug )
+ history.pushState( null, null, pageSlug );
+}
+
+/**
+ * Ready, set, go!
+ */
+$( document ).ready( function() {
+ // Check for our variables
+ if ( ! infiniteScroll )
+ return;
+
+ // Set ajaxurl (for brevity)
+ ajaxurl = infiniteScroll.settings.ajaxurl;
+
+ // Set stats, used for tracking stats
+ stats = infiniteScroll.settings.stats;
+
+ // Define what type of infinity we have, grab text for click-handle
+ type = infiniteScroll.settings.type;
+ text = infiniteScroll.settings.text;
+ totop = infiniteScroll.settings.totop;
+
+ // Initialize the scroller (with the ID of the element from the theme)
+ infiniteScroll.scroller = new Scroller( infiniteScroll.settings );
+
+ /**
+ * Monitor user scroll activity to update URL to correspond to archive page for current set of IS posts
+ * IE only supports pushState() in v10 and above, so don't bother if those conditions aren't met.
+ */
+ if ( ! isIE || ( isIE && IEVersion >= 10 ) ) {
+ $( window ).bind( 'scroll', function() {
+ clearTimeout( timer );
+ timer = setTimeout( infiniteScroll.scroller.determineURL , 100 );
+ });
+ }
+});
+
+
+})(jQuery); // Close closure \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll/infinity.php b/plugins/jetpack/modules/infinite-scroll/infinity.php
new file mode 100644
index 00000000..ad57f1b6
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/infinity.php
@@ -0,0 +1,945 @@
+<?php
+
+/*
+Plugin Name: The Neverending Home Page.
+Plugin URI: http://automattic.com/
+Description: Adds infinite scrolling support to the front-end blog post view for themes, pulling the next set of posts automatically into view when the reader approaches the bottom of the page.
+Version: 1.1
+Author: Automattic
+Author URI: http://automattic.com/
+License: GNU General Public License v2 or later
+License URI: http://www.gnu.org/licenses/gpl-2.0.html
+*/
+
+/**
+ * Class: The_Neverending_Home_Page relies on add_theme_support, expects specific
+ * styling from each theme; including fixed footer.
+ */
+class The_Neverending_Home_Page {
+ /**
+ *
+ */
+ function __construct() {
+ add_filter( 'pre_get_posts', array( $this, 'posts_per_page_query' ) );
+
+ add_action( 'admin_init', array( $this, 'settings_api_init' ) );
+ add_action( 'template_redirect', array( $this, 'action_template_redirect' ) );
+ add_action( 'template_redirect', array( $this, 'ajax_response' ) );
+ add_action( 'custom_ajax_infinite_scroll', array( $this, 'query' ) );
+ add_action( 'the_post', array( $this, 'preserve_more_tag' ) );
+ add_action( 'get_footer', array( $this, 'footer' ) );
+
+ // Plugin compatibility
+ add_filter( 'grunion_contact_form_redirect_url', array( $this, 'filter_grunion_redirect_url' ) );
+
+ // Parse IS settings from theme
+ self::get_settings();
+ }
+
+ /**
+ * Initialize our static variables
+ */
+ static $the_time = null;
+ static $settings = null; // Don't access directly, instead use self::get_settings().
+
+ static $option_name_enabled = 'infinite_scroll';
+
+ /**
+ * Parse IS settings provided by theme
+ *
+ * @uses get_theme_support, infinite_scroll_has_footer_widgets, sanitize_title, add_action, get_option, wp_parse_args, is_active_sidebar
+ * @return object
+ */
+ static function get_settings() {
+ if ( is_null( self::$settings ) ) {
+ $css_pattern = '#[^A-Z\d\-_]#i';
+
+ $settings = $defaults = array(
+ 'type' => 'scroll', // scroll | click
+ 'requested_type' => 'scroll', // store the original type for use when logic overrides it
+ 'footer_widgets' => false, // true | false | sidebar_id | array of sidebar_ids -- last two are checked with is_active_sidebar
+ 'container' => 'content', // container html id
+ 'wrapper' => true, // true | false | html class
+ 'render' => false, // optional function, otherwise the `content` template part will be used
+ 'footer' => true, // boolean to enable or disable the infinite footer | string to provide an html id to derive footer width from
+ 'posts_per_page' => false // int | false to set based on IS type
+ );
+
+ // Validate settings passed through add_theme_support()
+ $_settings = get_theme_support( 'infinite-scroll' );
+
+ if ( is_array( $_settings ) ) {
+ // Preferred implementation, where theme provides an array of options
+ if ( isset( $_settings[0] ) && is_array( $_settings[0] ) ) {
+ foreach ( $_settings[0] as $key => $value ) {
+ switch ( $key ) {
+ case 'type' :
+ if ( in_array( $value, array( 'scroll', 'click' ) ) )
+ $settings[ $key ] = $settings['requested_type'] = $value;
+
+ break;
+
+ case 'footer_widgets' :
+ if ( is_string( $value ) )
+ $settings[ $key ] = sanitize_title( $value );
+ elseif ( is_array( $value ) )
+ $settings[ $key ] = array_map( 'sanitize_title', $value );
+ elseif ( is_bool( $value ) )
+ $settings[ $key ] = $value;
+
+ break;
+
+ case 'container' :
+ case 'wrapper' :
+ if ( 'wrapper' == $key && is_bool( $value ) ) {
+ $settings[ $key ] = $value;
+ }
+ else {
+ $value = preg_replace( $css_pattern, '', $value );
+
+ if ( ! empty( $value ) )
+ $settings[ $key ] = $value;
+ }
+
+ break;
+
+ case 'render' :
+ if ( false !== $value && is_callable( $value ) ) {
+ $settings[ $key ] = $value;
+
+ add_action( 'infinite_scroll_render', $value );
+ }
+
+ break;
+
+ case 'footer' :
+ if ( is_bool( $value ) ) {
+ $settings[ $key ] = $value;
+ }
+ elseif ( is_string( $value ) ) {
+ $value = preg_replace( $css_pattern, '', $value );
+
+ if ( ! empty( $value ) )
+ $settings[ $key ] = $value;
+ }
+
+ break;
+
+ case 'posts_per_page' :
+ if ( is_numeric( $value ) )
+ $settings[ $key ] = (int) $value;
+
+ break;
+
+ default:
+ continue;
+
+ break;
+ }
+ }
+ }
+ // Checks below are for backwards compatibility
+ elseif ( is_string( $_settings[0] ) ) {
+ // Container to append new posts to
+ $settings['container'] = preg_replace( $css_pattern, '', $_settings[0] );
+
+ // Wrap IS elements?
+ if ( isset( $_settings[1] ) )
+ $settings['wrapper'] = (bool) $_settings[1];
+ }
+ }
+
+ // Always ensure all values are present in the final array
+ $settings = wp_parse_args( $settings, $defaults );
+
+ // Check if a legacy `infinite_scroll_has_footer_widgets()` function is defined and override the footer_widgets parameter's value.
+ // Otherwise, if a widget area ID or array of IDs was provided in the footer_widgets parameter, check if any contains any widgets.
+ // It is safe to use `is_active_sidebar()` before the sidebar is registered as this function doesn't check for a sidebar's existence when determining if it contains any widgets.
+ if ( function_exists( 'infinite_scroll_has_footer_widgets' ) ) {
+ $settings['footer_widgets'] = (bool) infinite_scroll_has_footer_widgets();
+ }
+ elseif ( is_array( $settings['footer_widgets'] ) ) {
+ $sidebar_ids = $settings['footer_widgets'];
+ $settings['footer_widgets'] = false;
+
+ foreach ( $sidebar_ids as $sidebar_id ) {
+ if ( is_active_sidebar( $sidebar_id ) ) {
+ $settings['footer_widgets'] = true;
+ break;
+ }
+ }
+
+ unset( $sidebar_ids );
+ unset( $sidebar_id );
+ }
+ elseif ( is_string( $settings['footer_widgets'] ) ) {
+ $settings['footer_widgets'] = (bool) is_active_sidebar( $settings['footer_widgets'] );
+ }
+
+ // For complex logic, let themes filter the `footer_widgets` parameter.
+ $settings['footer_widgets'] = apply_filters( 'infinite_scroll_has_footer_widgets', $settings['footer_widgets'] );
+
+ // Finally, after all of the sidebar checks and filtering, ensure that a boolean value is present, otherwise set to default of `false`.
+ if ( ! is_bool( $settings['footer_widgets'] ) )
+ $settings['footer_widgets'] = false;
+
+ // Ensure that IS is enabled and no footer widgets exist if the IS type isn't already "click".
+ if ( 'click' != $settings['type'] ) {
+ // Check the setting status
+ $disabled = '' === get_option( self::$option_name_enabled ) ? true : false;
+
+ // Footer content or Reading option check
+ if ( $settings['footer_widgets'] || $disabled )
+ $settings['type'] = 'click';
+ }
+
+ // Backwards compatibility for posts_per_page setting
+ if ( false === $settings['posts_per_page'] )
+ $settings['posts_per_page'] = 'click' == $settings['type'] ? (int) get_option( 'posts_per_page' ) : 7;
+
+ // Store final settings in a class static to avoid reparsing
+ self::$settings = apply_filters( 'infinite_scroll_settings', $settings );
+ }
+
+ return (object) self::$settings;
+ }
+
+ /**
+ * Has infinite scroll been triggered?
+ */
+ static function got_infinity() {
+ return isset( $_GET[ 'infinity' ] );
+ }
+
+ /**
+ * The more tag will be ignored by default if the blog page isn't our homepage.
+ * Let's force the $more global to false.
+ */
+ function preserve_more_tag( $array ) {
+ global $more;
+
+ if ( self::got_infinity() )
+ $more = 0; //0 = show content up to the more tag. Add more link.
+
+ return $array;
+ }
+
+ /**
+ * Add a checkbox field to Settings > Reading
+ * for enabling infinite scroll.
+ *
+ * Only show if the current theme supports infinity.
+ *
+ * @uses current_theme_supports, add_settings_field, __, register_setting
+ * @action admin_init
+ * @return null
+ */
+ function settings_api_init() {
+ if ( ! current_theme_supports( 'infinite-scroll' ) )
+ return;
+
+ // Add the setting field [infinite_scroll] and place it in Settings > Reading
+ add_settings_field( self::$option_name_enabled, '<span id="infinite-scroll-options">' . __( 'To infinity and beyond', 'jetpack' ) . '</span>', array( $this, 'infinite_setting_html' ), 'reading' );
+ register_setting( 'reading', self::$option_name_enabled, 'esc_attr' );
+ }
+
+ /**
+ * HTML code to display a checkbox true/false option
+ * for the infinite_scroll setting.
+ */
+ function infinite_setting_html() {
+ $notice = '<em>' . __( "We've disabled this option for you since you have footer widgets in Appearance &rarr; Widgets, or because your theme does not support infinite scroll.", 'jetpack' ) . '</em>';
+
+ // If the blog has footer widgets, show a notice instead of the checkbox
+ if ( self::get_settings()->footer_widgets || 'click' == self::get_settings()->requested_type ) {
+ echo '<label>' . $notice . '</label>';
+ } else {
+ echo '<label><input name="infinite_scroll" type="checkbox" value="1" ' . checked( 1, '' !== get_option( self::$option_name_enabled ), false ) . ' /> ' . __( 'Scroll Infinitely', 'jetpack' ) . '</br><small>' . sprintf( __( '(Shows %s posts on each load)', 'jetpack' ), number_format_i18n( self::get_settings()->posts_per_page ) ) . '</small>' . '</label>';
+ }
+ }
+
+ /**
+ * Does the legwork to determine whether the feature is enabled.
+ *
+ * @uses current_theme_supports, self::archive_supports_infinity, self::get_settings, self::set_last_post_time, add_filter, wp_enqueue_script, plugins_url, wp_enqueue_style, add_action
+ * @action template_redirect
+ * @return null
+ */
+ function action_template_redirect() {
+ // Check that we support infinite scroll, and are on the home page.
+ if ( ! current_theme_supports( 'infinite-scroll' ) || ! self::archive_supports_infinity() )
+ return;
+
+ $id = self::get_settings()->container;
+
+ // Check that we have an id.
+ if ( empty( $id ) )
+ return;
+
+ // Bail if there are not enough posts for infinity.
+ if ( ! self::set_last_post_time() )
+ return;
+
+ // Add a class to the body.
+ add_filter( 'body_class', array( $this, 'body_class' ) );
+
+ // Add our scripts.
+ wp_enqueue_script( 'the-neverending-homepage', plugins_url( 'infinity.js', __FILE__ ), array( 'jquery' ), '20130101' );
+
+ // Add our default styles.
+ wp_enqueue_style( 'the-neverending-homepage', plugins_url( 'infinity.css', __FILE__ ), array(), '20120612' );
+
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_spinner_scripts' ) );
+
+ add_action( 'wp_head', array( $this, 'action_wp_head' ), 2 );
+
+ add_action( 'wp_footer', array( $this, 'action_wp_footer' ), 99999999 );
+
+ add_filter( 'infinite_scroll_results', array( $this, 'filter_infinite_scroll_results' ), 10, 3 );
+ }
+
+ /**
+ * Enqueue spinner scripts.
+ */
+ function enqueue_spinner_scripts() {
+ wp_enqueue_script( 'jquery.spin' );
+ }
+
+ /**
+ * Adds an 'infinite-scroll' class to the body.
+ */
+ function body_class( $classes ) {
+ $classes[] = 'infinite-scroll';
+
+ if ( 'scroll' == self::get_settings()->type )
+ $classes[] = 'neverending';
+
+ return $classes;
+ }
+
+ /**
+ * Grab the timestamp for the last post.
+ * @return string 'Y-m-d H:i:s' or null
+ */
+ function set_last_post_time( $date = false ) {
+ global $posts;
+ $count = count( $posts );
+
+ if ( ! empty( $date ) && preg_match( '|\d{4}\-\d{2}\-\d{2}|', $_GET['date'] ) ) {
+ self::$the_time = "$date 00:00:00";
+ return self::$the_time;
+ }
+
+ // If we don't have enough posts for infinity, return early
+ if ( ! $count || $count < self::get_settings()->posts_per_page )
+ return self::$the_time;
+
+ $last_post = end( $posts );
+
+ // If the function is called again but we already have a value, return it
+ if ( null != self::$the_time ) {
+ return self::$the_time;
+ }
+ else if ( isset( $last_post->post_date_gmt ) ) {
+ // Grab the latest post time in Y-m-d H:i:s gmt format
+ self::$the_time = $last_post->post_date_gmt;
+ }
+
+ return self::$the_time;
+ }
+
+ /**
+ * Create a where clause that will make sure post queries
+ * will always return results prior to (descending sort)
+ * or before (ascending sort) the last post date.
+ *
+ * @param string $where
+ * @param object $query
+ * @filter posts_where
+ * @return string
+ */
+ function query_time_filter( $where, $query ) {
+ global $wpdb;
+
+ $operator = 'ASC' == $query->get( 'order' ) ? '>' : '<';
+
+ // Construct the date query using our timestamp
+ $where .= $wpdb->prepare( " AND post_date_gmt {$operator} %s", self::set_last_post_time() );
+
+ return $where;
+ }
+
+ /**
+ * Let's overwrite the default post_per_page setting to always display a fixed amount.
+ *
+ * @global $wp_the_query Used to provide compatibility back to WP 3.2
+ * @param object $query
+ * @uses self::archive_supports_infinity, self::get_settings
+ * @return null
+ */
+ function posts_per_page_query( $query ) {
+ global $wp_the_query;
+
+ if ( self::archive_supports_infinity() && $query === $wp_the_query ) // After 3.3, this line would be: if ( self::archive_supports_infinity() && $query->is_main_query() )
+ $query->set( 'posts_per_page', self::get_settings()->posts_per_page );
+ }
+
+ /**
+ * Check if the IS output should be wrapped in a div.
+ * Setting value can be a boolean or a string specifying the class applied to the div.
+ *
+ * @uses self::get_settings
+ * @return bool
+ */
+ function has_wrapper() {
+ return (bool) self::get_settings()->wrapper;
+ }
+
+ /**
+ * Returns the Ajax url
+ *
+ * @global $wp
+ * @uses home_url, is_ssl, add_query_arg, trailingslashit, apply_filters
+ * @return string
+ */
+ function ajax_url() {
+ global $wp;
+
+ // When using default permalinks, $wp->request will be null, so we reconstruct the request from the query arguments WP parsed.
+ if ( is_null( $wp->request ) ) {
+ $base_url = home_url( '/', is_ssl() ? 'https' : 'http' );
+ $base_url = add_query_arg( $wp->query_vars, $base_url );
+ } else {
+ $base_url = home_url( trailingslashit( $wp->request ), is_ssl() ? 'https' : 'http' );
+ }
+
+ $ajaxurl = add_query_arg( array( 'infinity' => 'scrolling' ), $base_url );
+
+ return apply_filters( 'infinite_scroll_ajax_url', $ajaxurl );
+ }
+
+ /**
+ * Our own Ajax response, avoiding calling admin-ajax
+ */
+ function ajax_response() {
+ // Only proceed if the url query has a key of "Infinity"
+ if ( ! self::got_infinity() )
+ return false;
+
+ define( 'DOING_AJAX', true );
+
+ @header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
+ send_nosniff_header();
+
+ do_action( 'custom_ajax_infinite_scroll' );
+ die( '0' );
+ }
+
+ /**
+ * Prints the relevant infinite scroll settings in JS.
+ *
+ * @uses self::get_settings, esc_js, esc_url_raw, self::has_wrapper, __, apply_filters, do_action
+ * @action wp_head
+ * @return string
+ */
+ function action_wp_head() {
+ global $wp_query, $wp_the_query, $wp_rewrite;
+
+ // Base JS settings
+ $js_settings = array(
+ 'id' => self::get_settings()->container,
+ 'ajaxurl' => esc_url_raw( self::ajax_url() ),
+ 'type' => esc_js( self::get_settings()->type ),
+ 'wrapper' => self::has_wrapper(),
+ 'wrapper_class' => is_string( self::get_settings()->wrapper ) ? esc_js( self::get_settings()->wrapper ) : 'infinite-wrap',
+ 'footer' => is_string( self::get_settings()->footer ) ? esc_js( self::get_settings()->footer ) : self::get_settings()->footer,
+ 'text' => esc_js( __( 'Older posts', 'jetpack' ) ),
+ 'totop' => esc_js( __( 'Scroll back to top', 'jetpack' ) ),
+ 'order' => 'DESC',
+ 'scripts' => array(),
+ 'styles' => array(),
+ 'google_analytics' => false,
+ 'offset' => $wp_query->get( 'paged' ),
+ 'history' => array(
+ 'host' => preg_replace( '#^http(s)?://#i', '', untrailingslashit( get_option( 'home' ) ) ),
+ 'path' => self::get_request_path(),
+ 'use_trailing_slashes' => $wp_rewrite->use_trailing_slashes
+ )
+ );
+
+ // Optional order param
+ if ( isset( $_GET['order'] ) ) {
+ $order = strtoupper( $_GET['order'] );
+
+ if ( in_array( $order, array( 'ASC', 'DESC' ) ) )
+ $js_settings['order'] = $order;
+ }
+
+ $js_settings = apply_filters( 'infinite_scroll_js_settings', $js_settings );
+
+ do_action( 'infinite_scroll_wp_head' );
+
+ ?>
+ <script type="text/javascript">
+ //<![CDATA[
+ var infiniteScroll = <?php echo json_encode( array( 'settings' => $js_settings ) ); ?>;
+ //]]>
+ </script>
+ <?php
+ }
+
+ /**
+ * Build path data for current request.
+ * Used for Google Analytics and pushState history tracking.
+ *
+ * @global $wp_rewrite
+ * @global $wp
+ * @uses user_trailingslashit, sanitize_text_field, add_query_arg
+ * @return string|bool
+ */
+ private function get_request_path() {
+ global $wp_rewrite;
+
+ if ( $wp_rewrite->using_permalinks() ) {
+ global $wp;
+
+ // If called too early, bail
+ if ( ! isset( $wp->request ) )
+ return false;
+
+ // Determine path for paginated version of current request
+ if ( false != preg_match( '#' . $wp_rewrite->pagination_base . '/\d+/?$#i', $wp->request ) )
+ $path = preg_replace( '#' . $wp_rewrite->pagination_base . '/\d+$#i', $wp_rewrite->pagination_base . '/%d', $wp->request );
+ else
+ $path = $wp->request . '/' . $wp_rewrite->pagination_base . '/%d';
+
+ // Slashes everywhere we need them
+ if ( 0 !== strpos( $path, '/' ) )
+ $path = '/' . $path;
+
+ $path = user_trailingslashit( $path );
+ }
+ else {
+ // Clean up raw $_GET input
+ $path = array_map( 'sanitize_text_field', $_GET );
+ $path = array_filter( $path );
+
+ $path['paged'] = '%d';
+
+ $path = add_query_arg( $path, '/' );
+ }
+
+ return empty( $path ) ? false : $path;
+ }
+
+ /**
+ * Provide IS with a list of the scripts and stylesheets already present on the page.
+ * Since posts may contain require additional assets that haven't been loaded, this data will be used to track the additional assets.
+ *
+ * @global $wp_scripts, $wp_styles
+ * @action wp_footer
+ * @return string
+ */
+ function action_wp_footer() {
+ global $wp_scripts, $wp_styles;
+
+ $scripts = is_a( $wp_scripts, 'WP_Scripts' ) ? $wp_scripts->done : array();
+ $scripts = apply_filters( 'infinite_scroll_existing_scripts', $scripts );
+
+ $styles = is_a( $wp_styles, 'WP_Styles' ) ? $wp_styles->done : array();
+ $styles = apply_filters( 'infinite_scroll_existing_stylesheets', $styles );
+
+ ?><script type="text/javascript">
+ jQuery.extend( infiniteScroll.settings.scripts, <?php echo json_encode( $scripts ); ?> );
+ jQuery.extend( infiniteScroll.settings.styles, <?php echo json_encode( $styles ); ?> );
+ </script><?php
+ }
+
+ /**
+ * Identify additional scripts required by the latest set of IS posts and provide the necessary data to the IS response handler.
+ *
+ * @global $wp_scripts
+ * @uses sanitize_text_field, add_query_arg
+ * @filter infinite_scroll_results
+ * @return array
+ */
+ function filter_infinite_scroll_results( $results, $query_args, $wp_query ) {
+ // Don't bother unless there are posts to display
+ if ( 'success' != $results['type'] )
+ return $results;
+
+ // Parse and sanitize the script handles already output
+ $initial_scripts = isset( $_GET['scripts'] ) && is_array( $_GET['scripts'] ) ? array_map( 'sanitize_text_field', $_GET['scripts'] ) : false;
+
+ if ( is_array( $initial_scripts ) ) {
+ global $wp_scripts;
+
+ // Identify new scripts needed by the latest set of IS posts
+ $new_scripts = array_diff( $wp_scripts->done, $initial_scripts );
+
+ // If new scripts are needed, extract relevant data from $wp_scripts
+ if ( ! empty( $new_scripts ) ) {
+ $results['scripts'] = array();
+
+ foreach ( $new_scripts as $handle ) {
+ // Abort if somehow the handle doesn't correspond to a registered script
+ if ( ! isset( $wp_scripts->registered[ $handle ] ) )
+ continue;
+
+ // Provide basic script data
+ $script_data = array(
+ 'handle' => $handle,
+ 'footer' => ( is_array( $wp_scripts->in_footer ) && in_array( $handle, $wp_scripts->in_footer ) ),
+ 'extra_data' => $wp_scripts->print_extra_script( $handle, false )
+ );
+
+ // Base source
+ $src = $wp_scripts->registered[ $handle ]->src;
+
+ // Take base_url into account
+ if ( strpos( $src, 'http' ) !== 0 )
+ $src = $wp_scripts->base_url . $src;
+
+ // Version and additional arguments
+ if ( null === $wp_scripts->registered[ $handle ]->ver )
+ $ver = '';
+ else
+ $ver = $wp_scripts->registered[ $handle ]->ver ? $wp_scripts->registered[ $handle ]->ver : $wp_scripts->default_version;
+
+ if ( isset($wp_scripts->args[ $handle ] ) )
+ $ver = $ver ? $ver . '&amp;' . $wp_scripts->args[$handle] : $wp_scripts->args[$handle];
+
+ // Full script source with version info
+ $script_data['src'] = add_query_arg( 'ver', $ver, $src );
+
+ // Add script to data that will be returned to IS JS
+ array_push( $results['scripts'], $script_data );
+ }
+ }
+ }
+
+ // Expose additional script data to filters, but only include in final `$results` array if needed.
+ if ( ! isset( $results['scripts'] ) )
+ $results['scripts'] = array();
+
+ $results['scripts'] = apply_filters( 'infinite_scroll_additional_scripts', $results['scripts'], $initial_scripts, $results, $query_args, $wp_query );
+
+ if ( empty( $results['scripts'] ) )
+ unset( $results['scripts' ] );
+
+ // Parse and sanitize the style handles already output
+ $initial_styles = isset( $_GET['styles'] ) && is_array( $_GET['styles'] ) ? array_map( 'sanitize_text_field', $_GET['styles'] ) : false;
+
+ if ( is_array( $initial_styles ) ) {
+ global $wp_styles;
+
+ // Identify new styles needed by the latest set of IS posts
+ $new_styles = array_diff( $wp_styles->done, $initial_styles );
+
+ // If new styles are needed, extract relevant data from $wp_styles
+ if ( ! empty( $new_styles ) ) {
+ $results['styles'] = array();
+
+ foreach ( $new_styles as $handle ) {
+ // Abort if somehow the handle doesn't correspond to a registered stylesheet
+ if ( ! isset( $wp_styles->registered[ $handle ] ) )
+ continue;
+
+ // Provide basic style data
+ $style_data = array(
+ 'handle' => $handle,
+ 'media' => 'all'
+ );
+
+ // Base source
+ $src = $wp_styles->registered[ $handle ]->src;
+
+ // Take base_url into account
+ if ( strpos( $src, 'http' ) !== 0 )
+ $src = $wp_styles->base_url . $src;
+
+ // Version and additional arguments
+ if ( null === $wp_styles->registered[ $handle ]->ver )
+ $ver = '';
+ else
+ $ver = $wp_styles->registered[ $handle ]->ver ? $wp_styles->registered[ $handle ]->ver : $wp_styles->default_version;
+
+ if ( isset($wp_styles->args[ $handle ] ) )
+ $ver = $ver ? $ver . '&amp;' . $wp_styles->args[$handle] : $wp_styles->args[$handle];
+
+ // Full stylesheet source with version info
+ $style_data['src'] = add_query_arg( 'ver', $ver, $src );
+
+ // Parse stylesheet's conditional comments if present, converting to logic executable in JS
+ if ( isset( $wp_styles->registered[ $handle ]->extra['conditional'] ) && $wp_styles->registered[ $handle ]->extra['conditional'] ) {
+ // First, convert conditional comment operators to standard logical operators. %ver is replaced in JS with the IE version
+ $style_data['conditional'] = str_replace( array(
+ 'lte',
+ 'lt',
+ 'gte',
+ 'gt'
+ ), array(
+ '%ver <=',
+ '%ver <',
+ '%ver >=',
+ '%ver >',
+ ), $wp_styles->registered[ $handle ]->extra['conditional'] );
+
+ // Next, replace any !IE checks. These shouldn't be present since WP's conditional stylesheet implementation doesn't support them, but someone could be _doing_it_wrong().
+ $style_data['conditional'] = preg_replace( '#!\s*IE(\s*\d+){0}#i', '1==2', $style_data['conditional'] );
+
+ // Lastly, remove the IE strings
+ $style_data['conditional'] = str_replace( 'IE', '', $style_data['conditional'] );
+ }
+
+ // Parse requested media context for stylesheet
+ if ( isset( $wp_styles->registered[ $handle ]->args ) )
+ $style_data['media'] = esc_attr( $wp_styles->registered[ $handle ]->args );
+
+ // Add stylesheet to data that will be returned to IS JS
+ array_push( $results['styles'], $style_data );
+ }
+ }
+ }
+
+ // Expose additional stylesheet data to filters, but only include in final `$results` array if needed.
+ if ( ! isset( $results['styles'] ) )
+ $results['styles'] = array();
+
+ $results['styles'] = apply_filters( 'infinite_scroll_additional_stylesheets', $results['styles'], $initial_styles, $results, $query_args, $wp_query );
+
+ if ( empty( $results['styles'] ) )
+ unset( $results['styles' ] );
+
+ // Lastly, return the IS results array
+ return $results;
+ }
+
+ /**
+ * Runs the query and returns the results via JSON.
+ * Triggered by an AJAX request.
+ *
+ * @global $wp_query
+ * @global $wp_the_query
+ * @uses current_user_can, get_option, self::set_last_post_time, current_user_can, apply_filters, self::get_settings, add_filter, WP_Query, remove_filter, have_posts, wp_head, do_action, add_action, this::render, this::has_wrapper, esc_attr, wp_footer, sharing_register_post_for_share_counts, get_the_id
+ * @return string or null
+ */
+ function query() {
+ global $wp_query, $wp_the_query;
+
+ if ( ! isset( $_GET['page'] ) || ! current_theme_supports( 'infinite-scroll' ) )
+ die;
+
+ $page = (int) $_GET['page'];
+ $sticky = get_option( 'sticky_posts' );
+
+ if ( ! empty( $_GET['date'] ) )
+ self::set_last_post_time( $_GET['date'] );
+
+ $post_status = array( 'publish' );
+ if ( current_user_can( 'read_private_posts' ) )
+ array_push( $post_status, 'private' );
+
+ $order = in_array( $_GET['order'], array( 'ASC', 'DESC' ) ) ? $_GET['order'] : 'DESC';
+
+ $query_args = array_merge( $wp_the_query->query_vars, array(
+ 'paged' => $page,
+ 'post_status' => $post_status,
+ 'posts_per_page' => self::get_settings()->posts_per_page,
+ 'post__not_in' => ( array ) $sticky,
+ 'order' => $order
+ ) );
+
+ // By default, don't query for a specific page of a paged post object.
+ // This argument comes from merging $wp_the_query.
+ // Since IS is only used on archives, we should always display the first page of any paged content.
+ unset( $query_args['page'] );
+
+ $query_args = apply_filters( 'infinite_scroll_query_args', $query_args );
+
+ // Add query filter that checks for posts below the date
+ add_filter( 'posts_where', array( $this, 'query_time_filter' ), 10, 2 );
+
+ $wp_the_query = $wp_query = new WP_Query( $query_args );
+
+ remove_filter( 'posts_where', array( $this, 'query_time_filter' ), 10, 2 );
+
+ $results = array();
+
+ if ( have_posts() ) {
+ // Fire wp_head to ensure that all necessary scripts are enqueued. Output isn't used, but scripts are extracted in self::action_wp_footer.
+ ob_start();
+ wp_head();
+ ob_end_clean();
+
+ $results['type'] = 'success';
+
+ // First, try theme's specified rendering handler, either specified via `add_theme_support` or by hooking to this action directly.
+ ob_start();
+ do_action( 'infinite_scroll_render' );
+ $results['html'] = ob_get_clean();
+
+ // Fall back if a theme doesn't specify a rendering function. Because themes may hook additional functions to the `infinite_scroll_render` action, `has_action()` is ineffective here.
+ if ( empty( $results['html'] ) ) {
+ add_action( 'infinite_scroll_render', array( $this, 'render' ) );
+ rewind_posts();
+
+ ob_start();
+ do_action( 'infinite_scroll_render' );
+ $results['html'] = ob_get_clean();
+ }
+
+ // If primary and fallback rendering methods fail, prevent further IS rendering attempts. Otherwise, wrap the output if requested.
+ if ( empty( $results['html'] ) ) {
+ unset( $results['html'] );
+ do_action( 'infinite_scroll_empty' );
+ $results['type'] = 'empty';
+ }
+ elseif ( $this->has_wrapper() ) {
+ $wrapper_classes = is_string( self::get_settings()->wrapper ) ? self::get_settings()->wrapper : 'infinite-wrap';
+ $wrapper_classes .= ' infinite-view-' . $page;
+ $wrapper_classes = trim( $wrapper_classes );
+
+ $results['html'] = '<div class="' . esc_attr( $wrapper_classes ) . '" id="infinite-view-' . $page . '" data-page-num="' . $page . '">' . $results['html'] . '</div>';
+ }
+
+ // Fire wp_footer to ensure that all necessary scripts are enqueued. Output isn't used, but scripts are extracted in self::action_wp_footer.
+ ob_start();
+ wp_footer();
+ ob_end_clean();
+
+ // Loop through posts to capture sharing data for new posts loaded via Infinite Scroll
+ if ( 'success' == $results['type'] && function_exists( 'sharing_register_post_for_share_counts' ) ) {
+ global $jetpack_sharing_counts;
+
+ while( have_posts() ) {
+ the_post();
+
+ sharing_register_post_for_share_counts( get_the_ID() );
+ }
+
+ $results['postflair'] = array_flip( $jetpack_sharing_counts );
+ }
+ } else {
+ do_action( 'infinite_scroll_empty' );
+ $results['type'] = 'empty';
+ }
+
+ echo json_encode( apply_filters( 'infinite_scroll_results', $results, $query_args, $wp_query ) );
+ die;
+ }
+
+ /**
+ * Rendering fallback used when themes don't specify their own handler.
+ *
+ * @uses have_posts, the_post, get_template_part, get_post_format
+ * @action infinite_scroll_render
+ * @return string
+ */
+ function render() {
+ while ( have_posts() ) {
+ the_post();
+
+ get_template_part( 'content', get_post_format() );
+ }
+ }
+
+ /**
+ * Allow plugins to filter what archives Infinite Scroll supports
+ *
+ * @uses apply_filters, current_theme_supports, is_home, is_archive, self::get_settings
+ * @return bool
+ */
+ public static function archive_supports_infinity() {
+ return (bool) apply_filters( 'infinite_scroll_archive_supported', current_theme_supports( 'infinite-scroll' ) && ( is_home() || is_archive() ), self::get_settings() );
+ }
+
+ /**
+ * The Infinite Blog Footer
+ *
+ * @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
+ * @return string or null
+ */
+ function footer() {
+ // Bail if theme requested footer not show
+ if ( false == self::get_settings()->footer )
+ return;
+
+ // Bail if there are not enough posts for infinity.
+ if ( ! self::set_last_post_time() )
+ return;
+
+ // We only need the new footer for the 'scroll' type
+ if ( 'scroll' != self::get_settings()->type || ! self::archive_supports_infinity() )
+ return;
+
+ $credits = '<a href="http://wordpress.org/" rel="generator">Proudly powered by WordPress</a> ';
+ $credits .= sprintf( __( 'Theme: %1$s.', 'jetpack' ), function_exists( 'wp_get_theme' ) ? wp_get_theme()->Name : get_current_theme() );
+ $credits = apply_filters( 'infinite_scroll_credit', $credits );
+
+ ?>
+ <div id="infinite-footer">
+ <div class="container">
+ <div class="blog-info">
+ <a id="infinity-blog-title" href="<?php echo home_url( '/' ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home">
+ <?php bloginfo( 'name' ); ?>
+ </a>
+ </div>
+ <div class="blog-credits">
+ <?php echo $credits; ?>
+ </div>
+ </div>
+ </div><!-- #infinite-footer -->
+ <?php
+ }
+
+ /**
+ * Ensure that IS doesn't interfere with Grunion by stripping IS query arguments from the Grunion redirect URL.
+ * When arguments are present, Grunion redirects to the IS AJAX endpoint.
+ *
+ * @param string $url
+ * @uses remove_query_arg
+ * @filter grunion_contact_form_redirect_url
+ * @return string
+ */
+ public function filter_grunion_redirect_url( $url ) {
+ // Remove IS query args, if present
+ if ( false !== strpos( $url, 'infinity=scrolling' ) ) {
+ $url = remove_query_arg( array(
+ 'infinity',
+ 'action',
+ 'page',
+ 'order',
+ 'scripts',
+ 'styles'
+ ), $url );
+ }
+
+ return $url;
+ }
+};
+
+/**
+ * Initialize The_Neverending_Home_Page
+ */
+function the_neverending_home_page_init() {
+ if ( ! current_theme_supports( 'infinite-scroll' ) )
+ return;
+
+ new The_Neverending_Home_Page;
+}
+add_action( 'init', 'the_neverending_home_page_init', 20 );
+
+/**
+ * Check whether the current theme is infinite-scroll aware.
+ * If so, include the files which add theme support.
+ */
+function the_neverending_home_page_theme_support() {
+ $theme_name = get_stylesheet();
+
+ $customization_file = apply_filters( 'infinite_scroll_customization_file', dirname( __FILE__ ) . "/themes/{$theme_name}.php", $theme_name );
+
+ if ( is_readable( $customization_file ) )
+ require_once( $customization_file );
+}
+add_action( 'after_setup_theme', 'the_neverending_home_page_theme_support', 5 );
diff --git a/plugins/jetpack/modules/infinite-scroll/themes/twentyeleven.css b/plugins/jetpack/modules/infinite-scroll/themes/twentyeleven.css
new file mode 100644
index 00000000..cc232785
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/themes/twentyeleven.css
@@ -0,0 +1,45 @@
+/* =Infinity Styles
+-------------------------------------------------------------- */
+.infinite-scroll #main:after {
+ clear: both;
+ content: '';
+ display: block;
+}
+.infinite-scroll #content {
+ margin-bottom: 40px;
+}
+.infinite-scroll.neverending #content {
+ margin-bottom: 70px;
+}
+.infinite-scroll .infinite-wrap {
+ border-top: none;
+ padding-top: 0;
+}
+.infinite-scroll .infinite-wrap .hentry:last-child {
+ border-bottom: 1px solid #ddd;
+}
+.infinite-scroll .infinite-wrap:last-of-type .hentry:last-child {
+ border-bottom: none;
+}
+
+/**
+ * Elements to hide:
+ * (footer widgets, post navigation, regular footer)
+ */
+.infinite-scroll.neverending #colophon #supplementary,
+.infinite-scroll #nav-below,
+.infinite-scroll.neverending #colophon {
+ display: none;
+}
+
+/* Hooks to infinity-end body class to restore footer */
+.infinity-end.neverending #colophon {
+ display: block;
+}
+
+/* For responsive CSS */
+@media (max-width: 800px) {
+ .infinite-scroll #infinite-handle {
+ padding-bottom: 40px;
+ }
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll/themes/twentyeleven.php b/plugins/jetpack/modules/infinite-scroll/themes/twentyeleven.php
new file mode 100644
index 00000000..a80ee810
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/themes/twentyeleven.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Infinite Scroll Theme Assets
+ *
+ * Register support for @Twenty Eleven and enqueue relevant styles.
+ */
+
+/**
+ * Add theme support for infinity scroll
+ */
+function twenty_eleven_infinite_scroll_init() {
+ add_theme_support( 'infinite-scroll', array(
+ 'container' => 'content',
+ 'footer_widgets' => array( 'sidebar-3', 'sidebar-4', 'sidebar-5' ),
+ 'footer' => 'page',
+ ) );
+}
+add_action( 'init', 'twenty_eleven_infinite_scroll_init' );
+
+/**
+ * Enqueue CSS stylesheet with theme styles for infinity.
+ */
+function twenty_eleven_infinite_scroll_enqueue_styles() {
+ // Add theme specific styles.
+ wp_enqueue_style( 'infinity-twentyeleven', plugins_url( 'twentyeleven.css', __FILE__ ), array( 'the-neverending-homepage' ), '20121002' );
+}
+add_action( 'wp_enqueue_scripts', 'twenty_eleven_infinite_scroll_enqueue_styles', 25 ); \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll/themes/twentyten.css b/plugins/jetpack/modules/infinite-scroll/themes/twentyten.css
new file mode 100644
index 00000000..889abb3f
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/themes/twentyten.css
@@ -0,0 +1,25 @@
+/* =Infinity Styles
+-------------------------------------------------------------- */
+.infinite-scroll #wrapper {
+ margin-bottom: 40px;
+}
+.infinite-scroll #content {
+ margin-bottom: 50px;
+}
+.infinite-scroll #content .infinite-wrap {
+ padding-top: 0;
+ border-top: 0;
+}
+/* Elements to hide */
+.infinite-scroll #nav-above,
+.infinite-scroll #nav-below,
+.infinite-scroll.neverending #footer {
+ display: none;
+}
+/* Restore the footer when IS is finished */
+.infinity-end.neverending #footer {
+ display: block;
+}
+#infinite-footer .blog-info a {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll/themes/twentyten.php b/plugins/jetpack/modules/infinite-scroll/themes/twentyten.php
new file mode 100644
index 00000000..094cef9c
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/themes/twentyten.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Infinite Scroll Theme Assets
+ *
+ * Register support for @Twenty Ten and enqueue relevant styles.
+ */
+
+/**
+ * Add theme support for infinity scroll
+ */
+function twenty_ten_infinite_scroll_init() {
+ add_theme_support( 'infinite-scroll', array(
+ 'container' => 'content',
+ 'render' => 'twenty_ten_infinite_scroll_render',
+ 'footer' => 'wrapper',
+ ) );
+}
+add_action( 'init', 'twenty_ten_infinite_scroll_init' );
+
+/**
+ * Set the code to be rendered on for calling posts,
+ * hooked to template parts when possible.
+ *
+ * Note: must define a loop.
+ */
+function twenty_ten_infinite_scroll_render() {
+ get_template_part( 'loop' );
+}
+
+/**
+ * Enqueue CSS stylesheet with theme styles for infinity.
+ */
+function twenty_ten_infinite_scroll_enqueue_styles() {
+ // Add theme specific styles.
+ wp_enqueue_style( 'infinity-twentyten', plugins_url( 'twentyten.css', __FILE__ ), array( 'the-neverending-homepage' ), '20121002' );
+}
+add_action( 'wp_enqueue_scripts', 'twenty_ten_infinite_scroll_enqueue_styles', 25 );
+
+/**
+ * Do we have footer widgets?
+ */
+function twenty_ten_has_footer_widgets( $has_widgets ) {
+ if ( is_active_sidebar( 'first-footer-widget-area' ) || is_active_sidebar( 'second-footer-widget-area' ) || is_active_sidebar( 'third-footer-widget-area' ) || is_active_sidebar( 'fourth-footer-widget-area' ) )
+ $has_widgets = true;
+
+ return $has_widgets;
+}
+add_filter( 'infinite_scroll_has_footer_widgets', 'twenty_ten_has_footer_widgets' ); \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll/themes/twentytwelve.css b/plugins/jetpack/modules/infinite-scroll/themes/twentytwelve.css
new file mode 100644
index 00000000..032c2c9a
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/themes/twentytwelve.css
@@ -0,0 +1,33 @@
+/* =Infinity Styles
+-------------------------------------------------------------- */
+.infinite-scroll .site-content:after {
+ clear: both;
+ content: '';
+ display: block;
+}
+.infinite-wrap {
+ border-top: 0;
+}
+.infinite-scroll.neverending .site-content {
+ margin-bottom: 48px;
+ margin-bottom: 3.428571429rem;
+}
+
+/* Elements to hide: post navigation, regular footer */
+.infinite-scroll #nav-below,
+.infinite-scroll.neverending #colophon {
+ display: none;
+}
+
+/* Hooks to infinity-end body class to restore footer */
+.infinity-end.neverending #colophon {
+ display: block;
+}
+
+/* For responsive CSS */
+@media (max-width: 599px) {
+ .infinite-scroll #infinite-handle {
+ padding-bottom: 48px;
+ padding-bottom: 3.428571429rem;
+ }
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/infinite-scroll/themes/twentytwelve.php b/plugins/jetpack/modules/infinite-scroll/themes/twentytwelve.php
new file mode 100644
index 00000000..f8b77011
--- /dev/null
+++ b/plugins/jetpack/modules/infinite-scroll/themes/twentytwelve.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Infinite Scroll Theme Assets
+ *
+ * Register support for Twenty Twelve and enqueue relevant styles.
+ */
+
+/**
+ * Add theme support for infinite scroll
+ */
+function twenty_twelve_infinite_scroll_init() {
+ add_theme_support( 'infinite-scroll', array(
+ 'container' => 'content',
+ 'footer' => 'page'
+ ) );
+}
+add_action( 'after_setup_theme', 'twenty_twelve_infinite_scroll_init' );
+
+/**
+ * Enqueue CSS stylesheet with theme styles for infinity.
+ */
+function twenty_twelve_infinite_scroll_enqueue_styles() {
+ // Add theme specific styles.
+ wp_enqueue_style( 'infinity-twentytwelve', plugins_url( 'twentytwelve.css', __FILE__ ), array( 'the-neverending-homepage' ), '20120817' );
+}
+add_action( 'wp_enqueue_scripts', 'twenty_twelve_infinite_scroll_enqueue_styles', 25 );
+
+/**
+ * Handle `footer_widgets` argument for mobile devices
+ *
+ * @param bool $has_widgets
+ * @uses jetpack_is_mobile, is_front_page, is_active_sidebar
+ * @filter infinite_scroll_has_footer_widgets
+ * @return bool
+ */
+function twenty_twelve_has_footer_widgets( $has_widgets ) {
+ if ( function_exists( 'jetpack_is_mobile' ) && jetpack_is_mobile() ) {
+ if ( is_front_page() && ( is_active_sidebar( 'sidebar-2' ) || is_active_sidebar( 'sidebar-3' ) ) )
+ $has_widgets = true;
+ elseif ( is_active_sidebar( 'sidebar-1' ) )
+ $has_widgets = true;
+ }
+
+ return $has_widgets;
+}
+add_filter( 'infinite_scroll_has_footer_widgets', 'twenty_twelve_has_footer_widgets' ); \ No newline at end of file
diff --git a/plugins/jetpack/modules/json-api.php b/plugins/jetpack/modules/json-api.php
new file mode 100644
index 00000000..fb1473ff
--- /dev/null
+++ b/plugins/jetpack/modules/json-api.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Module Name: JSON API
+ * Module Description: Allow applications to securely access your content through the cloud.
+ * Sort Order: 100
+ * First Introduced: 1.9
+ */
+
+function jetpack_json_api_toggle() {
+ $jetpack = Jetpack::init();
+ $jetpack->sync->register( 'noop' );
+
+ if ( false !== strpos( current_filter(), 'jetpack_activate_module_' ) ) {
+ Jetpack::check_privacy( __FILE__ );
+ }
+}
+
+add_action( 'jetpack_activate_module_json-api', 'jetpack_json_api_toggle' );
+add_action( 'jetpack_deactivate_module_json-api', 'jetpack_json_api_toggle' );
diff --git a/plugins/jetpack/modules/latex.php b/plugins/jetpack/modules/latex.php
index 4e4d9db2..76066cd6 100644
--- a/plugins/jetpack/modules/latex.php
+++ b/plugins/jetpack/modules/latex.php
@@ -1,7 +1,7 @@
<?php
/**
* Module Name: Beautiful Math
- * Module Description: Mark up your posts with the <img src="http://l.wordpress.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-2" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" /> markup language, perfect for complex mathematical equations and other &#252;ber-geekery.
+ * Module Description: Mark up your posts with the <img src="//s0.wp.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-2" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" /> markup language, perfect for complex mathematical equations and other &#252;ber-geekery.
* Sort Order: 12
* First Introduced: 1.1
*/
@@ -64,11 +64,11 @@ function latex_entity_decode( $latex ) {
}
function latex_render( $latex, $fg, $bg, $s = 0 ) {
- $url = ( is_ssl() ? 'https://s-ssl.wordpress.com' : 'http://s0.wp.com' ) . "/latex.php?latex=" . urlencode( $latex ) . "&bg=$bg&fg=$fg&s=$s";
+ $url = "//s0.wp.com/latex.php?latex=" . urlencode( $latex ) . "&bg=" . $bg . "&fg=" . $fg . "&s=" . $s;
$url = esc_url( $url );
$alt = str_replace( '\\', '&#92;', esc_attr( $latex ) );
- return "<img src='$url' alt='$alt' title='$alt' class='latex' />";
+ return '<img src="' . $url . '" alt="' . $alt . '" title="' . $alt . '" class="latex" />';
}
/**
diff --git a/plugins/jetpack/modules/likes.php b/plugins/jetpack/modules/likes.php
new file mode 100644
index 00000000..753d4ab4
--- /dev/null
+++ b/plugins/jetpack/modules/likes.php
@@ -0,0 +1,970 @@
+<?php
+/**
+ * Module Name: Likes
+ * 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.
+ * First Introduced: 2.2
+ * Sort Order: 4
+ */
+class Jetpack_Likes {
+ var $version = '20130226';
+
+ function &init() {
+ static $instance = NULL;
+
+ if ( ! $instance ) {
+ $instance = new Jetpack_Likes;
+ }
+
+ return $instance;
+ }
+
+ function __construct() {
+ $this->in_jetpack = ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ? false : true;
+
+ add_action( 'init', array( &$this, 'action_init' ) );
+
+ if ( $this->in_jetpack ) {
+ add_action( 'jetpack_activate_module_likes', array( $this, 'module_toggle' ) );
+ add_action( 'jetpack_deactivate_module_likes', array( $this, 'module_toggle' ) );
+
+ Jetpack::enable_module_configurable( __FILE__ );
+ Jetpack::module_configuration_load( __FILE__, array( 'Jetpack_Likes', 'configuration_redirect' ) );
+
+ add_action('admin_print_scripts-settings_page_sharing', array( &$this, 'load_jp_css' ) );
+ add_filter( 'sharing_show_buttons_on_row_start', array( $this, 'configuration_target_area' ) );
+
+ $active = Jetpack::get_active_modules();
+
+ if ( ! in_array( 'sharedaddy', $active ) && ! in_array( 'publicize', $active ) ) {
+ add_action( 'admin_menu', array( $this, 'sharing_menu' ) ); // we don't have a sharing page yet
+ }
+
+ if ( in_array( 'publicize', $active ) && ! in_array( 'sharedaddy', $active ) ) {
+ add_action( 'pre_admin_screen_sharing', array( $this, 'sharing_block' ), 20 ); // we have a sharing page but not the global options area
+ add_action( 'pre_admin_screen_sharing', array( $this, 'updated_message' ), -10 );
+ }
+
+ if( ! in_array( 'sharedaddy', $active ) ) {
+ add_action( 'admin_init', array( $this, 'process_update_requests_if_sharedaddy_not_loaded' ) );
+ add_action( 'sharing_global_options', array( $this, 'admin_settings_showbuttonon_init' ), 19 );
+ add_action( 'sharing_admin_update', array( $this, 'admin_settings_showbuttonon_callback' ), 19 );
+ add_action( 'admin_init', array( $this, 'add_meta_box' ) );
+ } else {
+ add_filter( 'sharing_meta_box_title', array( $this, 'add_likes_to_sharing_meta_box_title' ) );
+ add_action( 'start_sharing_meta_box_content', array( $this, 'meta_box_content' ) );
+ }
+ } else { // wpcom
+ add_action( 'admin_init', array( $this, 'add_meta_box' ) );
+ add_action( 'end_likes_meta_box_content', array( $this, 'sharing_meta_box_content' ) );
+ add_filter( 'likes_meta_box_title', array( $this, 'add_likes_to_sharing_meta_box_title' ) );
+ }
+
+ add_action( 'admin_bar_menu', array( $this, 'admin_bar_likes' ), 60 );
+
+ add_action( 'save_post', array( $this, 'meta_box_save' ) );
+ add_action( 'sharing_global_options', array( $this, 'admin_settings_init' ), 20 );
+ add_action( 'sharing_admin_update', array( $this, 'admin_settings_callback' ), 20 );
+ }
+
+ function module_toggle() {
+ $jetpack = Jetpack::init();
+ $jetpack->sync->register( 'noop' );
+ }
+
+ /**
+ * Redirects to the likes section of the sharing page.
+ */
+ function configuration_redirect() {
+ wp_safe_redirect( admin_url( 'options-general.php?page=sharing#likes' ) );
+ die();
+ }
+
+ /**
+ * Loads Jetpack's CSS on the sharing page so we can use .jetpack-targetable
+ */
+ function load_jp_css() {
+ Jetpack::init()->admin_styles();
+ }
+
+ /**
+ * Adds in the jetpack-targetable class so when we visit sharing#likes our like settings get highlighted by a yellow box
+ * @param string $html row heading for the sharedaddy "which page" setting
+ * @return string html with the jetpack-targetable class and likes id. tbody gets closed after the like settings
+ */
+ function configuration_target_area( $html = '' ) {
+ $html = "<tbody id='likes' class='jetpack-targetable'>" . $html;
+ return $html;
+ }
+
+ /**
+ * Replaces the "Sharing" title for the post screen metabox with "Likes and Shares"
+ * @param string $title The current title of the metabox, not needed/used.
+ */
+ function add_likes_to_sharing_meta_box_title( $title ) {
+ return __( 'Likes and Shares', 'jetpack' );
+ }
+
+ /**
+ * Adds a metabox to the post screen if the sharing one doesn't currently exist.
+ */
+ function add_meta_box() {
+ if ( apply_filters( 'post_flair_disable', false ) )
+ return;
+
+ $post_types = get_post_types( array( 'public' => true ) );
+ $title = apply_filters( 'likes_meta_box_title', __( 'Likes', 'jetpack' ) );
+ foreach( $post_types as $post_type ) {
+ add_meta_box( 'likes_meta', $title, array( $this, 'meta_box_content' ), $post_type, 'advanced', 'high' );
+ }
+ }
+
+ function meta_box_save( $post_id ) {
+ if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
+ return $post_id;
+
+ // Record sharing disable. Only needs to be done for WPCOM
+ if ( ! $this->in_jetpack ) {
+ if ( isset( $_POST['post_type'] ) && ( 'post' == $_POST['post_type'] || 'page' == $_POST['post_type'] ) ) {
+ if ( isset( $_POST['wpl_sharing_status_hidden'] ) && !isset( $_POST['wpl_enable_post_sharing'] ) ) {
+ update_post_meta( $post_id, 'sharing_disabled', 1 );
+ } else {
+ delete_post_meta( $post_id, 'sharing_disabled' );
+ }
+ }
+ }
+
+ if ( empty( $_POST['wpl_like_status_hidden'] ) )
+ return $post_id;
+
+ if ( 'post' == $_POST['post_type'] ) {
+ if ( !current_user_can( 'edit_post', $post_id ) ) {
+ return $post_id;
+ }
+ }
+
+ // Record a change in like status for this post - only if it contradicts the
+ // site like setting.
+ if ( ( $this->is_enabled_sitewide() && empty( $_POST['wpl_enable_post_likes'] ) ) || ( ! $this->is_enabled_sitewide() && !empty( $_POST['wpl_enable_post_likes'] ) ) ) {
+ update_post_meta( $post_id, 'switch_like_status', 1 );
+ //$g_gif = file_get_contents( 'http://stats.wordpress.com/g.gif?v=wpcom-no-pv&x_likes=switched_post_like_status' ); @todo stat
+ } else {
+ delete_post_meta( $post_id, 'switch_like_status' );
+ }
+
+ return $post_id;
+ }
+
+ /**
+ * Shows the likes option in the post screen metabox.
+ */
+ function meta_box_content( $post ) {
+ $post_id = ! empty( $post->ID ) ? (int) $post->ID : get_the_ID();
+ $checked = true;
+ $disabled = ! $this->is_enabled_sitewide();
+ $switched_status = get_post_meta( $post_id, 'switch_like_status', true );
+
+ if ( $disabled && empty( $switched_status ) || false == $disabled && !empty( $switched_status ) )
+ $checked = false;
+
+ do_action( 'start_likes_meta_box_content', $post );
+ ?>
+
+ <p>
+ <label for="wpl_enable_post_likes">
+ <input type="checkbox" name="wpl_enable_post_likes" id="wpl_enable_post_likes" value="1" <?php checked( $checked ); ?>>
+ <?php esc_html_e( 'Show likes.', 'jetpack' ); ?>
+ </label>
+ <input type="hidden" name="wpl_like_status_hidden" value="1" />
+ </p> <?php
+ do_action( 'end_likes_meta_box_content', $post );
+ }
+
+ /**
+ * WordPress.com: Metabox option for sharing (sharedaddy will handle this on the JP blog)
+ */
+ function sharing_meta_box_content( $post ) {
+ $post_id = ! empty( $post->ID ) ? (int) $post->ID : get_the_ID();
+ $disabled = get_post_meta( $post_id, 'sharing_disabled', true ); ?>
+ <p>
+ <label for="wpl_enable_post_sharing">
+ <input type="checkbox" name="wpl_enable_post_sharing" id="wpl_enable_post_sharing" value="1" <?php checked( !$disabled ); ?>>
+ <?php _e( 'Show sharing buttons.', 'jetpack' ); ?>
+ </label>
+ <input type="hidden" name="wpl_sharing_status_hidden" value="1" />
+ </p> <?php
+ }
+
+ /**
+ * The actual options block to be inserted into the sharing page.
+ */
+ function admin_settings_init() { ?>
+ <tr>
+ <th scope="row">
+ <label><?php esc_html_e( 'WordPress.com Likes are', 'jetpack' ); ?></label>
+ </th>
+ <td>
+ <div>
+ <label>
+ <input type="radio" class="code" name="wpl_default" value="on" <?php checked( $this->is_enabled_sitewide(), true ); ?> />
+ <?php esc_html_e( 'On for all posts', 'jetpack' ); ?>
+ </label>
+ </div>
+ <div>
+ <label>
+ <input type="radio" class="code" name="wpl_default" value="off" <?php checked( $this->is_enabled_sitewide(), false ); ?> />
+ <?php esc_html_e( 'Turned on per post', 'jetpack' ); ?>
+ </label>
+ <div>
+ </td>
+ </tr> <?php /*
+ <tr>
+ <th scope="row">
+ <label><?php esc_html_e( 'Comment Likes', 'jetpack' ); ?></label>
+ </th>
+ <td>
+ <div>
+ <label>
+ <input type="checkbox" class="code" name="jetpack_comment_likes_enabled" value="1" <?php checked( $this->is_comments_enabled(), true ); ?> />
+ <?php esc_html_e( 'Allow people to like comments', 'jetpack' ); ?>
+ </label>
+ </div>
+ </td>
+ </tr> */ ?>
+ </tbody> <?php // closes the tbody attached to sharing_show_buttons_on_row_start... ?>
+ <?php }
+
+ /**
+ * If sharedaddy is not loaded, we don't have the "Show buttons on" yet, so we need to add that since it affects likes too.
+ */
+ function admin_settings_showbuttonon_init() { ?>
+ <?php echo apply_filters( 'sharing_show_buttons_on_row_start', '<tr valign="top">' ); ?>
+ <th scope="row"><label><?php _e( 'Show buttons on', 'jetpack' ); ?></label></th>
+ <td>
+ <?php
+ $br = false;
+ $shows = array_values( get_post_types( array( 'public' => true ) ) );
+ array_unshift( $shows, 'index' );
+ $global = $this->get_options();
+ foreach ( $shows as $show ) :
+ if ( 'index' == $show ) {
+ $label = __( 'Front Page, Archive Pages, and Search Results', 'jetpack' );
+ } else {
+ $post_type_object = get_post_type_object( $show );
+ $label = $post_type_object->labels->name;
+ }
+ ?>
+ <?php if ( $br ) echo '<br />'; ?><label><input type="checkbox"<?php checked( in_array( $show, $global['show'] ) ); ?> name="show[]" value="<?php echo esc_attr( $show ); ?>" /> <?php echo esc_html( $label ); ?></label>
+ <?php $br = true; endforeach; ?>
+ </td>
+ <?php echo apply_filters( 'sharing_show_buttons_on_row_end', '</tr>' ); ?>
+ <?php }
+
+
+ /**
+ * If sharedaddy is not loaded, we still need to save the the settings of the "Show buttons on" option.
+ */
+ function admin_settings_showbuttonon_callback() {
+ $options = get_option( 'sharing-options' );
+ if ( !is_array( $options ) )
+ $options = array();
+
+ $shows = array_values( get_post_types( array( 'public' => true ) ) );
+ $shows[] = 'index';
+ $data = $_POST;
+
+ if ( isset( $data['show'] ) ) {
+ if ( is_scalar( $data['show'] ) ) {
+ switch ( $data['show'] ) {
+ case 'posts' :
+ $data['show'] = array( 'post', 'page' );
+ break;
+ case 'index' :
+ $data['show'] = array( 'index' );
+ break;
+ case 'posts-index' :
+ $data['show'] = array( 'post', 'page', 'index' );
+ break;
+ }
+ }
+
+ if ( $data['show'] = array_intersect( $data['show'], $shows ) ) {
+ $options['global']['show'] = $data['show'];
+ }
+ } else {
+ $options['global']['show'] = array();
+ }
+
+ update_option( 'sharing-options', $options );
+ }
+
+ /**
+ * Adds the admin update hook so we can save settings even if Sharedaddy is not enabled.
+ */
+ function process_update_requests_if_sharedaddy_not_loaded() {
+ if ( isset( $_GET['page'] ) && ( $_GET['page'] == 'sharing.php' || $_GET['page'] == 'sharing' ) ) {
+ if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'sharing-options' ) ) {
+ do_action( 'sharing_admin_update' );
+ wp_safe_redirect( admin_url( 'options-general.php?page=sharing&update=saved' ) );
+ die();
+ }
+ }
+ }
+
+ /**
+ * Saves the setting in the database, bumps a stat on WordPress.com
+ */
+ function admin_settings_callback() {
+ // We're looking for these, and doing a dance to set some stats and save
+ // them together in array option.
+ $new_state = !empty( $_POST['wpl_default'] ) ? $_POST['wpl_default'] : 'on';
+ $db_state = $this->is_enabled_sitewide();
+
+ /** Default State *********************************************************/
+
+ // Checked (enabled)
+ switch( $new_state ) {
+ case 'off' :
+ if ( true == $db_state && ! $this->in_jetpack ) {
+ $g_gif = file_get_contents( 'http://stats.wordpress.com/g.gif?v=wpcom-no-pv&x_likes=disabled_likes' );
+ }
+ update_option( 'disabled_likes', 1 );
+ break;
+ case 'on' :
+ default:
+ if ( false == $db_state && ! $this->in_jetpack ) {
+ $g_gif = file_get_contents( 'http://stats.wordpress.com/g.gif?v=wpcom-no-pv&x_likes=reenabled_likes' );
+ }
+ delete_option( 'disabled_likes' );
+ break;
+ }
+
+
+ // comment setting
+ $new_comments_state = !empty( $_POST['jetpack_comment_likes_enabled'] ) ? $_POST['jetpack_comment_likes_enabled'] : false;
+ switch( (bool) $new_comments_state ) {
+ case true:
+ update_option( 'jetpack_comment_likes_enabled', 1 );
+ break;
+ case false:
+ default:
+ update_option( 'jetpack_comment_likes_enabled', 0 );
+ break;
+ }
+ }
+
+ /**
+ * Adds the 'sharing' menu to the settings menu.
+ * Only ran if sharedaddy and publicize are not already active.
+ */
+ function sharing_menu() {
+ add_submenu_page( 'options-general.php', esc_html__( 'Sharing Settings', 'jetpack' ), esc_html__( 'Sharing', 'jetpack' ), 'manage_options', 'sharing', array( $this, 'sharing_page' ) );
+ }
+
+ /**
+ * Provides a sharing page with the sharing_global_options hook
+ * so we can display the setting.
+ * Only ran if sharedaddy and publicize are not already active.
+ */
+ function sharing_page() {
+ $this->updated_message(); ?>
+ <div class="wrap">
+ <div class="icon32" id="icon-options-general"><br /></div>
+ <h2><?php esc_html_e( 'Sharing Settings', 'jetpack' ); ?></h2>
+ <?php do_action( 'pre_admin_screen_sharing' ) ?>
+ <?php $this->sharing_block(); ?>
+ </div> <?php
+ }
+
+ /**
+ * Returns the settings have been saved message.
+ */
+ function updated_message() {
+ if ( isset( $_GET['update'] ) && $_GET['update'] == 'saved' )
+ echo '<div class="updated"><p>' . esc_html__( 'Settings have been saved', 'jetpack' ) . '</p></div>';
+ }
+
+ /**
+ * Returns just the "sharing buttons" w/ like option block, so it can be inserted into different sharing page contexts
+ */
+ function sharing_block() { ?>
+ <h3><?php esc_html_e( 'Sharing Buttons', 'jetpack' ); ?></h3>
+ <form method="post" action="">
+ <table class="form-table">
+ <tbody>
+ <?php do_action( 'sharing_global_options' ); ?>
+ </tbody>
+ </table>
+
+ <p class="submit">
+ <input type="submit" name="submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes', 'jetpack' ); ?>" />
+ </p>
+
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce( 'sharing-options' );?>" />
+ </form> <?php
+ }
+
+ function action_init() {
+ if ( is_admin() )
+ return;
+
+ if ( ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) ||
+ ( defined( 'APP_REQUEST' ) && APP_REQUEST ) ||
+ ( defined( 'REST_API_REQUEST' ) && REST_API_REQUEST ) ||
+ ( defined( 'COOKIE_AUTH_REQUEST' ) && COOKIE_AUTH_REQUEST ) ||
+ ( defined( 'JABBER_SERVER' ) && JABBER_SERVER ) )
+ return;
+
+ // Comment Likes widget has been disabled, pending performance improvements.
+ // add_filter( 'comment_text', array( &$this, 'comment_likes' ), 10, 2 );
+
+ if ( $this->in_jetpack ) {
+ add_filter( 'the_content', array( &$this, 'post_likes' ), 30, 1 );
+ wp_enqueue_script( 'postmessage', plugins_url( '_inc/postmessage.js', dirname(__FILE__) ), array( 'jquery' ), JETPACK__VERSION, false );
+ wp_enqueue_script( 'jquery_inview', plugins_url( '_inc/jquery.inview.js', dirname(__FILE__) ), array( 'jquery' ), JETPACK__VERSION, false );
+ wp_enqueue_style( 'jetpack_likes', plugins_url( 'likes/style.css', __FILE__ ), array(), JETPACK__VERSION );
+ } else {
+ add_filter( 'post_flair', array( &$this, 'post_likes' ), 30, 1 );
+ add_filter( 'post_flair_block_css', array( $this, 'post_flair_service_enabled_like' ) );
+
+ wp_enqueue_script( 'postmessage', '/wp-content/js/postmessage.js', array( 'jquery' ), JETPACK__VERSION, false );
+ wp_enqueue_script( 'jquery_inview', '/wp-content/js/jquery/jquery.inview.js', array( 'jquery' ), JETPACK__VERSION, false );
+ wp_enqueue_style( 'jetpack_likes', plugins_url( 'jetpack-likes.css', __FILE__ ), array(), JETPACK__VERSION );
+ }
+ }
+
+ function post_likes( $content ) {
+ global $post;
+
+ if ( ! $this->is_likes_visible() )
+ return $content;
+
+ $protocol = 'http';
+ if ( is_ssl() )
+ $protocol = 'https';
+
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ $blog_id = get_current_blog_id();
+ $bloginfo = get_blog_details( (int) $blog_id );
+ $domain = $bloginfo->domain;
+ } else {
+ $jetpack = Jetpack::init();
+ $blog_id = $jetpack->get_option( 'id' );
+ $url = home_url();
+ $url_parts = parse_url( $url );
+ $domain = $url_parts['host'];
+ }
+
+ add_filter( 'wp_footer', array( $this, 'likes_master' ) );
+
+ $src = sprintf( '%1$s://widgets.wp.com/likes/#blog_id=%2$d&post_id=%3$d&origin=%1$s://%4$s', $protocol, $blog_id, $post->ID, $domain );
+ $name = sprintf( 'like-post-frame-%1$d-%2$d', $blog_id, $post->ID );
+ $wrapper = sprintf( 'like-post-wrapper-%1$d-%2$d', $blog_id, $post->ID );
+
+ $html = "<div class='sharedaddy sd-block sd-like jetpack-likes-widget-wrapper jetpack-likes-widget-unloaded' id='$wrapper' data-src='$src' data-name='$name'><h3 class='sd-title'>" . esc_html__( 'Like this:', 'jetpack' ) . '</h3>';
+ $html .= "<div class='post-likes-widget-placeholder' style='height:55px'><span class='button'><span>" . esc_html__( 'Like', 'jetpack' ) . '</span></span> <span class="loading">' . esc_html__( 'Loading...', 'jetpack' ) . '</span></div>';
+ $html .= "<span class='sd-text-color'></span><a class='sd-link-color'></a>";
+ $html .= '</div>';
+
+ return $content . $html;
+ }
+
+ function comment_likes( $content, $comment = null ) {
+ if ( empty( $comment ) )
+ return $content;
+
+ if ( ! $this->is_comments_enabled() )
+ return $content;
+
+ $protocol = 'http';
+ if ( is_ssl() )
+ $protocol = 'https';
+
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ $blog_id = get_current_blog_id();
+ $bloginfo = get_blog_details( (int) $blog_id );
+ $domain = $bloginfo->domain;
+ } else {
+ $jetpack = Jetpack::init();
+ $blog_id = $jetpack->get_option( 'id' );
+ $url = home_url();
+ $url_parts = parse_url( $url );
+ $domain = $url_parts['host'];
+ }
+
+ add_filter( 'wp_footer', array( $this, 'likes_master' ) );
+
+ $src = sprintf( '%1$s://widgets.wp.com/likes/#blog_id=%2$d&comment_id=%3$d&origin=%1$s://%4$s', $protocol, $blog_id, $comment->comment_ID, $domain );
+ $name = sprintf( 'like-comment-frame-%1$d-%2$d', $blog_id, $comment->comment_ID );
+ $wrapper = sprintf( 'like-comment-wrapper-%1$d-%2$d', $blog_id, $comment->comment_ID );
+
+ $html = "<div><div class='jetpack-likes-widget-wrapper jetpack-likes-widget-unloaded' id='$wrapper'>";
+ $html .= "<iframe class='comment-likes-widget jetpack-likes-widget' name='$name' height='16px' width='100%' data='$src'></iframe>";
+ $html .= '</div></div>';
+ return $content . $html;
+ }
+
+ function post_flair_service_enabled_like( $classes ) {
+ $classes[] = 'sd-like-enabled';
+ return $classes;
+ }
+
+ function admin_bar_likes() {
+ global $wp_admin_bar, $post;
+
+ if ( ! $this->is_admin_bar_button_visible() ) {
+ return;
+ }
+
+ $protocol = 'http';
+ if ( is_ssl() )
+ $protocol = 'https';
+
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ $blog_id = get_current_blog_id();
+ $bloginfo = get_blog_details( (int) $blog_id );
+ $domain = $bloginfo->domain;
+ } else {
+ $jetpack = Jetpack::init();
+ $blog_id = $jetpack->get_option( 'id' );
+ $url = home_url();
+ $url_parts = parse_url( $url );
+ $domain = $url_parts['host'];
+ }
+
+ add_filter( 'wp_footer', array( $this, 'likes_master' ) );
+
+ $src = sprintf( '%1$s://widgets.wp.com/likes/#blog_id=%2$d&post_id=%3$d&origin=%1$s://%4$s', $protocol, $blog_id, $post->ID, $domain );
+
+ $html = "<iframe class='admin-bar-likes-widget jetpack-likes-widget' frameBorder='0' name='admin-bar-likes-widget' src='$src'></iframe>";
+
+ $node = array(
+ 'id' => 'admin-bar-likes-widget',
+ 'meta' => array(
+ 'html' => $html
+ )
+ );
+
+ $wp_admin_bar->add_node( $node );
+ }
+
+ function likes_master() {
+ $protocol = 'http';
+ if ( is_ssl() )
+ $protocol = 'https';
+
+ $locale = ( '' == get_locale() || 'en' == get_locale() ) ? '' : '&lang=' . strtolower( substr( get_locale(), 0, 2 ) );
+ $src = sprintf( '%1$s://widgets.wp.com/likes/master.html?ver=%2$s#ver=%2$s%3$s', $protocol, $this->version, $locale );
+
+ $likersText = wp_kses( __( '<span>%d</span> bloggers like this:', 'jetpack' ), array( 'span' => array() ) );
+?>
+ <iframe src='<?php echo $src; ?>' id='likes-master' name='likes-master' style='display:none;'></iframe>
+ <div id='likes-other-gravatars'><div class="likes-text"><?php echo $likersText; ?></div><ul class="wpl-avatars sd-like-gravatars"></ul></div>
+ <script type="text/javascript">
+ //<![CDATA[
+ var jetpackLikesWidgetQueue = [];
+ var jetpackLikesMasterReady = false;
+
+ function JetpackLikespostMessage( message, target ) {
+ if ( "string" === typeof message ){
+ try{
+ message = JSON.parse( message );
+ }
+ catch(e) {
+ return;
+ }
+ }
+
+ pm( {
+ target: target,
+ type: 'likesMessage',
+ data: message,
+ origin: '*'
+ } );
+ }
+
+ function JetpackLikesMessageListener( event ) {
+ if ( "undefined" == typeof event.event )
+ return;
+
+ if ( 'masterReady' == event.event ) {
+ jQuery( document ).ready( function() {
+ jetpackLikesMasterReady = true;
+
+ var stylesData = {
+ event: 'injectStyles'
+ };
+
+ if ( jQuery( 'iframe.admin-bar-likes-widget' ).length > 0 ) {
+ JetpackLikespostMessage( { event: 'adminBarEnabled' }, window.frames[ 'likes-master' ] );
+
+ stylesData.adminBarStyles = {
+ background: jQuery( '#wpadminbar .quicklinks li#wp-admin-bar-wpl-like > a' ).css( 'background' )
+ };
+ }
+
+ if ( !window.addEventListener )
+ jQuery( '#wp-admin-bar-admin-bar-likes-widget' ).hide();
+
+ stylesData.textStyles = {
+ color: jQuery( '.sd-text-color').css( 'color' ),
+ fontFamily: jQuery( '.sd-text-color' ).css( 'font-family' ),
+ fontSize: jQuery( '.sd-text-color' ).css( 'font-size' ),
+ direction: jQuery( '.sd-text-color' ).css( 'direction' ),
+ fontWeight: jQuery( '.sd-text-color' ).css( 'font-weight' ),
+ fontStyle: jQuery( '.sd-text-color' ).css( 'font-style' ),
+ textDecoration: jQuery( '.sd-text-color' ).css('text-decoration')
+ };
+
+ stylesData.linkStyles = {
+ color: jQuery( '.sd-link-color' ).css('color'),
+ fontFamily: jQuery( '.sd-link-color' ).css('font-family'),
+ fontSize: jQuery( '.sd-link-color' ).css('font-size'),
+ textDecoration: jQuery( '.sd-link-color' ).css('text-decoration'),
+ fontWeight: jQuery( '.sd-link-color' ).css( 'font-weight' ),
+ fontStyle: jQuery( '.sd-link-color' ).css( 'font-style' )
+ };
+
+ JetpackLikespostMessage( stylesData, window.frames[ 'likes-master' ] );
+
+ var requests = [];
+ jQuery( '.jetpack-likes-widget-wrapper' ).each( function( i ) {
+ var regex = /like-(post|comment)-wrapper-(\d+)-(\d+)/;
+ var match = regex.exec( this.id );
+ if ( ! match || match.length != 4 )
+ return;
+
+ var info = {
+ blog_id: match[2],
+ width: this.width
+ };
+
+ if ( 'post' == match[1] ) {
+ info.post_id = match[3];
+ } else if ( 'comment' == match[1] ) {
+ info.comment_id = match[3];
+ }
+
+ requests.push( info );
+ });
+
+ JetpackLikespostMessage( { event: 'initialBatch', requests: requests }, window.frames['likes-master'] );
+
+ jQuery( document ).on( 'inview', 'div.jetpack-likes-widget-unloaded', function() {
+ jetpackLikesWidgetQueue.push( this.id );
+ });
+ });
+ }
+
+ if ( 'showLikeWidget' == event.event ) {
+ setTimeout( JetpackLikesWidgetQueueHandler, 10 );
+ jQuery( '#' + event.id + ' .post-likes-widget-placeholder' ).fadeOut( 'fast', function() {
+ jQuery( '#' + event.id + ' .post-likes-widget' ).fadeIn( 'fast' );
+ JetpackLikespostMessage( { event: 'likeWidgetDisplayed', blog_id: event.blog_id, post_id: event.post_id }, window.frames['likes-master'] );
+ });
+ }
+
+ if ( 'showOtherGravatars' == event.event ) {
+ var $container = jQuery( '#likes-other-gravatars' );
+ var $list = $container.find( 'ul' );
+
+ $container.hide();
+ $list.html( '' );
+
+ $container.find( '.likes-text span' ).text( event.total );
+
+ jQuery.each( event.likers, function( i, liker ) {
+ $list.append( '<li class="' + liker.css_class + '"><a href="' + liker.profile_URL + '" class="wpl-liker" rel="nofollow" target="_parent"><img src="' + liker.avatar_URL + '" alt="' + liker.name + '" width="30" height="30" style="padding-right: 3px;" /></a></li>');
+ } );
+
+ var offset = jQuery( "[name='" + event.parent + "']" ).offset();
+
+ $container.css( 'left', offset.left + event.position.left - 10 + 'px' );
+ $container.css( 'top', offset.top + event.position.top - 33 + 'px' );
+
+ var rowLength = Math.floor( event.width / 37 );
+ var height = ( Math.ceil( event.likers.length / rowLength ) * 37 ) + 13;
+ if ( height > 204 ) {
+ height = 204;
+ }
+
+ $container.css( 'height', height + 'px' );
+ $container.css( 'width', rowLength * 37 - 7 + 'px' );
+
+ $list.css( 'width', rowLength * 37 + 'px' );
+
+ $container.fadeIn( 'slow' );
+
+ var scrollbarWidth = $list[0].offsetWidth - $list[0].clientWidth;
+ if ( scrollbarWidth > 0 ) {
+ $container.width( $container.width() + scrollbarWidth );
+ $list.width( $list.width() + scrollbarWidth );
+ }
+ }
+ }
+
+ pm.bind( 'likesMessage', function(e) { JetpackLikesMessageListener(e); } );
+
+ jQuery( document ).click( function( e ) {
+ var $container = jQuery( '#likes-other-gravatars' );
+
+ if ( $container.has( e.target ).length === 0 ) {
+ $container.fadeOut( 'slow' );
+ }
+ });
+
+ function JetpackLikesWidgetQueueHandler() {
+ var wrapperID;
+ if ( ! jetpackLikesMasterReady ) {
+ setTimeout( JetpackLikesWidgetQueueHandler, 500 );
+ return;
+ }
+
+ if ( jetpackLikesWidgetQueue.length > 0 ) {
+ // We may have a widget that needs creating now
+ var found = false;
+ while( jetpackLikesWidgetQueue.length > 0 ) {
+ // Grab the first member of the queue that isn't already loading.
+ wrapperID = jetpackLikesWidgetQueue.splice( 0, 1 )[0];
+ if ( jQuery( '#' + wrapperID ).hasClass( 'jetpack-likes-widget-unloaded' ) ) {
+ found = true;
+ break;
+ }
+ }
+ if ( ! found ) {
+ setTimeout( JetpackLikesWidgetQueueHandler, 500 );
+ return;
+ }
+ } else if ( jQuery( 'div.jetpack-likes-widget-unloaded' ).length > 0 ) {
+ // Get the next unloaded widget
+ wrapperID = jQuery( 'div.jetpack-likes-widget-unloaded' ).first()[0].id;
+ if ( ! wrapperID ) {
+ // Everything is currently loaded
+ setTimeout( JetpackLikesWidgetQueueHandler, 500 );
+ return;
+ }
+ }
+
+ var $wrapper = jQuery( '#' + wrapperID );
+ $wrapper.find( 'iframe' ).remove();
+
+ $wrapper.find( '.post-likes-widget-placeholder' ).after( "<iframe class='post-likes-widget jetpack-likes-widget' name='" + $wrapper.data( 'name' ) + "' height='55px' width='100%' frameBorder='0' src='" + $wrapper.data( 'src' ) + "'></iframe>" );
+
+
+ $wrapper.removeClass( 'jetpack-likes-widget-unloaded' ).addClass( 'jetpack-likes-widget-loading' );
+
+ $wrapper.find( 'iframe' ).load( function( e ) {
+ var $iframe = jQuery( e.target );
+ $wrapper.removeClass( 'jetpack-likes-widget-loading' ).addClass( 'jetpack-likes-widget-loaded' );
+
+ JetpackLikespostMessage( { event: 'loadLikeWidget', name: $iframe.attr( 'name' ), width: $iframe.width() }, window.frames[ 'likes-master' ] );
+ });
+ }
+ setInterval( JetpackLikesWidgetQueueHandler, 250 );
+ //]]>
+ </script>
+<?php
+ }
+
+ /**
+ * Get the 'disabled_likes' option from the DB of the current blog.
+ *
+ * @return array
+ */
+ function get_options() {
+ $setting = array();
+ $setting['disabled'] = get_option( 'disabled_likes' );
+ $sharing = get_option( 'sharing-options' );
+
+ // Default visibility settings
+ if ( ! isset( $sharing['global']['show'] ) ) {
+ $sharing['global']['show'] = array( 'post', 'page' );
+
+ // Scalar check
+ } elseif ( is_scalar( $sharing['global']['show'] ) ) {
+ switch ( $sharing['global']['show'] ) {
+ case 'posts' :
+ $sharing['global']['show'] = array( 'post', 'page' );
+ break;
+ case 'index' :
+ $sharing['global']['show'] = array( 'index' );
+ break;
+ case 'posts-index' :
+ $sharing['global']['show'] = array( 'post', 'page', 'index' );
+ break;
+ }
+ }
+
+ // Ensure it's always an array (even if not previously empty or scalar)
+ $setting['show'] = !empty( $sharing['global']['show'] ) ? (array) $sharing['global']['show'] : array();
+
+ return apply_filters( 'wpl_get_options', $setting );
+ }
+
+ /** _is_ functions ************************************************************/
+
+ /**
+ * Are likes visible in this context?
+ *
+ * Some of this code was taken and modified from sharing_display() to ensure
+ * similar logic and filters apply here, too.
+ */
+ function is_likes_visible() {
+
+ global $wp_current_filter; // Used to check 'get_the_excerpt' filter
+ global $post; // Used to apply 'sharing_show' filter
+
+ // Never show on feeds or previews
+ if ( is_feed() || is_preview() || is_comments_popup() ) {
+ $enabled = false;
+
+ // Not a feed or preview, so what is it?
+ } else {
+
+ if ( in_the_loop() ) {
+ // If in the loop, check if the current post is likeable
+ $enabled = $this->is_post_likeable();
+ } else {
+ // Otherwise, check and see if likes are enabled sitewide
+ $enabled = $this->is_enabled_sitewide();
+ }
+
+ /** Other Checks ******************************************************/
+
+ // Do not show on excerpts
+ if ( in_array( 'get_the_excerpt', (array) $wp_current_filter ) ) {
+ $enabled = false;
+
+ // Sharing Setting Overrides ****************************************
+ } else {
+ // Single post
+ if ( is_singular( 'post' ) ) {
+ if ( ! $this->is_single_post_enabled() ) {
+ $enabled = false;
+ }
+
+ // Single page
+ } elseif ( is_page() ) {
+ if ( ! $this->is_single_page_enabled() ) {
+ $enabled = false;
+ }
+
+ // Attachment
+ } elseif ( is_attachment() ) {
+ if ( ! $this->is_attachment_enabled() ) {
+ $enabled = false;
+ }
+
+ // All other loops
+ } elseif ( ! $this->is_index_enabled() ) {
+ $enabled = false;
+ }
+ }
+ }
+
+ // Run through the sharing filters
+ $enabled = apply_filters( 'sharing_show', $enabled, $post );
+
+ return (bool) apply_filters( 'wpl_is_likes_visible', $enabled );
+ }
+
+ /**
+ * Returns the current state of the "WordPress.com Likes are" option.
+ * @return boolean true if enabled sitewide, false if not
+ */
+ function is_enabled_sitewide() {
+ return (bool) apply_filters( 'wpl_is_enabled_sitewide', ! get_option( 'disabled_likes' ) );
+ }
+
+ /**
+ * Returns if comment likes are enabled. Defaults to 'on'
+ * @todo decide what the default should be
+ * @return boolean true if we should show comment likes, false if not
+ */
+ function is_comments_enabled() {
+ return (bool) apply_filters( 'jetpack_comment_likes_enabled', get_option( 'jetpack_comment_likes_enabled', true ) );
+ }
+
+ function is_admin_bar_button_visible() {
+ global $wp_admin_bar;
+
+ if ( ! is_object( $wp_admin_bar ) )
+ return false;
+
+ if ( ( ! is_singular( 'post' ) && ! is_attachment() && ! is_page() ) )
+ return false;
+
+ if ( ! $this->is_likes_visible() )
+ return false;
+
+ if ( ! $this->is_post_likeable() )
+ return false;
+
+ return (bool) apply_filters( 'jetpack_admin_bar_likes_enabled', true );
+ }
+
+ /**
+ * Are likes enabled for this post?
+ *
+ * @param int $post_id
+ * @retun bool
+ */
+ function is_post_likeable( $post_id = 0 ) {
+ $post = get_post( $post_id );
+ if ( !$post || is_wp_error( $post ) ) {
+ return false;
+ }
+
+ $sitewide_likes_enabled = (bool) Jetpack_Likes::is_enabled_sitewide();
+ $post_likes_switched = (bool) get_post_meta( $post->ID, 'switch_like_status', true );
+
+ $post_likes_enabled = $sitewide_likes_enabled;
+ if ( $post_likes_switched ) {
+ $post_likes_enabled = ! $post_likes_enabled;
+ }
+
+ return $post_likes_enabled;
+ }
+
+ /**
+ * Are Post Likes enabled on archive/front/search pages?
+ *
+ * @return bool
+ */
+ function is_index_enabled() {
+ $options = $this->get_options();
+ return (bool) apply_filters( 'wpl_is_index_disabled', (bool) in_array( 'index', $options['show'] ) );
+ }
+
+ /**
+ * Are Post Likes enabled on single posts?
+ *
+ * @return bool
+ */
+ function is_single_post_enabled() {
+ $options = $this->get_options();
+ return (bool) apply_filters( 'wpl_is_single_post_disabled', (bool) in_array( 'post', $options['show'] ) );
+ }
+
+ /**
+ * Are Post Likes enabled on single pages?
+ *
+ * @return bool
+ */
+ function is_single_page_enabled() {
+ $options = $this->get_options();
+ return (bool) apply_filters( 'wpl_is_single_page_disabled', (bool) in_array( 'page', $options['show'] ) );
+ }
+
+ /**
+ * Are Media Likes enabled on single pages?
+ *
+ * @return bool
+ */
+ function is_attachment_enabled() {
+ $options = $this->get_options();
+ return (bool) apply_filters( 'wpl_is_attachment_disabled', (bool) in_array( 'attachment', $options['show'] ) );
+ }
+
+}
+
+Jetpack_Likes::init();
diff --git a/plugins/jetpack/modules/likes/style.css b/plugins/jetpack/modules/likes/style.css
new file mode 100644
index 00000000..3885cace
--- /dev/null
+++ b/plugins/jetpack/modules/likes/style.css
@@ -0,0 +1,189 @@
+#wpadminbar li#wp-admin-bar-admin-bar-likes-widget {
+ width: 61px;
+}
+
+#wpadminbar iframe.admin-bar-likes-widget {
+ width: 61px;
+ height: 28px;
+ min-height: 28px;
+ border-width: 0px;
+ position: absolute;
+ top: 0;
+}
+
+div.jetpack-likes-widget-wrapper {
+ width: 100%;
+}
+
+#likes-other-gravatars {
+ display: none;
+ position: absolute;
+ padding: 10px;
+ background-color: #000;
+ border-width: 0;
+ opacity: 0.88;
+ filter: alpha(opacity=88);
+ box-shadow: 0 0 10px black;
+ min-width: 130px;
+ z-index: 1000;
+}
+
+#likes-other-gravatars .likes-text {
+ color: white;
+ font-size: 14px;
+ padding-bottom: 5px;
+}
+
+#likes-other-gravatars ul,
+#likes-other-gravatars li {
+ margin: 0;
+ padding: 0;
+ text-indent: 0;
+ list-style-type: none;
+}
+
+#likes-other-gravatars li::before {
+ content: "";
+}
+
+#likes-other-gravatars ul.wpl-avatars {
+ overflow: auto;
+ display: block;
+ position: absolute;
+ max-height: 190px;
+}
+
+#likes-other-gravatars ul.wpl-avatars li {
+ width: 32px;
+ height: 32px;
+ float: left;
+ margin: 0 5px 5px 0;
+}
+
+#likes-other-gravatars ul.wpl-avatars li a {
+ margin: 0 2px 0 0;
+ border-bottom: none !important;
+ display: block;
+}
+
+#likes-other-gravatars ul.wpl-avatars li a img {
+ background: none;
+ border: none;
+ margin: 0 !important;
+ padding: 0 !important;
+ position: static;
+}
+
+
+div.sd-box {
+ border-top: 1px solid #ddd;
+ border-top: 1px solid rgba(0,0,0,.13);
+}
+
+h3.sd-title {
+ font-size: 12px;
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ margin: 3px 0;
+ padding: 0;
+ text-transform: none;
+ letter-spacing: 0;
+ line-height: 1;
+ font-weight: bold;
+ width: 15.625%; /* 100px / 640px */ float: left;
+ position: static;
+ background: none;
+ border: none;
+}
+
+.rtl .sd-title {
+ float: right;
+ text-align: right;
+}
+
+.entry-content .post-likes-widget, .post-likes-widget,
+.comment-likes-widget {
+ margin: 0;
+ border-width: 0;
+}
+
+.post-likes-widget-placeholder {
+ margin: 0;
+ border-width: 0;
+}
+
+.post-likes-widget-placeholder .button {
+ margin: 0;
+ padding: 0;
+ display: inline-block;
+ background: #efefef;
+ background: -moz-linear-gradient(top, #f7f7f7 0%, #efefef 100%);
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f7f7f7), color-stop(100%,#efefef));
+ background: -webkit-linear-gradient(top, #f7f7f7 0%,#efefef 100%);
+ background: -o-linear-gradient(top, #f7f7f7 0%,#efefef 100%);
+ background: -ms-linear-gradient(top, #f7f7f7 0%,#efefef 100%);
+ background: linear-gradient(top, #f7f7f7 0%,#efefef 100%);
+ border-radius: 3px;
+ border: 1px solid #ddd !important;
+ box-shadow: inset 0 1px 0 #fff;
+ color: #999;
+ text-decoration: none;
+ line-height: 1;
+ font-size: 12px;
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-weight: normal;
+}
+
+.post-likes-widget-placeholder .button span {
+ padding: 1px 5px 1px 2px;
+ display: block;
+ opacity: .8;
+ line-height: 1.5em;
+ text-shadow: none;
+}
+
+.post-likes-widget-placeholder .button span:before {
+ color: #97A8CC;
+ font-family: "Noticons";
+ content: '\2605';
+ font-size: 16px;
+ line-height: 0;
+ text-shadow: 0 1px 0 #fff;
+ position: relative;
+ top: 3px;
+}
+
+.post-likes-widget-placeholder .loading {
+ color: #999;
+ font-size: 12px;
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+}
+
+.post-likes-widget {
+ width: 82.125%;
+ display: none;
+ float: right;
+}
+
+/* Like Special cases (display on it's own) */
+
+div.sharedaddy.sd-like-enabled .sd-like h3 {
+ display: none;
+}
+
+div.sharedaddy.sd-like-enabled .sd-like .post-likes-widget {
+ width: 100%;
+ float: none;
+}
+
+div.sharedaddy.sd-rating-enabled .sd-like .post-likes-widget, div.sharedaddy.sd-sharing-enabled .sd-like .post-likes-widget {
+ width: 82.125%;
+ float: right;
+}
+
+div.sharedaddy.sd-rating-enabled .sd-like h3, div.sharedaddy.sd-sharing-enabled .sd-like h3 {
+ display: block;
+}
+
+.comment-likes-widget {
+ width: 100%;
+}
diff --git a/plugins/jetpack/modules/minileven.php b/plugins/jetpack/modules/minileven.php
new file mode 100644
index 00000000..e2047e50
--- /dev/null
+++ b/plugins/jetpack/modules/minileven.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * Module Name: Mobile Theme
+ * Module Description: Automatically optimize your site for mobile devices.
+ * Sort Order: 11
+ * First Introduced: 1.8
+ */
+
+function jetpack_load_minileven() {
+ include dirname( __FILE__ ) . "/minileven/minileven.php";
+
+ if ( get_option( 'wp_mobile_app_promos' ) != '1' )
+ remove_action( 'wp_mobile_theme_footer', 'jetpack_mobile_app_promo' );
+}
+
+add_action( 'jetpack_modules_loaded', 'minileven_loaded' );
+
+function minileven_loaded() {
+ Jetpack::enable_module_configurable( __FILE__ );
+ Jetpack::module_configuration_load( __FILE__, 'minileven_configuration_load' );
+ Jetpack::module_configuration_screen( __FILE__, 'minileven_configuration_screen' );
+}
+
+function minileven_configuration_load() {
+ if ( isset( $_POST['action'] ) && $_POST['action'] == 'save_options' && $_POST['_wpnonce'] == wp_create_nonce( 'minileven' ) ) {
+ if ( isset( $_POST['wp_mobile_excerpt'] ) )
+ update_option( 'wp_mobile_excerpt', '1' == $_POST['wp_mobile_excerpt'] ? '1' : '0' );
+
+ update_option( 'wp_mobile_app_promos', ( isset( $_POST['wp_mobile_app_promos'] ) ) ? '1' : '0' );
+
+ Jetpack::state( 'message', 'module_configured' );
+ wp_safe_redirect( Jetpack::module_configuration_url( 'minileven' ) );
+ exit;
+ }
+}
+
+function minileven_configuration_screen() {
+ $excerpts = ( 0 == get_option( 'wp_mobile_excerpt' ) ) ? 0 : 1;
+ $promos = ( '1' == get_option( 'wp_mobile_app_promos' ) ) ? 1 : 0;
+
+ ?>
+ <form method="post">
+ <input type="hidden" name="action" value="save_options" />
+ <?php wp_nonce_field( 'minileven' ); ?>
+ <table id="menu" class="form-table">
+ <tr valign="top">
+ <th scope="row"><?php _e( 'Excerpts', 'jetpack' ); ?></th>
+ <td>
+ <label>
+ <input name="wp_mobile_excerpt" type="radio" value="1" class="code" <?php checked( 1, $excerpts, true ); ?> />
+ <?php _e( 'Enable excerpts on front page and on archive pages', 'jetpack' ); ?>
+ </label>
+ <br />
+ <label>
+ <input name="wp_mobile_excerpt" type="radio" value="0" class="code" <?php checked( 0, $excerpts, true ); ?> />
+ <?php _e( 'Show full posts on front page and on archive pages', 'jetpack' ); ?>
+ </label>
+ </td>
+ </tr>
+ <tr valign="top">
+ <th scope="row"><?php _e( 'Mobile App Promos', 'jetpack' ); ?></th>
+ <td>
+ <label>
+ <input name="wp_mobile_app_promos" type="checkbox" value="1" <?php checked( 1, $promos, true ); ?> />
+ <?php _e ( 'Show a promo for the WordPress mobile apps in the footer of the mobile theme.', 'jetpack' ); ?>
+ </label>
+ </td>
+ </tr>
+ </table>
+ <p class="submit">
+ <input type="submit" class="button-primary" value="<?php esc_attr_e( __( 'Save configuration', 'jetpack' ) ); ?>" />
+ </p>
+ </form>
+ <h3><?php _e( 'Mobile Apps', 'jetpack' ); ?></h3>
+ <p><?php _e( 'Take WordPress with you.', 'jetpack' ); ?></p>
+ <a href="http://wordpress.org/extend/mobile/"><img src="<?php echo plugin_dir_url( __FILE__ ); ?>/minileven/images/wp-app-devices.png" width="332" height="73" /></a>
+ <p><?php printf( __( 'We have apps for <a href="%s">iOS (iPhone, iPad, iPod Touch)</a>, <a href="%s">Android</a>, <a href="%s">BlackBerry</a>, <a href="%s">Windows Phone</a>, and <a href="%s">more</a>!', 'jetpack' ), 'http://ios.wordpress.org/', 'http://android.wordpress.org/', 'http://blackberry.wordpress.org/', 'http://windowsphone.wordpress.org/', 'http://wordpress.org/extend/mobile/' ); ?></p>
+ <?php
+}
+
+function minileven_theme_root( $theme_root ) {
+ if ( jetpack_check_mobile() ) {
+ return dirname( __FILE__ ) . '/minileven/theme';
+ }
+
+ return $theme_root;
+}
+
+add_filter( 'theme_root', 'minileven_theme_root' );
+
+function minileven_theme_root_uri( $theme_root_uri ) {
+ if ( jetpack_check_mobile() ) {
+ return plugins_url( 'modules/minileven/theme', dirname( __FILE__ ) );
+ }
+
+ return $theme_root_uri;
+}
+
+add_filter( 'theme_root_uri', 'minileven_theme_root_uri' );
+
+function minileven_enabled( $wp_mobile_disable_option ) {
+ return true;
+}
+
+add_filter( 'option_wp_mobile_disable', 'minileven_enabled' );
+
+jetpack_load_minileven(); \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/images/wp-app-devices.png b/plugins/jetpack/modules/minileven/images/wp-app-devices.png
new file mode 100644
index 00000000..4b5f4be9
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/images/wp-app-devices.png
Binary files differ
diff --git a/plugins/jetpack/modules/minileven/minileven.php b/plugins/jetpack/modules/minileven/minileven.php
new file mode 100644
index 00000000..ae2ab016
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/minileven.php
@@ -0,0 +1,313 @@
+<?php
+
+// ********** modify blog option 'wp_mobile_template' manually to specify a theme (ex. 'vip/cnnmobile')
+
+// WordPress Mobile Edition
+//
+// Copyright (c) 2002-2008 Alex King
+// http://alexking.org/projects/wordpress
+//
+// Released under the GPL license
+// http://www.opensource.org/licenses/gpl-license.php
+//
+// **********************************************************************
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// *****************************************************************
+
+/*
+Plugin Name: WordPress Mobile Edition
+Plugin URI: http://alexking.org/projects/wordpress
+Description: Show a mobile view of the post/page if the visitor is on a known mobile device. Questions on configuration, etc.? Make sure to read the README.
+Author: Alex King
+Author URI: http://alexking.org
+Version: 2.1a-WPCOM
+*/
+
+$_SERVER['REQUEST_URI'] = ( isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['SCRIPT_NAME'] . (( isset($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : '')));
+
+function jetpack_check_mobile() {
+ if ( ( defined('XMLRPC_REQUEST') && XMLRPC_REQUEST ) || ( defined('APP_REQUEST') && APP_REQUEST ) )
+ return false;
+ if ( !isset($_SERVER["HTTP_USER_AGENT"]) || (isset($_COOKIE['akm_mobile']) && $_COOKIE['akm_mobile'] == 'false') )
+ return false;
+ if ( jetpack_mobile_exclude() )
+ return false;
+ if ( 1 == get_option('wp_mobile_disable') )
+ return false;
+ if ( isset($_COOKIE['akm_mobile']) && $_COOKIE['akm_mobile'] == 'true' )
+ return true;
+
+ $is_mobile = jetpack_is_mobile();
+
+ return apply_filters( 'jetpack_check_mobile', $is_mobile );
+}
+
+function jetpack_mobile_exclude() {
+ $exclude = false;
+ $pages_to_exclude = array(
+ 'wp-admin',
+ 'wp-comments-post.php',
+ 'wp-mail.php',
+ 'wp-login.php',
+ 'wp-activate.php',
+ );
+ foreach ( $pages_to_exclude as $exclude_page ) {
+ if ( strstr( strtolower( $_SERVER['REQUEST_URI'] ), $exclude_page ) )
+ $exclude = true;
+ }
+
+ if ( defined( 'DOING_AJAX' ) && true === DOING_AJAX )
+ $exclude = false;
+
+ if ( isset( $GLOBALS['wp_customize'] ) )
+ return true;
+
+ return $exclude;
+}
+
+function wp_mobile_get_main_template() {
+ remove_action( 'option_template', 'jetpack_mobile_template' );
+ $template = get_option( 'template' );
+ add_action( 'option_template', 'jetpack_mobile_template' );
+ return $template;
+}
+
+function wp_mobile_get_main_stylesheet() {
+ remove_action( 'option_stylesheet', 'jetpack_mobile_stylesheet' );
+ $stylesheet = get_option( 'stylesheet' );
+ add_action( 'option_stylesheet', 'jetpack_mobile_stylesheet' );
+ return $stylesheet;
+}
+
+function jetpack_mobile_stylesheet( $theme ) {
+ return apply_filters( 'jetpack_mobile_stylesheet', 'pub/minileven', $theme );
+}
+
+function jetpack_mobile_template( $theme ) {
+ return apply_filters( 'jetpack_mobile_template', 'pub/minileven', $theme );
+}
+
+function jetpack_mobile_available() {
+ echo '<div style="text-align:center;margin:10px 0;"><a href="'. home_url( '?ak_action=accept_mobile' ) . '">' . __( 'View Mobile Site', 'jetpack' ) . '</a></div>';
+}
+
+function jetpack_mobile_request_handler() {
+ global $wpdb;
+ if (isset($_GET['ak_action'])) {
+ $url = parse_url( get_bloginfo( 'url' ) );
+ $domain = $url['host'];
+ if (!empty($url['path'])) {
+ $path = $url['path'];
+ }
+ else {
+ $path = '/';
+ }
+ $redirect = false;
+ switch ($_GET['ak_action']) {
+ case 'reject_mobile':
+ setcookie(
+ 'akm_mobile'
+ , 'false'
+ , time() + 300000
+ , $path
+ , $domain
+ );
+ $redirect = true;
+
+ do_action( 'mobile_reject_mobile' );
+ break;
+ case 'force_mobile':
+ case 'accept_mobile':
+ setcookie(
+ 'akm_mobile'
+ , 'true'
+ , time() + 300000
+ , $path
+ , $domain
+ );
+ $redirect = true;
+
+ do_action( 'mobile_force_mobile' );
+ break;
+ }
+ if ($redirect) {
+ if ( isset( $_GET['redirect_to'] ) && $_GET['redirect_to'] ) {
+ $go = urldecode( $_GET['redirect_to'] );
+ } else if (!empty($_SERVER['HTTP_REFERER'])) {
+ $go = $_SERVER['HTTP_REFERER'];
+ }
+ else {
+ $go = remove_query_arg( array( 'ak_action' ) );
+ }
+ wp_safe_redirect( $go );
+ exit;
+ }
+ }
+}
+add_action('init', 'jetpack_mobile_request_handler');
+
+function jetpack_mobile_theme_setup() {
+ if ( jetpack_check_mobile() ) {
+ // Redirect to download page if user clicked mobile app promo link in mobile footer
+ if ( isset( $_GET['app-download'] ) ) {
+ do_action( 'mobile_app_promo_download', $_GET['app-download'] );
+
+ switch ( $_GET['app-download'] ) {
+ case 'android':
+ header( 'Location: market://search?q=pname:org.wordpress.android' );
+ exit;
+ break;
+ case 'ios':
+ header( 'Location: http://itunes.apple.com/us/app/wordpress/id335703880?mt=8' );
+ exit;
+ break;
+ case 'blackberry':
+ header( 'Location: http://blackberry.wordpress.org/download/' );
+ exit;
+ break;
+ case 'nokia':
+ header( 'Location: http://nokia.wordpress.org/download/' );
+ exit;
+ break;
+ case 'windowsphone':
+ header( 'Location: http://social.zune.net/redirect?type=phoneApp&id=5f64ad85-f801-e011-9264-00237de2db9e' );
+ exit;
+ break;
+ }
+ }
+
+ add_action('stylesheet', 'jetpack_mobile_stylesheet');
+ add_action('template', 'jetpack_mobile_template');
+ add_action('option_template', 'jetpack_mobile_template');
+ add_action('option_stylesheet', 'jetpack_mobile_stylesheet');
+
+ if ( class_exists( 'Jetpack_Custom_CSS' ) && method_exists( 'Jetpack_Custom_CSS', 'disable' ) && ! get_option( 'wp_mobile_custom_css' ) )
+ add_action( 'init', array( 'Jetpack_Custom_CSS', 'disable' ), 11 );
+
+ do_action( 'mobile_setup' );
+ }
+}
+
+// Need a hook after plugins_loaded (since this code won't be loaded in Jetpack
+// until then) but after init (because it has its own init hooks to add).
+add_action( 'setup_theme', 'jetpack_mobile_theme_setup' );
+
+if (isset($_COOKIE['akm_mobile']) && $_COOKIE['akm_mobile'] == 'false') {
+ add_action('wp_footer', 'jetpack_mobile_available');
+}
+
+add_action( 'wp_footer', 'mobile_admin_bar', 20 );
+function mobile_admin_bar() {
+ global $wp_version;
+
+ if ( jetpack_is_mobile() && 1 != version_compare( $wp_version, '3.5-beta3-22631' ) ) :
+ // This fix was made unnecessary in http://core.trac.wordpress.org/changeset/22636
+ ?>
+ <script type="text/javascript" id='mobile-admin-bar'>
+ jQuery( function( $ ) {
+ var menupop = $( '#wpadminbar .ab-top-menu > li.menupop' )
+ .unbind( 'mouseover' )
+ .unbind( 'mouseout' )
+ .click( function ( e ) {
+ $( this ).toggleClass( 'hover' );
+ $( '#wpadminbar .menupop' ).not( this ).removeClass( 'hover' );
+ } )
+ .children( 'a' )
+ .click( function( e ) {
+ e.preventDefault();
+ } );
+ $( '#wpadminbar' ).css( 'position', 'absolute' );
+ $( '#ab-reblog-box' ).css( 'position', 'absolute' );
+ } );
+ </script>
+ <?php
+ endif;
+}
+
+function jetpack_mobile_app_promo() {
+ ?>
+ <script type="text/javascript">
+ if ( ! navigator.userAgent.match( /wp-(iphone|android|blackberry|nokia|windowsphone)/i ) ) {
+ if ( ( navigator.userAgent.match( /iphone/i ) ) || ( navigator.userAgent.match( /ipod/i ) ) )
+ document.write( '<span id="wpcom-mobile-app-promo" style="margin-top: 10px; font-size: 13px;"><strong>Now Available!</strong> <a href="/index.php?app-download=ios">Download WordPress for iOS</a></span><br /><br />' );
+ else if ( ( navigator.userAgent.match( /android/i ) ) && ( null == navigator.userAgent.match( /playbook/i ) && null == navigator.userAgent.match( /bb10/i ) ) )
+ document.write( '<span id="wpcom-mobile-app-promo" style="margin-top: 10px; font-size: 13px;"><strong>Now Available!</strong> <a href="/index.php?app-download=android">Download WordPress for Android</a></span><br /><br />' );
+ else if ( ( navigator.userAgent.match( /blackberry/i ) ) || ( navigator.userAgent.match( /playbook/i ) ) || ( navigator.userAgent.match( /bb10/i ) ) )
+ document.write( '<span id="wpcom-mobile-app-promo" style="margin-top: 10px; font-size: 13px;"><strong>Now Available!</strong> <a href="/index.php?app-download=blackberry">Download WordPress for BlackBerry</a></span><br /><br />' );
+ else if ( ( navigator.userAgent.match( /windows phone os/i ) ) )
+ document.write( '<span id="wpcom-mobile-app-promo" style="margin-top: 10px; font-size: 13px; line-height: 13px;"><strong>Now Available!</strong> <a href="/index.php?app-download=windowsphone">Download WordPress for <br />Windows Phone</a></span><br /><br />' );
+ else if ( ( navigator.userAgent.match( /nokia/i ) ) )
+ document.write( '<span id="wpcom-mobile-app-promo" style="margin-top: 10px; font-size: 13px;"><strong>Now Available!</strong> <a href="/index.php?app-download=nokia">Download WordPress for Nokia</a></span><br /><br />' );
+ }
+ </script>
+ <?php
+}
+
+add_action( 'wp_mobile_theme_footer', 'jetpack_mobile_app_promo' );
+
+/**
+ * Adds an option to allow your Custom CSS to also be applied to the Mobile Theme.
+ * It's disabled by default, but this should allow people who know what they're
+ * doing to customize the mobile theme.
+ */
+function jetpack_mobile_css_settings() {
+ $mobile_css = get_option( 'wp_mobile_custom_css' );
+
+ ?>
+ <div class="misc-pub-section">
+ <label><?php esc_html_e( 'Mobile-compatible:', 'jetpack' ); ?></label>
+ <span id="mobile-css-display"><?php echo $mobile_css ? __( 'Yes', 'jetpack' ) : __( 'No', 'jetpack' ); ?></span>
+ <a class="edit-mobile-css hide-if-no-js" href="#mobile-css"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
+ <div id="mobile-css-select" class="hide-if-js">
+ <input type="hidden" name="mobile_css" id="mobile-css" value="<?php echo intval( $mobile_css ); ?>" />
+ <label>
+ <input type="checkbox" id="mobile-css-visible" <?php checked( get_option( 'wp_mobile_custom_css' ) ); ?> />
+ <?php esc_html_e( 'Include this CSS in the Mobile Theme', 'jetpack' ); ?>
+ </label>
+ <p>
+ <a class="save-mobile-css hide-if-no-js button" href="#mobile-css"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
+ <a class="cancel-mobile-css hide-if-no-js" href="#mobile-css"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
+ </p>
+ </div>
+ </div>
+ <script type="text/javascript">
+ jQuery( function ( $ ) {
+ $( '.edit-mobile-css' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#mobile-css-select' ).slideDown();
+ $( this ).hide();
+ } );
+
+ $( '.cancel-mobile-css' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#mobile-css-select' ).slideUp( function () {
+ $( '.edit-mobile-css' ).show();
+
+ $( '#mobile-css-visible' ).prop( 'checked', $( '#mobile-css' ).val() == '1' );
+ } );
+ } );
+
+ $( '.save-mobile-css' ).bind( 'click', function ( e ) {
+ e.preventDefault();
+
+ $( '#mobile-css-select' ).slideUp();
+ $( '#mobile-css-display' ).text( $( '#mobile-css-visible' ).prop( 'checked' ) ? 'Yes' : 'No' );
+ $( '#mobile-css' ).val( $( '#mobile-css-visible' ).prop( 'checked' ) ? '1' : '0' );
+ $( '.edit-mobile-css' ).show();
+ } );
+ } );
+ </script>
+ <?php
+}
+
+add_action( 'custom_css_submitbox_misc_actions', 'jetpack_mobile_css_settings' );
+
+function jetpack_mobile_save_css_settings() {
+ update_option( 'wp_mobile_custom_css', isset( $_POST['mobile_css'] ) && ! empty( $_POST['mobile_css'] ) );
+}
+
+add_action( 'safecss_save_pre', 'jetpack_mobile_save_css_settings' );
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/comments.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/comments.php
new file mode 100644
index 00000000..55c35161
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/comments.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * The template for displaying Comments.
+ *
+ * The area of the page that contains both current comments
+ * and the comment form. The actual display of comments is
+ * handled by a callback to minileven_comment() which is
+ * located in the functions.php file.
+ *
+ * @package Minileven
+ */
+?>
+ <div id="comments">
+ <?php if ( post_password_required() ) : ?>
+ <p class="nopassword"><?php _e( 'This post is password protected. Enter the password to view any comments.', 'jetpack' ); ?></p>
+ </div><!-- #comments -->
+ <?php
+ /* Stop the rest of comments.php from being processed,
+ * but don't kill the script entirely -- we still have
+ * to fully load the template.
+ */
+ return;
+ endif;
+ ?>
+
+ <?php // You can start editing here -- including this comment! ?>
+
+ <?php comment_form(); ?>
+
+ <?php if ( have_comments() ) : ?>
+ <ol class="commentlist">
+ <?php
+ /* Loop through and list the comments. Tell wp_list_comments()
+ * to use minileven_comment() to format the comments.
+ * If you want to overload this in a child theme then you can
+ * define minileven_comment() and that will be used instead.
+ * See minileven_comment() in minileven/functions.php for more.
+ */
+ wp_list_comments( array( 'callback' => 'minileven_comment' ) );
+ ?>
+ </ol>
+
+ <?php if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) : // are there comments to navigate through ?>
+ <nav id="comment-nav-below">
+ <h1 class="assistive-text"><?php _e( 'Comment navigation', 'jetpack' ); ?></h1>
+ <div class="nav-previous"><?php previous_comments_link( __( '&larr; Older Comments', 'jetpack' ) ); ?></div>
+ <div class="nav-next"><?php next_comments_link( __( 'Newer Comments &rarr;', 'jetpack' ) ); ?></div>
+ </nav>
+ <?php endif; // check for comment navigation
+ endif; // check for the existence of comments
+ ?>
+ </div><!-- #comments --> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/content-gallery.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/content-gallery.php
new file mode 100644
index 00000000..cf69f252
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/content-gallery.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * The template for displaying posts in the Gallery Post Format on index and archive pages
+ *
+ * Learn more: http://codex.wordpress.org/Post_Formats
+ *
+ * @package Minileven
+ */
+?>
+
+<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
+ <header class="entry-header">
+ <hgroup>
+ <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>
+ <h3 class="entry-format"><?php _e( 'Gallery', 'jetpack' ); ?></h3>
+ </hgroup>
+ </header><!-- .entry-header -->
+
+ <div class="entry-content">
+ <?php if ( is_single() ) : ?>
+ <?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'jetpack' ) ); ?>
+
+ <?php else : ?>
+ <?php
+ $images = get_children( array( 'post_parent' => $post->ID, 'post_type' => 'attachment', 'post_mime_type' => 'image', 'orderby' => 'rand', 'order' => 'ASC', 'numberposts' => 999 ) );
+ if ( $images ) :
+ $total_images = count( $images );
+ $large_image = array_shift( $images );
+ $thumb1_image = array_shift( $images );
+ $thumb2_image = array_shift( $images );
+ $thumb3_image = array_shift( $images );
+
+ $image_img_tag = wp_get_attachment_image( $large_image->ID, 'large' );
+ $thumb1_img_tag = wp_get_attachment_image( $thumb1_image->ID, 'thumbnail' );
+ $thumb2_img_tag = wp_get_attachment_image( $thumb2_image->ID, 'thumbnail' );
+ $thumb3_img_tag = wp_get_attachment_image( $thumb3_image->ID, 'thumbnail' );
+ ?>
+ <div class="img-gallery">
+ <div class="gallery-large">
+ <a href="<?php the_permalink(); ?>"><?php echo $image_img_tag; ?></a>
+ </div><!-- .gallery-large -->
+ <?php if ( 3 == $total_images ) : ?>
+ <div class="gallery-thumbs-2">
+ <a href="<?php the_permalink(); ?>" class="gallery-thumb-1"><?php echo $thumb1_img_tag; ?></a>
+ <a href="<?php the_permalink(); ?>" class="gallery-thumb-2"><?php echo $thumb2_img_tag; ?></a>
+ </div><!-- .gallery-thumbs -->
+
+ <?php elseif ( 4 <= $total_images ) : ?>
+ <div class="gallery-thumbs-3">
+ <a href="<?php the_permalink(); ?>" class="gallery-thumb-1"><?php echo $thumb1_img_tag; ?></a>
+ <a href="<?php the_permalink(); ?>" class="gallery-thumb-2"><?php echo $thumb2_img_tag; ?></a>
+ <a href="<?php the_permalink(); ?>" class="gallery-thumb-3"><?php echo $thumb3_img_tag; ?></a>
+ </div><!-- .gallery-thumbs -->
+ </div><!-- .img-gallery -->
+ <?php endif; ?>
+
+ <p class="gallery-info"><em><?php printf( _n( 'This gallery contains <a %1$s>%2$s photo</a>.', 'This gallery contains <a %1$s>%2$s photos</a>.', $total_images, 'jetpack' ),
+ 'href="' . esc_url( get_permalink() ) . '" title="' . esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ) . '" rel="bookmark"',
+ number_format_i18n( $total_images ) );
+ ?></em></p>
+
+ <?php endif; ?>
+ <?php endif; ?>
+
+ <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'jetpack' ) . '</span>', 'after' => '</div>' ) ); ?>
+</div><!-- .entry-content -->
+
+ <footer class="entry-meta">
+ <?php minileven_posted_on(); ?>
+ <?php if ( comments_open() ) : ?>
+ <span class="comments-link"><?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a Reply', 'jetpack' ) . '</span>', __( '<b>1</b> Reply', 'minileven' , 'jetpack'), __( '<b>%</b> Replies', 'minileven' , 'jetpack') ); ?></span>
+ <?php endif; // End if comments_open() ?>
+
+ <?php edit_post_link( __( 'Edit', 'jetpack' ), '<span class="edit-link">', '</span>' ); ?>
+ </footer><!-- #entry-meta -->
+</article><!-- #post-<?php the_ID(); ?> -->
+
+<?php comments_template( '', true ); ?> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/content.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/content.php
new file mode 100644
index 00000000..9ab03516
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/content.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * The default template for displaying content
+ *
+ * @package Minileven
+ */
+?>
+
+ <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
+ <header class="entry-header">
+ <?php if ( is_sticky() ) : ?>
+ <hgroup>
+ <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>
+ <h3 class="entry-format"><?php _e( 'Featured', 'jetpack' ); ?></h3>
+ </hgroup>
+ <?php else : ?>
+ <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>
+ <?php endif; ?>
+
+ <div class="entry-meta">
+ <?php if ( is_singular() && is_multi_author() ) : ?>
+ <span class="author-link">
+ <?php _e( 'Posted by ', 'jetpack' ); ?>
+ <a href="<?php echo esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ); ?>" rel="author">
+ <?php printf( __( '%s', 'jetpack' ), get_the_author() ); ?>
+ </a>
+ </span><!-- .author-link -->
+ <?php endif; ?>
+ </div><!-- .entry-meta -->
+ </header><!-- .entry-header -->
+
+ <div class="entry-content">
+ <?php if ( '1' == get_option( 'wp_mobile_excerpt' ) && is_home() || is_search() || is_archive() ) : ?>
+ <?php the_excerpt(); ?>
+ <?php else : ?>
+ <?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'jetpack' ) ); ?>
+ <?php endif; ?>
+ <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'jetpack' ) . '</span>', 'after' => '</div>' ) ); ?>
+ </div><!-- .entry-content -->
+
+ <footer class="entry-meta">
+ <?php if ( 'post' == get_post_type() ) : ?>
+ <?php minileven_posted_on(); ?>
+ <?php endif; ?>
+ <?php if ( comments_open() ) : ?>
+ <span class="comments-link"><?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a reply', 'jetpack' ) . '</span>', __( '<b>1</b> Reply', 'minileven' , 'jetpack'), __( '<b>%</b> Replies', 'minileven' , 'jetpack') ); ?></span>
+ <?php endif; // End if comments_open() ?>
+ <?php edit_post_link( __( 'Edit', 'jetpack' ), '<span class="edit-link">', '</span>' ); ?>
+ </footer><!-- #entry-meta -->
+ </article><!-- #post-<?php the_ID(); ?> -->
+
+ <?php if ( is_single() ) : ?>
+ <nav id="nav-single">
+ <h3 class="assistive-text"><?php _e( 'Post navigation', 'jetpack' ); ?></h3>
+ <span class="nav-previous"><?php previous_post_link( '%link', __( '&laquo; Previous', 'jetpack' ) ); ?></span>
+ <span class="nav-next"><?php next_post_link( '%link', __( 'Next &raquo;', 'jetpack' ) ); ?></span>
+ </nav><!-- #nav-single -->
+ <?php endif; ?>
+
+ <?php comments_template( '', true ); ?> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/footer.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/footer.php
new file mode 100644
index 00000000..b739fe46
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/footer.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * The template for displaying the footer.
+ *
+ * Contains the closing of the id=main div and all content after
+ *
+ * @package Minileven
+ */
+?>
+
+ </div><!-- #main -->
+</div><!-- #page -->
+<?php get_sidebar(); ?>
+
+</div><!-- #wrapper -->
+
+<footer id="colophon" role="contentinfo">
+ <div id="site-generator">
+
+<?php
+ global $wp;
+ $current_url = trailingslashit( home_url( add_query_arg( array(), $wp->request ) ) );
+?>
+ <a href="<?php echo $current_url . '?ak_action=reject_mobile'; ?>">View Full Site</a><br />
+ <?php do_action( 'wp_mobile_theme_footer' ); ?>
+ <?php do_action( 'minileven_credits' ); ?>
+ <a href="<?php echo esc_url( __( 'http://wordpress.org/', 'jetpack' ) ); ?>" title="<?php esc_attr_e( 'Semantic Personal Publishing Platform', 'minileven' , 'jetpack'); ?>" rel="generator"><?php printf( __( 'Proudly powered by %s', 'minileven' , 'jetpack'), 'WordPress' ); ?></a>
+ </div>
+</footer><!-- #colophon -->
+
+
+
+<?php wp_footer(); ?>
+
+</body>
+</html> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/functions.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/functions.php
new file mode 100644
index 00000000..d13cb234
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/functions.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Minileven functions and definitions
+ *
+ * Sets up the theme and provides some helper functions. Some helper functions
+ * are used in the theme as custom template tags. Others are attached to action and
+ * filter hooks in WordPress to change core functionality.
+ *
+ * The first function, minileven_setup(), sets up the theme by registering support
+ * for various features in WordPress, such as post thumbnails, navigation menus, and the like.
+ *
+ * @package Minileven
+ */
+
+/**
+ * Set the content width based on the theme's design and stylesheet.
+ */
+if ( ! isset( $content_width ) )
+ $content_width = 584;
+
+/**
+ * Tell WordPress to run minileven_setup() when the 'after_setup_theme' hook is run.
+ */
+add_action( 'after_setup_theme', 'minileven_setup' );
+
+if ( ! function_exists( 'minileven_setup' ) ):
+/**
+ * Sets up theme defaults and registers support for various WordPress features.
+ */
+function minileven_setup() {
+ global $wp_version;
+
+ /**
+ * Custom template tags for this theme.
+ */
+ require( get_template_directory() . '/inc/template-tags.php' );
+
+ /**
+ * Custom functions that act independently of the theme templates
+ */
+ require( get_template_directory() . '/inc/tweaks.php' );
+
+ /* Make Minileven available for translation.
+ * Translations can be added to the /languages/ directory.
+ * If you're building a theme based on Minileven, use a find and replace
+ * to change 'minileven' to the name of your theme in all the template files.
+ */
+ load_theme_textdomain( 'minileven', TEMPLATEPATH . '/languages' );
+
+ // Add default posts and comments RSS feed links to <head>.
+ add_theme_support( 'automatic-feed-links' );
+
+ // This theme uses wp_nav_menu() in one location.
+ register_nav_menu( 'primary', __( 'Primary Menu', 'jetpack' ) );
+
+ // Add support for a variety of post formats
+ add_theme_support( 'post-formats', array( 'gallery' ) );
+
+ // Add support for custom backgrounds
+ if ( version_compare( $wp_version, '3.4', '>=' ) )
+ add_theme_support( 'custom-background' );
+ else
+ add_custom_background();
+
+ // Add support for post thumbnails
+ add_theme_support( 'post-thumbnails' );
+}
+endif; // minileven_setup
+
+/**
+ * Enqueue scripts and styles
+ */
+function minileven_scripts() {
+ global $post;
+
+ wp_enqueue_style( 'style', get_stylesheet_uri() );
+
+ wp_enqueue_script( 'small-menu', get_template_directory_uri() . '/js/small-menu.js', array( 'jquery' ), '20120206', true );
+
+ if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
+ wp_enqueue_script( 'comment-reply' );
+ }
+}
+add_action( 'wp_enqueue_scripts', 'minileven_scripts' );
+
+/**
+ * Register our sidebars and widgetized areas.
+ * @since Minileven 1.0
+ */
+function minileven_widgets_init() {
+ register_sidebar( array(
+ 'name' => __( 'Main Sidebar', 'jetpack' ),
+ 'id' => 'sidebar-1',
+ 'before_widget' => '<aside id="%1$s" class="widget %2$s">',
+ 'after_widget' => "</aside>",
+ 'before_title' => '<h3 class="widget-title">',
+ 'after_title' => '</h3>',
+ ) );
+}
+add_action( 'widgets_init', 'minileven_widgets_init' );
+
+function minileven_posts_per_page() {
+ return 5;
+}
+add_filter('pre_option_posts_per_page', 'minileven_posts_per_page');
+
+/* This function determines the actual theme the user is using. */
+function minileven_actual_current_theme() {
+ if ( function_exists( 'jetpack_mobile_template' ) )
+ remove_action( 'option_template', 'jetpack_mobile_template' );
+
+ $template = get_option( 'template' );
+
+ if ( function_exists( 'jetpack_mobile_template' ) )
+ add_action( 'option_template', 'jetpack_mobile_template' );
+
+ return $template;
+}
+
+/* This function grabs the location of the custom menus from the current theme. If no menu is set in a location
+* it will return a boolean "false". This function helps Minileven know which custom menu to display. */
+function minileven_get_menu_location() {
+ $theme_slug = minileven_actual_current_theme();
+ $mods = get_option( "theme_mods_{$theme_slug}" );
+
+ if ( isset( $mods['nav_menu_locations'] ) && ! empty( $mods['nav_menu_locations'] ) )
+ return $mods['nav_menu_locations'];
+
+ return false;
+}
+
+/* This function grabs the custom background image from the user's current theme so that Minileven can display it. */
+function minileven_get_background() {
+ $theme_slug = minileven_actual_current_theme();
+ $mods = get_option( "theme_mods_$theme_slug" );
+
+ if ( ! empty( $mods ) ) {
+ return array(
+ 'color' => isset( $mods['background_color'] ) ? $mods['background_color'] : null,
+ 'image' => isset( $mods['background_image'] ) ? $mods['background_image'] : null,
+ 'repeat' => isset( $mods['background_repeat'] ) ? $mods['background_repeat'] : null,
+ 'position' => isset( $mods['background_position_x'] ) ? $mods['background_position_x'] : null,
+ 'attachment' => isset( $mods['attachment'] ) ? $mods['attachment'] : null,
+ );
+ }
+ return false;
+}
+
+/**
+ * Implement the Custom Header functions
+ */
+require( get_template_directory() . '/inc/custom-header.php' ); \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/header.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/header.php
new file mode 100644
index 00000000..7c5f9a66
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/header.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * The Header for our theme.
+ *
+ * Displays all of the <head> section and everything up till <div id="main">
+ *
+ * @package Minileven
+ */
+?><!DOCTYPE html>
+<html <?php language_attributes(); ?>>
+<head>
+<meta charset="<?php bloginfo( 'charset' ); ?>" />
+<meta name="viewport" content="width=device-width" />
+<title><?php wp_title( '|', true, 'right' ); ?></title>
+<link rel="profile" href="http://gmpg.org/xfn/11" />
+<link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
+<?php wp_head(); ?>
+
+<body <?php body_class(); ?>>
+<div id="wrapper">
+<div id="page" class="hfeed">
+ <header id="branding" role="banner">
+ <?php
+ minileven_header();
+ $location = minileven_get_menu_location(); // get the menu locations from the current theme in use
+ ?>
+ <div class="menu-search">
+ <nav id="access" role="navigation">
+ <div class="menu-handle">
+ <h3 class="assistive-text"><?php _e( 'Menu', 'jetpack' ); ?></h3>
+ </div><!-- .menu-handle -->
+ <?php /* Allow screen readers / text browsers to skip the navigation menu and get right to the good stuff. */ ?>
+ <div class="skip-link"><a class="assistive-text" href="#content" title="<?php esc_attr_e( 'Skip to primary content', 'jetpack' ); ?>"><?php _e( 'Skip to primary content', 'minileven' , 'jetpack'); ?></a></div>
+ <?php /* Our navigation menu. If one isn't filled out, wp_nav_menu falls back to wp_page_menu. The menu assiged to the primary position is the one used. If none is assigned, the menu with the lowest ID is used. */
+ if ( false !== $location ) :
+ $menu_id = array_shift( array_values( $location ) ); // acccess the ID of the menu assigned to that location. Using only the first menu ID returned in the array.
+ wp_nav_menu( array( 'theme_location' => 'primary', 'menu' => $menu_id ) );
+ else: // if the $location variable is false, wp_page_menu() is shown instead.
+ wp_nav_menu( array( 'theme_location' => 'primary' ) );
+ endif;
+ ?>
+ </nav><!-- #access -->
+ <div class="search-form">
+ <?php get_search_form(); ?>
+ </div><!-- .search-form-->
+ </div><!-- .menu-search-->
+ </header><!-- #branding -->
+
+ <div id="main"> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/image.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/image.php
new file mode 100644
index 00000000..be8402bd
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/image.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * The template for displaying image attachments.
+ *
+ * @package Minileven
+ */
+
+get_header(); ?>
+
+ <div id="primary" class="image-attachment">
+ <div id="content" role="main">
+
+ <?php while ( have_posts() ) : the_post(); ?>
+
+ <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
+ <header class="entry-header">
+ <h1 class="entry-title"><?php the_title(); ?></h1>
+ </header><!-- .entry-header -->
+
+ <div class="entry-content">
+
+ <div class="entry-attachment">
+ <div class="attachment">
+<?php
+ /**
+ * Grab the IDs of all the image attachments in a gallery so we can get the URL of the next adjacent image in a gallery,
+ * or the first image (if we're looking at the last image in a gallery), or, in a gallery of one, just the link to that image file
+ */
+ $attachments = array_values( get_children( array( 'post_parent' => $post->post_parent, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID' ) ) );
+ foreach ( $attachments as $k => $attachment ) {
+ if ( $attachment->ID == $post->ID )
+ break;
+ }
+ $k++;
+ // If there is more than 1 attachment in a gallery
+ if ( count( $attachments ) > 1 ) {
+ if ( isset( $attachments[ $k ] ) )
+ // get the URL of the next image attachment
+ $next_attachment_url = get_attachment_link( $attachments[ $k ]->ID );
+ else
+ // or get the URL of the first image attachment
+ $next_attachment_url = get_attachment_link( $attachments[ 0 ]->ID );
+ } else {
+ // or, if there's only 1 image, get the URL of the image
+ $next_attachment_url = wp_get_attachment_url();
+ }
+?>
+ <a href="<?php echo esc_url( $next_attachment_url ); ?>" title="<?php echo esc_attr( get_the_title() ); ?>" rel="attachment"><?php
+ $attachment_size = apply_filters( 'minileven_attachment_size', 848 );
+ echo wp_get_attachment_image( $post->ID, array( $attachment_size, 1024 ) ); // filterable image width with 1024px limit for image height.
+ ?></a>
+
+ <?php if ( ! empty( $post->post_excerpt ) ) : ?>
+ <div class="entry-caption">
+ <?php the_excerpt(); ?>
+ </div>
+ <?php endif; ?>
+ </div><!-- .attachment -->
+
+ </div><!-- .entry-attachment -->
+
+ <div class="entry-description">
+ <?php the_content(); ?>
+ <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'jetpack' ) . '</span>', 'after' => '</div>' ) ); ?>
+ </div><!-- .entry-description -->
+
+ </div><!-- .entry-content -->
+
+ <footer class="entry-meta">
+ <div class="attachment-meta">
+ <?php
+ $metadata = wp_get_attachment_metadata();
+ printf( __( '<span class="entry-gallery">&laquo; <a href="%1$s" title="Back to %2$s" rel="gallery">Back to Gallery</a></span>', 'jetpack' ),
+ esc_url( get_permalink( $post->post_parent ) ),
+ get_the_title( $post->post_parent )
+ );
+ ?>
+ </div><!-- .attachment-meta-->
+ <?php if ( comments_open() ) : ?>
+ <span class="comments-link"><?php comments_popup_link( '<span class="leave-reply">' . __( 'Leave a reply', 'jetpack' ) . '</span>', __( '<b>1</b> Reply', 'minileven' , 'jetpack'), __( '<b>%</b> Replies', 'minileven' , 'jetpack') ); ?></span>
+ <?php endif; // End if comments_open() ?>
+ <?php edit_post_link( __( 'Edit', 'jetpack' ), '<span class="edit-link">', '</span>' ); ?>
+ </footer><!-- #entry-meta -->
+ </article><!-- #post-<?php the_ID(); ?> -->
+
+ <nav id="nav-single">
+ <h3 class="assistive-text"><?php _e( 'Image navigation', 'next-saturday' , 'jetpack' ); ?></h3>
+ <span class="nav-previous"><?php previous_image_link( false, __( '&raquo; Previous' , 'jetpack' ) ); ?></span>
+ <span class="nav-next"><?php next_image_link( false, __( 'Next &raquo; ' , 'jetpack' ) ); ?></span>
+ </nav><!-- #nav-single -->
+
+ <?php comments_template(); ?>
+
+ <?php endwhile; // end of the loop. ?>
+
+ </div><!-- #content -->
+ </div><!-- #primary -->
+<?php get_footer(); ?> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/custom-header.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/custom-header.php
new file mode 100644
index 00000000..8a7a21e8
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/custom-header.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * @package Minileven
+ * @since Minileven 2.0
+ */
+
+/* This function grabs the custom header from the current theme so that Minileven can display it. */
+function minileven_get_header_image() {
+ $theme_slug = minileven_actual_current_theme();
+ $mods = get_option( "theme_mods_{$theme_slug}" );
+
+ if ( isset( $mods['header_image'] ) && 'remove-header' != $mods['header_image'] && 'random-default-image' != $mods['header_image'] && 'random-uploaded-image' != $mods['header_image'] )
+ return $mods['header_image'];
+
+ return false;
+}
+
+/* This function determines whether or not the user is displaying the header on the current theme */
+function minileven_header_text_display() {
+ $theme_slug = minileven_actual_current_theme();
+ $mods = get_option( "theme_mods_{$theme_slug}" );
+
+ if ( isset( $mods['header_textcolor'] ) )
+ return $mods['header_textcolor'];
+
+ return false;
+}
+
+/* This function determines how the header should be displayed. */
+function minileven_header() {
+ $header_image = minileven_get_header_image();
+ $header_text = minileven_header_text_display();
+
+ if ( 'blank' != $header_text ) : ?>
+ <hgroup>
+ <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>
+ <h2 id="site-description"><?php bloginfo( 'description' ); ?></h2>
+ </hgroup>
+<?php endif;
+
+ if ( false !== $header_image ) : ?>
+ <div id="header-img">
+ <a href="<?php echo esc_url( home_url( '/' ) ); ?>">
+ <img src="<?php echo $header_image; ?>" alt="" />
+ </a>
+ </div><!-- #header-img -->
+<?php endif; // end check for header image existence.
+}
+
+/* This function displays the custom background image or color, and custom text color */
+function minileven_show_background_and_header_color() {
+ $background = minileven_get_background();
+ $header_text = minileven_header_text_display();
+
+ $style = '';
+
+ if ( $background['color'] || $background['image'] ) :
+ $style = $background['color'] ? "background-color: #$background[color];" : '';
+
+ if ( $background['image'] ) :
+ $image = " background-image: url('$background[image]');";
+
+ if ( ! in_array( $background['repeat'], array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) )
+ $background['repeat'] = 'repeat';
+ $repeat = " background-repeat: $background[repeat];";
+
+ if ( ! in_array( $background['position'], array( 'center', 'right', 'left' ) ) )
+ $background['position'] = 'left';
+ $position = " background-position: top $background[position];";
+
+ if ( ! in_array( $background['attachment'], array( 'fixed', 'scroll' ) ) )
+ $background['attachment'] = 'scroll';
+ $attachment = " background-attachment: $background[attachment];";
+
+ $style .= $image . $repeat . $position . $attachment;
+ endif;
+ endif;
+?>
+ <style type="text/css">
+ <?php if ( $style ) { ?>
+ body {
+ <?php echo trim( $style ); ?>
+ }
+ <?php } ?>
+ #page {
+ margin: 0.6em 0.6em 0.8em;
+ }
+ #site-generator {
+ border: 0;
+ }
+ <?php if ( 'blank' != $header_text && '1' != get_option( 'wp_mobile_header_color' ) ) : ?>
+ /* If The user has set a header text color, use that */
+ #site-title,
+ #site-title a {
+ color: #<?php echo $header_text; ?>;
+ <?php endif; ?>
+ }
+ </style>
+<?php
+}
+add_action( 'wp_head', 'minileven_show_background_and_header_color' ); \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/template-tags.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/template-tags.php
new file mode 100644
index 00000000..2fc5f6d6
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/template-tags.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Custom template tags for this theme.
+ *
+ * Eventually, some of the functionality here could be replaced by core features
+ *
+ * @package Minileven
+ * @since Minileven 2.0
+ */
+
+/**
+ * Display navigation to next/previous pages when applicable
+ */
+function minileven_content_nav( $nav_id ) {
+ global $wp_query;
+
+ if ( $wp_query->max_num_pages > 1 ) : ?>
+ <nav id="<?php echo $nav_id; ?>">
+ <h3 class="assistive-text"><?php _e( 'Post navigation', 'jetpack' ); ?></h3>
+ <div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">&laquo;</span> Older', 'jetpack' ) ); ?></div>
+ <div class="nav-next"><?php previous_posts_link( __( 'Newer <span class="meta-nav">&raquo;</span>', 'jetpack' ) ); ?></div>
+ </nav><!-- #nav-above -->
+ <?php endif;
+}
+
+/**
+ * Template for comments and pingbacks.
+ * Used as a callback by wp_list_comments() for displaying the comments.
+ * @since Minileven 1.0
+ */
+function minileven_comment( $comment, $args, $depth ) {
+ $GLOBALS['comment'] = $comment;
+ switch ( $comment->comment_type ) :
+ case 'pingback' :
+ case 'trackback' :
+ ?>
+ <li class="post pingback">
+ <p><?php _e( 'Pingback:', 'jetpack' ); ?> <?php comment_author_link(); ?></p>
+ <?php
+ break;
+ default :
+ ?>
+ <li <?php comment_class(); ?> id="li-comment-<?php comment_ID(); ?>">
+ <article id="comment-<?php comment_ID(); ?>" class="comment">
+ <footer class="comment-meta">
+ <div class="comment-author vcard">
+ <?php
+ $avatar_size = 32;
+ if ( '0' != $comment->comment_parent )
+ $avatar_size = 24;
+
+ echo get_avatar( $comment, $avatar_size );
+
+ /* translators: 1: comment author, 2: date and time */
+ printf( __( '%1$s on %2$s', 'jetpack' ),
+ sprintf( '<span class="fn">%s</span>', get_comment_author_link() ),
+ sprintf( '<a href="%1$s"><time pubdate datetime="%2$s">%3$s</time></a>',
+ esc_url( get_comment_link( $comment->comment_ID ) ),
+ get_comment_time( 'c' ),
+ /* translators: 1: date, 2: time */
+ sprintf( __( '%1$s at %2$s', 'jetpack' ), get_comment_date(), get_comment_time() )
+ )
+ );
+ ?>
+
+ <?php edit_comment_link( __( 'Edit', 'jetpack' ), '<span class="edit-link">', '</span>' ); ?>
+ </div><!-- .comment-author .vcard -->
+
+ <?php if ( $comment->comment_approved == '0' ) : ?>
+ <em class="comment-awaiting-moderation"><?php _e( 'Your comment is awaiting moderation.', 'jetpack' ); ?></em>
+ <br />
+ <?php endif; ?>
+
+ </footer>
+
+ <div class="comment-content"><?php comment_text(); ?></div>
+
+ <div class="reply">
+ <?php comment_reply_link( array_merge( $args, array( 'reply_text' => __( 'Reply <span>&darr;</span>', 'jetpack' ), 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?>
+ </div><!-- .reply -->
+ </article><!-- #comment-## -->
+
+ <?php
+ break;
+ endswitch;
+}
+
+/**
+ * Prints HTML with meta information for the current post-date/time and author.
+ * @since Minileven 1.0
+ */
+function minileven_posted_on() {
+ printf( __( '<span class="entry-date"><a href="%1$s" title="%2$s" rel="bookmark"><time datetime="%3$s" pubdate>%4$s</time></a></span>', 'jetpack' ),
+ esc_url( get_permalink() ),
+ esc_attr( get_the_time() ),
+ esc_attr( get_the_date( 'c' ) ),
+ esc_html( get_the_date() )
+ );
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/tweaks.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/tweaks.php
new file mode 100644
index 00000000..35a96720
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/tweaks.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Custom functions that act independently of the theme templates
+ *
+ * Eventually, some of the functionality here could be replaced by core features
+ *
+ * @package Minileven
+ * @since Minileven 2.0
+ */
+
+/**
+ * Sets the post excerpt length to 40 words.
+ *
+ * To override this length in a child theme, remove the filter and add your own
+ * function tied to the excerpt_length filter hook.
+ */
+function minileven_excerpt_length( $length ) {
+ return 40;
+}
+add_filter( 'excerpt_length', 'minileven_excerpt_length' );
+
+/**
+ * Returns a "Continue Reading" link for excerpts
+ */
+function minileven_continue_reading_link() {
+ return ' <a href="'. esc_url( get_permalink() ) . '">' . __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'jetpack' ) . '</a>';
+}
+
+/**
+ * Replaces "[...]" (appended to automatically generated excerpts) with an ellipsis and minileven_continue_reading_link().
+ */
+function minileven_auto_excerpt_more( $more ) {
+ return ' &hellip;' . minileven_continue_reading_link();
+}
+add_filter( 'excerpt_more', 'minileven_auto_excerpt_more' );
+
+/**
+ * Adds a pretty "Continue Reading" link to custom post excerpts.
+ *
+ * To override this link in a child theme, remove the filter and add your own
+ * function tied to the get_the_excerpt filter hook.
+ */
+function minileven_custom_excerpt_more( $output ) {
+ if ( has_excerpt() && ! is_attachment() ) {
+ $output .= minileven_continue_reading_link();
+ }
+ return $output;
+}
+add_filter( 'get_the_excerpt', 'minileven_custom_excerpt_more' );
+
+/**
+ * Get our wp_nav_menu() fallback, wp_page_menu(), to show a home link.
+ */
+function minileven_page_menu_args( $args ) {
+ $args['show_home'] = true;
+ return $args;
+}
+add_filter( 'wp_page_menu_args', 'minileven_page_menu_args' );
+
+/**
+ * Adds a custom class to the array of body classes, to allow Minileven to be targeted with Custom CSS.
+ */
+function minileven_body_classes( $classes ) {
+ $classes[] = 'mobile-theme';
+ return $classes;
+}
+add_filter( 'body_class', 'minileven_body_classes' );
+
+/**
+ * Filters wp_title to print a neat <title> tag based on what is being viewed.
+ *
+ * @since Minileven 2.0
+ */
+function minileven_wp_title( $title, $sep ) {
+ global $page, $paged;
+
+ if ( is_feed() )
+ return $title;
+
+ // Add the blog name
+ $title .= get_bloginfo( 'name' );
+
+ // Add the blog description for the home/front page.
+ $site_description = get_bloginfo( 'description', 'display' );
+ if ( $site_description && ( is_home() || is_front_page() ) )
+ $title .= " $sep $site_description";
+
+ // Add a page number if necessary:
+ if ( $paged >= 2 || $page >= 2 )
+ $title .= " $sep " . sprintf( __( 'Page %s', 'jetpack' ), max( $paged, $page ) );
+
+ return $title;
+}
+add_filter( 'wp_title', 'minileven_wp_title', 10, 2 );
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/index.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/index.php
new file mode 100644
index 00000000..71aa73b6
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/index.php
@@ -0,0 +1,73 @@
+<?php
+/**
+ * The main template file.
+ *
+ * This is the most generic template file in a WordPress theme
+ * and one of the two required files for a theme (the other being style.css).
+ * It is used to display a page when nothing more specific matches a query.
+ * E.g., it puts together the home page when no home.php file exists.
+ * Learn more: http://codex.wordpress.org/Template_Hierarchy
+ *
+ * @package Minileven
+ */
+
+get_header(); ?>
+
+ <div id="primary">
+ <div id="content" role="main">
+
+ <?php if ( is_archive() ) : ?>
+ <header class="page-header">
+ <h1 class="page-title">
+ <?php if ( is_day() ) : ?>
+ <?php printf( __( 'Daily Archives: %s', 'jetpack' ), '<span>' . get_the_date() . '</span>' ); ?>
+ <?php elseif ( is_month() ) : ?>
+ <?php printf( __( 'Monthly Archives: %s', 'jetpack' ), '<span>' . get_the_date( 'F Y' ) . '</span>' ); ?>
+ <?php elseif ( is_year() ) : ?>
+ <?php printf( __( 'Yearly Archives: %s', 'jetpack' ), '<span>' . get_the_date( 'Y' ) . '</span>' ); ?>
+ <?php elseif ( is_category() ) : ?>
+ <?php printf( __( 'Posted in %s', 'jetpack' ), '<span>' . single_cat_title( '', false ) . '</span>' ); ?>
+ <?php elseif ( is_tag() ) : ?>
+ <?php printf( __( 'Tagged with %s', 'jetpack' ), '<span>' . single_tag_title( '', false ) . '</span>' ); ?>
+ <?php elseif( is_author() ) : ?>
+ <?php printf( __( 'Posted by', 'jetpack' ), '<span>' . get_the_author() . '</span>' ); ?>
+ <?php else : ?>
+ <?php _e( 'Blog Archives', 'jetpack' ); ?>
+ <?php endif; ?>
+ </h1>
+ </header>
+ <?php endif; ?>
+
+ <?php if ( is_search() ) : ?>
+ <header class="page-header">
+ <h1 class="page-title"><?php printf( __( 'Search Results for: %s', 'jetpack' ), '<span>' . get_search_query() . '</span>' ); ?></h1>
+ </header>
+ <?php endif; ?>
+
+ <?php if ( have_posts() ) : // Start the loop ?>
+ <?php while ( have_posts() ) : the_post(); ?>
+
+ <?php get_template_part( 'content', get_post_format() ); ?>
+
+ <?php endwhile; ?>
+
+ <?php else : ?>
+ <article id="post-0" class="post error404 not-found">
+ <header class="entry-header">
+ <h1 class="entry-title"><?php _e( 'Nothing Found', 'jetpack' ); ?></h1>
+ </header><!-- .entry-header -->
+
+ <div class="entry-content">
+ <p><?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'jetpack' ); ?></p>
+ <?php get_search_form(); ?>
+ </div><!-- .entry-content -->
+ </article><!-- #post-0 -->
+
+ <?php endif; ?>
+
+ </div><!-- #content -->
+
+ <?php minileven_content_nav( 'nav-below' ); ?>
+
+ </div><!-- #primary -->
+<?php get_footer(); ?> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/js/small-menu.js b/plugins/jetpack/modules/minileven/theme/pub/minileven/js/small-menu.js
new file mode 100644
index 00000000..f6e1d060
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/js/small-menu.js
@@ -0,0 +1,41 @@
+/**
+ * Handles toggling the main navigation menu for small screens.
+ */
+jQuery( document ).ready( function( $ ) {
+ var $subsidiary = $( '#branding' ),
+ timeout = false;
+
+ $.fn.smallMenu = function() {
+ $subsidiary.find( '#access' ).addClass( 'main-small-navigation' );
+ $subsidiary.find( '#access h3' ).removeClass( 'assistive-text' ).addClass( 'menu-label' );
+ $subsidiary.find( '#access .menu-handle' ).addClass( 'menu-toggle' );
+
+ $( '.menu-toggle' ).click( function() {
+ $subsidiary.find( '.menu' ).toggle();
+ $( this ).toggleClass( 'toggled-on' );
+ } );
+ };
+
+ // Check viewport width on first load.
+ if ( $( window ).width() < 4000 )
+ $.fn.smallMenu();
+
+ // Check viewport width when user resizes the browser window.
+ $( window ).resize( function() {
+ var browserWidth = $( window ).width();
+
+ if ( false !== timeout )
+ clearTimeout( timeout );
+
+ timeout = setTimeout( function() {
+ if ( browserWidth < 4000 ) {
+ $.fn.smallMenu();
+ } else {
+ $subsidiary.find( '#access' ).removeClass( 'main-small-navigation' );
+ $subsidiary.find( '#access h3' ).removeClass( 'menu-label' ).addClass( 'assistive-text' );
+ $subsidiary.find( '#access .menu-handle' ).removeClass( 'menu-toggle' );
+ $subsidiary.find( '.menu' ).removeAttr( 'style' );
+ }
+ }, 200 );
+ } );
+} ); \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/page.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/page.php
new file mode 100644
index 00000000..785137ef
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/page.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * The template for displaying all pages.
+ *
+ * This is the template that displays all pages by default.
+ * Please note that this is the WordPress construct of pages
+ * and that other 'pages' on your WordPress site will use a
+ * different template.
+ *
+ * @package Minileven
+ */
+
+get_header(); ?>
+
+ <div id="primary">
+ <div id="content" role="main">
+
+ <?php while ( have_posts() ) : the_post(); ?>
+
+ <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
+ <header class="entry-header">
+ <h1 class="entry-title"><?php the_title(); ?></h1>
+ </header><!-- .entry-header -->
+
+ <div class="entry-content">
+ <?php the_content(); ?>
+ <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'jetpack' ) . '</span>', 'after' => '</div>' ) ); ?>
+ </div><!-- .entry-content -->
+ <?php if ( is_user_logged_in() ) : ?>
+ <footer class="entry-meta">
+ <?php edit_post_link( __( 'Edit', 'jetpack' ), '<span class="edit-link">', '</span>' ); ?>
+ </footer><!-- .entry-meta -->
+ <?php endif; ?>
+ </article><!-- #post-<?php the_ID(); ?> -->
+
+ <?php comments_template( '', true ); ?>
+
+ <?php endwhile; // end of the loop. ?>
+
+ </div><!-- #content -->
+ </div><!-- #primary -->
+<?php get_footer(); ?> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/rtl.css b/plugins/jetpack/modules/minileven/theme/pub/minileven/rtl.css
new file mode 100644
index 00000000..7b67e1f2
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/rtl.css
@@ -0,0 +1,582 @@
+/*
+Theme Name: Twenty Eleven
+
+Adding support for language written in a Right To Left (RTL) direction is easy -
+it's just a matter of overwriting all the horizontal positioning attributes
+of your CSS stylesheet in a separate stylesheet file named rtl.css.
+
+http://codex.wordpress.org/Right_to_Left_Language_Support
+
+*/
+
+/* =Reset reset
+----------------------------------------------- */
+
+caption, th, td {
+ text-align: right;
+}
+
+/* =Structure
+----------------------------------------------- */
+
+body {
+ direction:rtl;
+ unicode-bidi:embed;
+}
+
+/* Showcase */
+.page-template-showcase-php section.recent-posts {
+ float: left;
+ margin: 0 31% 0 0;
+}
+.page-template-showcase-php #main .widget-area {
+ float: right;
+ margin: 0 0 0 -22.15%;
+}
+
+/* One column */
+
+.one-column article.feature-image.small .entry-summary a {
+ left: auto;
+ right: -9%;
+}
+
+/* Simplify the pullquotes and pull styles */
+.one-column.singular .entry-meta .edit-link a {
+ right: 0px;
+ left: auto;
+}
+/* Make sure we have room for our comment avatars */
+.one-column .commentlist > li.comment {
+ margin-left: 0;
+ margin-right: 102px;
+}
+/* Make sure the logo and search form don't collide */
+.one-column #branding #searchform {
+ right: auto;
+ left: 40px;
+}
+/* Talking avatars take up too much room at this size */
+.one-column .commentlist > li.comment {
+ margin-right: 0;
+}
+.one-column .commentlist > li.comment .comment-meta,
+.one-column .commentlist > li.comment .comment-content {
+ margin-right: 0;
+ margin-left: 85px;
+}
+.one-column .commentlist .avatar {
+ right: auto;
+ left: 1.625em;
+}
+.one-column .commentlist .children .avatar {
+ left: auto;
+ right: 2.2em;
+}
+
+/* =Global
+----------------------------------------------- */
+
+/* Text elements */
+p {
+ margin-bottom: 1.625em;
+}
+ul, ol {
+ margin: 0 2.5em 1.625em 0;
+}
+.ltr ul, ol {
+ margin: 0 0 1.625em 2.5em;
+}
+blockquote {
+ font-family: Arial, sans-serif;
+}
+blockquote em, blockquote i, blockquote cite {
+ font-style: normal;
+}
+
+/* Forms */
+textarea {
+ padding-left: 0;
+ padding-right: 3px;
+}
+input#s {
+ background-position: 97% 6px;
+ padding: 4px 28px 4px 10px;
+}
+
+/* Assistive text */
+#access a.assistive-text:active,
+#access a.assistive-text:focus {
+ left: auto;
+ right: 7.6%;
+}
+
+/* =Header
+----------------------------------------------- */
+
+#site-title {
+ margin-right: 0;
+ margin-left: 270px;
+}
+
+#site-description {
+ margin: 0 0 3.65625em 270px;
+}
+
+/* =Menu
+-------------------------------------------------------------- */
+
+#access {
+ float: right;
+}
+#access ul {
+ margin: 0 -0.8125em 0 0;
+ padding-right: 0;
+}
+#access li {
+ float: right;
+}
+#access ul ul {
+ float: right;
+ left: auto;
+ right: 0;
+}
+#access ul ul ul {
+ left: auto;
+ right: 100%;
+}
+
+/* Search Form */
+#branding #searchform {
+ right: auto;
+ left: 7.6%;
+ text-align: left;
+}
+#branding #s {
+ float: left;
+}
+#branding .only-search + #access div {
+ padding-right: 0;
+ padding-left: 205px;
+}
+
+
+/* =Content
+----------------------------------------------- */
+.entry-title,
+.entry-header .entry-meta {
+ padding-right: 0;
+ padding-left: 76px;
+}
+.entry-content td,
+.comment-content td {
+ padding: 6px 0 6px 10px;
+}
+.page-link span {
+ margin-right: 0;
+ margin-left: 6px;
+}
+.entry-meta .edit-link a {
+ float: left;
+}
+/* Images */
+
+.wp-caption .wp-caption-text,
+.gallery-caption {
+ font-family: Arial, sans-serif;
+}
+.wp-caption .wp-caption-text {
+ padding: 10px 40px 5px 0px;
+}
+.wp-caption .wp-caption-text:before {
+ margin-right: 0;
+ margin-left: 5px;
+ left: auto;
+ right: 10px;
+}
+#content .gallery-columns-4 .gallery-item {
+ padding-right:0;
+ padding-left:2%;
+}
+
+/* Author Info */
+.singular #author-info {
+ margin: 2.2em -35.4% 0 -35.6%;
+}
+#author-avatar {
+ float: right;
+ margin-right: 0;
+ margin-left: -78px;
+}
+#author-description {
+ float: right;
+ margin-left: 0;
+ margin-right: 108px;
+}
+/* Comments link */
+.entry-header .comments-link a {
+ background-image: url(images/comment-bubble-rtl.png);
+ right: auto;
+ left: 0;
+}
+
+/*
+ Post Formats Headings
+*/
+.singular .entry-title,
+.singular .entry-header .entry-meta {
+ padding-left: 0;
+}
+.singular .entry-header .entry-meta {
+ left: auto;
+ right: 0;
+}
+.singular .entry-meta .edit-link a {
+ left: auto;
+ right: 50px;
+}
+
+
+/* =Gallery
+----------------------------------------------- */
+
+.format-gallery .gallery-thumb {
+ float: right;
+ margin: .375em 0 0 1.625em;
+}
+
+
+/* =Status
+----------------------------------------------- */
+
+.format-status img.avatar {
+ float: right;
+ margin: 4px 0 2px 10px;
+}
+
+
+/* =Image
+----------------------------------------------- */
+
+.indexed.format-image div.entry-meta {
+ float: right;
+}
+/* =error404
+----------------------
+------------------------- */
+.error404 #main .widget {
+ float: right;
+ margin-right: auto;
+ margin-left: 3.7%;
+}
+.error404 #main .widget_archive {
+ margin-left: 0;
+}
+.error404 #main .widget_tag_cloud {
+ margin-left: 0;
+}
+
+/* =Showcase
+----------------------------------------------- */
+
+article.intro .edit-link a {
+ right: auto;
+ left: 20px;
+}
+
+/* Featured post */
+section.featured-post {
+ float: right;
+}
+
+/* Small featured post */
+section.featured-post .attachment-small-feature {
+ float: left;
+ margin: 0 0 1.625em -8.9%;
+ right: auto;
+ left: -15px;
+}
+article.feature-image.small {
+ float: right;
+}
+article.feature-image.small .entry-summary p a {
+ left:auto;
+ right: -23.8%;
+ padding: 9px 85px 9px 26px;
+}
+
+/* Large featured post */
+section.feature-image.large .hentry {
+ left:auto;
+ right: 9%;
+ margin: 1.625em 0 0 9%;
+}
+/* Featured Slider */
+.featured-posts .showcase-heading {
+ padding-left: 0;
+ padding-right: 8.9%;
+}
+.featured-posts section.featured-post {
+ left: auto;
+ right: 0;
+}
+#content .feature-slider {
+ right: auto;
+ left: 8.9%;
+}
+.feature-slider li {
+ float: right;
+}
+/* Recent Posts */
+section.recent-posts .other-recent-posts a[rel="bookmark"] {
+ float: right;
+}
+section.recent-posts .other-recent-posts .comments-link a,
+section.recent-posts .other-recent-posts .comments-link > span {
+ padding: 0.3125em 1em 0.3125em 0;
+ left: 0;
+ text-align: left;
+}
+
+/* =Attachments
+----------------------------------------------- */
+
+/* =Navigation
+-------------------------------------------------------------- */
+
+.nav-previous {
+ float: right;
+}
+.nav-next {
+ float: left;
+ text-align: left;
+}
+
+/* Singular navigation */
+#nav-single {
+ float: left;
+ text-align: left;
+}
+#nav-single .nav-next {
+ padding-left: 0;
+ padding-right: .5em;
+}
+
+
+/* =Widgets
+----------------------------------------------- */
+
+.widget ul ul {
+ margin-left: 0;
+ margin-right: 1.5em;
+}
+
+/* Twitter */
+.widget_twitter .timesince {
+ margin-right: 0;
+ margin-left: -10px;
+ text-align: left;
+}
+
+/* =Comments
+----------------------------------------------- */
+
+.commentlist .children li.comment {
+ border-left: none;
+ border-right: 1px solid #ddd;
+ -moz-border-radius: 3px 0 0 3px;
+ border-radius: 3px 0 0 3px;
+}
+.commentlist .children li.comment .comment-meta {
+ margin-left: 0;
+ margin-right: 50px;
+}
+.commentlist .avatar {
+ left: auto;
+ right: -102px;
+}
+.commentlist > li:before {
+ content: url(images/comment-arrow-rtl.png);
+ left:auto;
+ right: -21px;
+}
+.commentlist > li.pingback:before {
+ content: '';
+}
+.commentlist .children .avatar {
+ left: auto;
+ right: 2.2em;
+}
+
+/* Post author highlighting */
+.commentlist > li.bypostauthor:before {
+ content: url(images/comment-arrow-bypostauthor-rtl.png);
+}
+
+/* sidebar-page.php comments */
+/* Make sure we have room for our comment avatars */
+.page-template-sidebar-page-php .commentlist > li.comment,
+.page-template-sidebar-page-php.commentlist .pingback {
+ margin-left: 0;
+ margin-right: 102px;
+}
+
+/* Comment Form */
+#respond .comment-form-author label,
+#respond .comment-form-email label,
+#respond .comment-form-url label,
+#respond .comment-form-comment label {
+ left: auto;
+ right: 4px;
+}
+#respond .comment-form-author label,
+#respond .comment-form-email label,
+#respond .comment-form-url label,
+#respond .comment-form-comment label {
+ -webkit-box-shadow: -1px 2px 2px rgba(204,204,204,0.8);
+ -moz-box-shadow: -1px 2px 2px rgba(204,204,204,0.8);
+ box-shadow: -1px 2px 2px rgba(204,204,204,0.8);
+}
+#respond .comment-form-author .required,
+#respond .comment-form-email .required {
+ left: auto;
+ right: 75%;
+}
+#respond .form-submit {
+ float: left;
+}
+#respond input#submit {
+ left: auto;
+ right: 30px;
+ padding: 5px 22px 5px 42px;
+}
+#respond #cancel-comment-reply-link {
+ margin-left: 0;
+ margin-right: 10px;
+}
+#cancel-comment-reply-link {
+ right: auto;
+ left: 1.625em;
+}
+
+/* =Footer
+----------------------------------------------- */
+
+/* Two Footer Widget Areas */
+#supplementary.two .widget-area {
+ float: right;
+ margin-right: 0;
+ margin-left: 3.7%;
+}
+#supplementary.two .widget-area + .widget-area {
+ margin-left: 0;
+}
+
+/* Three Footer Widget Areas */
+#supplementary.three .widget-area {
+ float: right;
+ margin-right: 0;
+ margin-left: 3.7%;
+}
+#supplementary.three .widget-area + .widget-area + .widget-area {
+ margin-left: 0;
+}
+
+/* Site Generator Line */
+#site-generator .sep {
+ background-position: right center;
+}
+
+
+/* =Responsive Structure
+----------------------------------------------- */
+
+@media (max-width: 800px) {
+ /* Simplify the showcase template when small feature */
+ section.featured-post .attachment-small-feature,
+ .one-column section.featured-post .attachment-small-feature {
+ float: right;
+ }
+ article.feature-image.small {
+ float: left;
+ }
+ article.feature-image.small .entry-summary p a {
+ right: 0;
+ }
+ .singular .entry-meta .edit-link a {
+ left: auto;
+ right: 0px;
+ }
+ /* Make sure we have room for our comment avatars */
+ .commentlist > li.comment,
+ .commentlist .pingback {
+ margin-left: 0;
+ margin-right: 102px;
+ }
+ /* No need to float footer widgets at this size */
+ #colophon #supplementary .widget-area {
+ margin-left: 0;
+ }
+ /* No need to float 404 widgets at this size */
+ .error404 #main .widget {
+ margin-left: 0;
+ }
+}
+@media (max-width: 650px) {
+ /* @media (max-width: 650px) Reduce font-sizes for better readability on smaller devices */
+ #site-title,
+ #site-description {
+ margin-left: 0;
+ }
+ /* Talking avatars take up too much room at this size */
+ .commentlist > li.comment,
+ .commentlist > li.pingback {
+ margin-right: 0 !important;
+ }
+ .commentlist .children .avatar {
+ left: auto;
+ right: 2.2em;
+ }
+ /* Use the available space in the smaller comment form */
+ #respond .comment-form-author .required,
+ #respond .comment-form-email .required {
+ left: auto;
+ right: 95%;
+ }
+ #content .gallery-columns-3 .gallery-item {
+ padding-right: 0;
+ padding-left:2%;
+ }
+}
+@media (max-width: 450px) {
+ #content .gallery-columns-2 .gallery-item {
+ padding-right:0;
+ padding-left:4%;
+ }
+}
+
+/* =Print
+----------------------------------------------- */
+
+@media print {
+ #primary {
+ float: right;
+ }
+ /* Comments */
+ .commentlist .avatar {
+ left: auto;
+ right: 2.2em;
+ }
+ .commentlist li.comment .comment-meta {
+ margin-left: 0;
+ margin-right: 50px;
+ }
+}
+
+/* =IE7
+----------------------------------------------- */
+
+#ie7 section.recent-posts {
+ margin-right: 0;
+ margin-left: 7.6%;
+}
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/screenshot.png b/plugins/jetpack/modules/minileven/theme/pub/minileven/screenshot.png
new file mode 100644
index 00000000..348e94c0
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/screenshot.png
Binary files differ
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/searchform.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/searchform.php
new file mode 100644
index 00000000..b4fd79aa
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/searchform.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * The template for displaying search forms in Minileven
+ *
+ * @package Minileven
+ */
+?>
+ <form method="get" id="searchform" action="<?php echo esc_url( home_url( '/' ) ); ?>">
+ <label for="s" class="assistive-text"><?php _e( 'Search', 'jetpack' ); ?></label>
+ <input type="text" class="field" name="s" id="s" placeholder="<?php esc_attr_e( 'Search', 'jetpack' ); ?>" />
+ <input type="submit" class="submit" name="submit" id="searchsubmit" value="<?php esc_attr_e( 'Search', 'jetpack' ); ?>" />
+ </form>
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/sidebar.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/sidebar.php
new file mode 100644
index 00000000..5d1a4a06
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/sidebar.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * The Sidebar containing the main widget area.
+ *
+ * @package Minileven
+ */
+?>
+ <?php if ( is_active_sidebar( 'sidebar-1' ) ) : ?>
+ <div id="secondary" class="widget-area" role="complementary">
+ <?php dynamic_sidebar( 'sidebar-1' ); ?>
+ </div><!-- #secondary .widget-area -->
+ <?php endif; ?> \ No newline at end of file
diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/style.css b/plugins/jetpack/modules/minileven/theme/pub/minileven/style.css
new file mode 100644
index 00000000..692a8f4f
--- /dev/null
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/style.css
@@ -0,0 +1,1437 @@
+/*
+Theme Name: Minileven
+Theme URI: http://automattic.com
+Author: Automattic
+Author URI: http://automattic.com
+Description: The Minileven theme is a clean, lightweight mobile experience for your blog based on Twenty Eleven.
+Version: 2.0-wpcom
+License: GNU General Public License
+License URI: license.txt
+Tags: dark, light, white, black, gray, one-column, flexible-width, responsive-width, custom-background, custom-header, custom-menu, full-width-template, infinite-scroll, microformats, post-formats, rtl-language-support, sticky-post, theme-options, translation-ready, blog, bright, clean, contemporary, elegant, minimal, modern, photography, simple, tumblelog
+*/
+
+
+/* =Reset default browser CSS. Based on work by Eric Meyer: http://meyerweb.com/eric/tools/css/reset/index.html
+-------------------------------------------------------------- */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+ border: 0;
+ font-family: inherit;
+ font-size: 100%;
+ font-style: inherit;
+ font-weight: inherit;
+ margin: 0;
+ outline: 0;
+ padding: 0;
+ vertical-align: baseline;
+}
+:focus {/* remember to define focus styles! */
+ outline: 0;
+}
+body {
+ background: #fff;
+ line-height: 1;
+ -webkit-overflow-scrolling: touch;
+}
+ol, ul {
+ list-style: none;
+}
+a img {
+ border: 0;
+}
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+
+
+/* =Global
+----------------------------------------------- */
+
+body, input, textarea {
+ color: #373737;
+ font: 13px "Helvetica Neue", Helvetica, Arial, sans-serif;
+ line-height: 1.625;
+ word-wrap: break-word;
+}
+body {
+ background: #eee;
+}
+#page {
+ background: #fff;
+}
+
+/* Headings */
+h1,h2,h3,h4,h5,h6 {
+ clear: both;
+}
+hr {
+ background-color: #ccc;
+ border: 0;
+ height: 1px;
+ margin-bottom: 1.625em;
+}
+
+/* Text elements */
+p {
+ margin-bottom: 1.0em;
+}
+ul, ol {
+ margin: 0 0 1.625em 2.5em;
+}
+ul {
+ list-style: square;
+}
+ol {
+ list-style-type: decimal;
+}
+ul ul, ol ol, ul ol, ol ul {
+ margin-bottom: 0;
+}
+dl {
+ margin: 0 1.625em;
+}
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-bottom: 1.625em;
+}
+strong {
+ font-weight: bold;
+}
+cite, em, i {
+ font-style: italic;
+}
+blockquote {
+ font-family: Georgia, "Bitstream Charter", serif;
+ font-style: italic;
+ font-weight: normal;
+ margin: 0;
+}
+blockquote em, blockquote i, blockquote cite {
+ font-style: normal;
+}
+blockquote cite {
+ color: #666;
+ font-size: 0.800em;
+ font-weight: 300;
+ letter-spacing: 0.05em;
+ text-transform: uppercase;
+}
+pre {
+ background: #f4f4f4;
+ font: 1em "Courier 10 Pitch", Courier, monospace;
+ line-height: 1.5;
+ margin-bottom: 1.625em;
+ overflow: auto;
+ padding: 0.75em 1.625em;
+}
+code, kbd {
+ font: 1em Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace;
+}
+abbr, acronym, dfn {
+ border-bottom: 1px dotted #666;
+ cursor: help;
+}
+address {
+ display: block;
+ margin: 0 0 1.625em;
+}
+ins {
+ background: #fff9c0;
+ text-decoration: none;
+}
+sup,
+sub {
+ font-size: 0.667em;
+ height: 0;
+ line-height: 1;
+ position: relative;
+ vertical-align: baseline;
+}
+sup {
+ bottom: 1ex;
+}
+sub {
+ top: .5ex;
+}
+
+/* Forms */
+input[type=text],
+input[type=email],
+input[type=password],
+textarea {
+ background: #fafafa;
+ -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);
+ border: 1px solid #ddd;
+ color: #888;
+}
+input[type=text]:focus,
+input[type=email]:focus,
+textarea:focus {
+ color: #373737;
+}
+textarea {
+ padding-left: 3px;
+ width: 98%;
+}
+input[type=text],
+input[type=email] {
+ padding: 3px;
+}
+input#s {
+ border-radius: 2px;
+ height: 1.692em;
+ line-height: 1.2em;
+ padding: 0.4em 0.6em;
+}
+input#searchsubmit {
+ display: none;
+}
+
+/* Links */
+a {
+ color: #00a4bc;
+ text-decoration: none;
+}
+/* Assistive text */
+.assistive-text {
+ clip: rect(1px, 1px, 1px, 1px);
+ position: absolute !important;
+ visibility: hidden;
+}
+
+
+/* =Structure
+----------------------------------------------- */
+
+#page {
+ margin: 0 auto;
+ padding: 2.5%;
+}
+
+#primary,
+#secondary {
+ margin: 0 auto;
+ width: auto;
+}
+
+/* Alignment */
+.aligncenter,
+.alignleft,
+.alignright {
+ clear: both;
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+/* Make sure embeds and iframes scale on smaller screens */
+embed,
+iframe,
+object {
+ height: auto;
+ width: auto;
+}
+
+
+/* =Header
+----------------------------------------------- */
+
+#branding hgroup {
+ margin-bottom: 1.3em;
+}
+#site-title,
+#site-description {
+ clear: none;
+}
+#site-title a {
+ color: #111;
+ font-size: 1.846em;
+ font-weight: bold;
+ line-height: 1.3em;
+}
+#site-description {
+ color: #7a7a7a;
+ font-size: 0.923em;
+}
+
+/* Header Image */
+#header-img {
+ text-align: center;
+}
+header img {
+ max-width: 100%;
+ height: auto;
+}
+
+
+/* =Navigation and Search Form
+----------------------------------------------- */
+
+.menu-search {
+ background: #dcdcdc;
+ background: -moz-linear-gradient(#dcdcdc, #c8c8c8);
+ background: -o-linear-gradient(#dcdcdc, #c8c8c8);
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#dcdcdc), to(#c8c8c8)); /* older webkit syntax */
+ background: -webkit-linear-gradient(#dcdcdc, #c8c8c8);
+ clear: both;
+ margin-bottom: 1.3em;
+ width: 100%;
+}
+.menu-search:after {
+ clear: both;
+ content: "";
+ display: block;
+}
+
+/* Small menu */
+#access {
+ float: left;
+ width: 55%;
+}
+.search-form {
+ float: right;
+ text-align: right;
+ width: 43%;
+}
+.menu-toggle {
+ cursor: pointer;
+}
+#access .toggled-on {
+ background-color: #F1F1F1;
+ background-image: -ms-linear-gradient(top,#f9f9f9,#ececec);
+ background-image: -moz-linear-gradient(top,#f9f9f9,#ececec);
+ background-image: -o-linear-gradient(top,#f9f9f9,#ececec);
+ background-image: -webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#ececec));
+ background-image: -webkit-linear-gradient(top,#f9f9f9,#ececec);
+ background-image: linear-gradient(top,#f9f9f9,#ececec);
+ border: 1px solid #e9e9e9;
+ border-bottom-width: 0;
+ box-shadow: 0 1px 0 #fff;
+}
+.main-small-navigation {
+ position: relative;
+ z-index: 99999;
+}
+.main-small-navigation .menu {
+ background: #f9f9f9;
+ border: 1px solid #e9e9e9;
+ position: absolute;
+ width: 100%;
+}
+.main-small-navigation ul li {
+ border-bottom: 1px solid #e9e9e9;
+ padding: 0.5em 0.8em;
+}
+.main-small-navigation ul li:last-of-type {
+ border: none;
+}
+.main-small-navigation ul ul li,
+.main-small-navigation ul ul ul li {
+ border: none;
+ padding-bottom: 0;
+}
+.main-small-navigation a {
+ color: #373737;
+ display: block;
+ font-size: 0.923em;
+ font-weight: bold;
+}
+.main-small-navigation ul {
+ list-style: none;
+ margin: 0;
+ padding: 0.5em 0;
+}
+.main-small-navigation .sub-menu {
+ margin: 0 0 0 15px;
+}
+#access .menu-label {
+ clear: none;
+ font-size: 1.077em;
+ font-weight: bold;
+ line-height: 2.5em;
+ padding-left: 0.8em;
+ text-shadow: 0 1px 0 #fff;
+}
+#access .menu-label:after {
+ color: #999;
+ content: "+";
+ cursor: pointer;
+ font-size: 1em;
+ font-weight: bold;
+ margin-left: 0.5em;
+ width: 18px;
+ height: 18px;
+ text-shadow: 0 1px 0 #fff;
+}
+#access .toggled-on .menu-label:after {
+ content: "-";
+}
+.main-small-navigation .menu {
+ display: none;
+}
+.search-form #s {
+ background: #eee;
+ border: 1px solid #ddd;
+ border-radius: 0;
+ color: #888;
+ font-size: 0.923em;
+ margin-right: 1%;
+ text-shadow: 0 1px 0 #fff;
+ padding: 0.6em;
+ width: 80%;
+}
+
+
+/* =Content
+----------------------------------------------- */
+
+.page-title {
+ color: #666;
+ font-size: 0.769em;
+ font-weight: 500;
+ letter-spacing: 0.1em;
+ line-height: 2.6em;
+ text-transform: uppercase;
+}
+.page-title a {
+ font-size: 0.923em;
+ font-weight: bold;
+ letter-spacing: 0;
+ text-transform: none;
+}
+.hentry,
+.no-results {
+ clear: both;
+ margin: 0 0 1.5em;
+ padding: 0 0 2em;
+ position: relative;
+}
+.hentry {
+ border-bottom: 1px solid #ddd;
+}
+.hentry:last-child,
+.no-results,
+body.singular .hentry {
+ border-bottom: none;
+}
+.blog .sticky .entry-header .entry-meta {
+ clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
+ clip: rect(1px, 1px, 1px, 1px);
+ position: absolute !important;
+}
+.entry-title {
+ clear: both;
+ color: #222;
+ font-size: 1.615em;
+ font-weight: bold;
+ line-height: 1.5em;
+ padding-bottom: .3em;
+ word-wrap: break-word;
+}
+.featured-post .entry-title {
+ font-size: 1.077em;
+}
+.entry-title,
+.entry-title a {
+ color: #222;
+ text-decoration: none;
+}
+.entry-meta {
+ color: #666;
+ clear: both;
+ font-size: 0.923em;
+ line-height: 1.385em;
+ overflow: hidden;
+ padding: 0 0 0.6em 0;
+}
+.entry-meta a {
+ font-weight: bold;
+}
+.entry-content {
+ padding: 0;
+}
+.entry-content h1,
+.entry-content h2,
+.comment-content h1,
+.comment-content h2 {
+ color: #000;
+ font-weight: bold;
+ margin: 0 0 .8125em;
+}
+.entry-content h3,
+.comment-content h3 {
+ font-size: 0.769em;
+ letter-spacing: 0.1em;
+ line-height: 2.6em;
+ text-transform: uppercase;
+}
+.entry-content table,
+.comment-content table {
+ border-bottom: 1px solid #ddd;
+ margin: 0 0 1.625em;
+ width: 100%;
+}
+.entry-content th,
+.comment-content th {
+ color: #666;
+ font-size: 0.769em;
+ font-weight: 500;
+ letter-spacing: 0.1em;
+ line-height: 2.6em;
+ text-transform: uppercase;
+}
+.entry-content td,
+.comment-content td {
+ border-top: 1px solid #ddd;
+ padding: 0.600em 1em 0.600em 0;
+}
+.entry-content #s {
+ width: 75%;
+}
+.comment-content ul,
+.comment-content ol {
+ margin-bottom: 1.625em;
+}
+.comment-content ul ul,
+.comment-content ol ol,
+.comment-content ul ol,
+.comment-content ol ul {
+ margin-bottom: 0;
+}
+dl.gallery-item {
+ margin: 0;
+}
+.page-link {
+ clear: both;
+ display: block;
+ margin: 0 0 1em;
+}
+.page-link a {
+ background: #eee;
+ color: #373737;
+ margin: 0;
+ padding: 0.154em 0.231em;
+ text-decoration: none;
+}
+.page-link span {
+ margin-right: 0.462em;
+}
+.entry-meta .entry-date,
+.entry-meta .entry-gallery {
+ display: block;
+ float: left;
+}
+.entry-meta .comments-link {
+ display: block;
+ float: right;
+}
+.entry-meta .edit-link a {
+ margin-right: .5em;
+}
+.entry-meta .edit-link a,
+.commentlist .edit-link a {
+ background: #eee;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ color: #666;
+ float: right;
+ font-size: 1em;
+ font-weight: normal;
+ line-height: 1.5em;
+ text-decoration: none;
+ padding: 0 0.615em;
+}
+.entry-content .edit-link {
+ clear: both;
+ display: block;
+}
+
+/* Images */
+.entry-content img,
+.comment-content img,
+.widget img {
+ display: block;
+ height: auto;
+ margin: 0 auto;
+ max-width: 100%; /* Fluid images for posts, comments, and widgets */
+}
+#content .gallery-columns-3 .gallery-item img,
+#content .gallery-columns-4 .gallery-item img,
+#content .gallery-columns-2 .gallery-item img {
+ width: 100%;
+ height: auto;
+}
+img[class*="align"],
+img[class*="wp-image-"],
+img[class*="attachment-"] {
+ height: auto; /* Make sure images with WordPress-added height and width attributes are scaled correctly */
+}
+img.size-full,
+img.size-large {
+ max-width: 100%;
+ width: auto; /* Prevent stretching of full-size and large-size images with height and width attributes in IE8 */
+ height: auto; /* Make sure images with WordPress-added height and width attributes are scaled correctly */
+}
+.entry-content img.wp-smiley {
+ border: none;
+ margin-bottom: 0;
+ margin-top: 0;
+ padding: 0;
+}
+img.alignleft,
+img.alignright,
+img.aligncenter {
+ margin-bottom: 1.625em;
+}
+p img,
+.wp-caption {
+ margin-top: 0.4em;
+}
+.wp-caption {
+ max-width: 96%;
+}
+.wp-caption img {
+ display: block;
+ margin: 0 auto;
+ max-width: 98%;
+}
+.wp-caption .wp-caption-text,
+.gallery-caption {
+ color: #666;
+ font-family: Georgia, serif;
+ font-size: 0.923em;
+}
+.wp-caption .wp-caption-text {
+ margin-bottom: 0.6em;
+ padding: 0.833em 0 0.417em 0;
+ position: relative;
+}
+#content .gallery {
+ margin: 0 auto 1.625em;
+}
+#content .gallery a img {
+ border: none;
+}
+#content .gallery-columns-3 .gallery-item {
+ width: 31%;
+ padding-right: 2%;
+}
+#content .gallery-columns-4 .gallery-item {
+ width: 23%;
+ padding-right: 2%;
+}
+#content .gallery-columns-2 .gallery-item {
+ width: 45%;
+ padding-right: 4%;
+}
+
+
+/* Make sure embeds and iframes fit their containers */
+embed,
+iframe,
+object {
+ max-width: 100%;
+}
+
+/* Password Protected Posts */
+.post-password-required .entry-header .comments-link {
+ margin: 1.625em 0 0;
+}
+.post-password-required input[type=password] {
+ margin: 0.8125em 0;
+}
+.post-password-required input[type=password]:focus {
+ background: #f7f7f7;
+}
+
+
+/*
+Post Formats Headings
+To hide the headings, display: none the ".entry-header .entry-format" selector,
+and remove the padding rules below.
+*/
+.entry-header .entry-format {
+ color: #666;
+ font-size: 10px;
+ font-weight: 500;
+ letter-spacing: 0.1em;
+ line-height: 2.6em;
+ position: absolute;
+ text-transform: uppercase;
+ top: -5px;
+}
+.entry-header hgroup .entry-title {
+ padding-top: 0.8em;
+}
+
+/* Singular content styles for Posts and Pages */
+.singular .hentry {
+ padding: 1.625em 0 0;
+ position: relative;
+}
+.page .hentry {
+ padding-bottom: .7em;
+}
+.singular .entry-meta .edit-link a {
+ bottom: auto;
+ left: 0;
+ position: absolute;
+ right: auto;
+ top: 40px;
+}
+.single-format-gallery .hentry {
+ margin-bottom: 0;
+}
+.singular #author-info {
+ margin: 2.2em -8.8% 0;
+ padding: 1.538em 8.8%;
+}
+
+
+/* =Gallery Posts
+----------------------------------------------- */
+
+#content .gallery {
+ margin-bottom: 0;
+}
+.format-gallery img {
+ margin: 0;
+}
+.format-gallery .gallery-large {
+ line-height: 1.2em;
+ margin: 0;
+ width: 100%;
+}
+.format-gallery .gallery-thumbs-2,
+ .format-gallery .gallery-thumbs-3 {
+ overflow: hidden;
+ width: 100%;
+}
+.format-gallery .gallery-thumbs-2 img {
+ margin-right: 0.3%;
+ max-width: 48%;
+}
+.format-gallery .gallery-thumbs-3 img {
+ float: left;
+ margin-left: 0.2%;
+ max-width: 33%;
+}
+.format-gallery .gallery-large,
+.format-gallery .gallery-thumbs-2 img,
+ .format-gallery .gallery-thumbs-3 img {
+ display: inline-block;
+}
+.format-gallery .gallery-thumbs-3 .gallery-thumb-1 img {
+ margin: 0;
+}
+.gallery-info {
+ margin-top: 1.3em;
+}
+
+/* =Quote Posts
+----------------------------------------------- */
+
+.format-quote blockquote {
+ color: #555;
+ font-size: 1.308em;
+ margin: 0;
+}
+
+/* =error404
+----------------------------------------------- */
+
+.error404 #main #searchform {
+ background: #f9f9f9;
+ border: 1px solid #ddd;
+ border-width: 1px 0;
+ margin: 0 -8.9% 1.625em;
+ overflow: hidden;
+ padding: 1.625em 8.9%;
+}
+.error404 #main #s {
+ width: 95%;
+}
+.error404 .widgettitle {
+ font-size: 0.769em;
+ letter-spacing: 0.1em;
+ line-height: 2.6em;
+ text-transform: uppercase;
+}
+
+
+/* =Attachments
+----------------------------------------------- */
+
+.image-attachment div.attachment {
+ background: #f9f9f9;
+ border: 1px solid #ddd;
+ border-width: 1px 0;
+ margin: 0 -8.9% 1.625em;
+ overflow: hidden;
+ padding: 1.625em 1.625em 0;
+ text-align: center;
+}
+.image-attachment div.attachment img {
+ display: block;
+ height: auto;
+ margin: 0 auto 1.625em;
+ max-width: 100%;
+}
+.image-attachment div.attachment a img {
+ border-color: #f9f9f9;
+}
+.image-attachment div.attachment a:focus img,
+.image-attachment div.attachment a:hover img,
+.image-attachment div.attachment a:active img {
+ border-color: #ddd;
+ background: #fff;
+}
+.image-attachment .entry-caption p {
+ font-size: 0.769em;
+ letter-spacing: 0.1em;
+ line-height: 2.6em;
+ margin: 0 0 2.6em;
+ text-transform: uppercase;
+}
+
+
+/* =Navigation
+-------------------------------------------------------------- */
+
+#content nav {
+ clear: both;
+}
+#nav-below,
+#nav-single {
+ margin: 0 auto 0.6em;
+ overflow: hidden;
+ width: 100%;
+}
+.nav-previous {
+ float: left;
+ width: 48%;
+}
+.nav-next {
+ float: right;
+ width: 46%;
+}
+#nav-single {
+ display: block;
+ position: static;
+}
+#nav-single .nav-previous {
+ margin-left: 0;
+ width: 50%;
+}
+#nav-single .nav-next {
+ margin-right: 0;
+ width: 49%;
+}
+.nav-previous a,
+.nav-next a {
+ background: #00a4bc;
+ color: #fff;
+ display: block;
+ font-size: 1.231em;
+ font-weight: bold;
+ padding: 1.2em 0;
+ text-align: center;
+ width: 100%;
+}
+#content nav .meta-nav {
+ font-weight: normal;
+}
+#jp-post-flair {
+ margin: 1em auto !important;
+}
+
+
+
+/* =Widget Area & Widgets
+----------------------------------------------- */
+
+.widget-area {
+ background: #f9f9f9;
+ border-top: 1px solid #ddd;
+ color: #666;
+ font-size: 0.923em;
+ padding: .6em 0.8em;
+}
+.widget {
+ border-bottom: 1px solid #ddd;
+ clear: both;
+ margin: 0;
+ padding: 1.625em 0;
+}
+.widget:last-of-type {
+ border: 0;
+}
+.widget-title {
+ color: #666;
+ font-size: 0.833em;
+ letter-spacing: 0.1em;
+ line-height: 2em;
+ margin-bottom: 0.5em;
+ text-transform: uppercase;
+}
+.widget-title a {
+ color: #666;
+}
+.widget ul {
+ margin-bottom: 0;
+}
+.widget ul ul {
+ margin-left: 1.5em;
+}
+.widget ul li {
+ color: #777;
+}
+.widget a {
+ font-weight: bold;
+ text-decoration: none;
+}
+.widget a:hover,
+.widget a:focus,
+.widget a:active {
+ text-decoration: underline;
+}
+
+/* Search Widget */
+.widget_search #s {
+ width: 77%;
+}
+.widget_search #searchsubmit {
+ background: #ddd;
+ border: 1px solid #ccc;
+ -webkit-box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09);
+ -moz-box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09);
+ box-shadow: inset 0px -1px 1px rgba(0, 0, 0, 0.09);
+ color: #888;
+ line-height: 2.083em;
+ position: relative;
+ top: -2px;
+}
+.widget_search #searchsubmit:active {
+ background: #00a4bc;
+ border-color: #0861a5;
+ -webkit-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.1);
+ color: #bfddf3;
+}
+
+/* Twitter */
+.tweets {
+ margin-left: 0;
+}
+.widget_twitter li {
+ list-style-type: none;
+ margin-bottom: 1.167em;
+}
+.widget_twitter .timesince {
+ font-size: 0.917em;
+ font-weight: normal;
+ text-align: right;
+}
+
+/* RSS-Related Widgets */
+.widget_rss img {
+ display: inline-block;
+ margin: 0;
+ vertical-align: middle;
+}
+.widget_rss .rss-date {
+ font-size: 90%;
+}
+.widget_rss_links img,
+.widget_rss_links a:hover img,
+.widget_rss_links a:focus img,
+.widget_rss_links a:active img {
+ background: transparent;
+ border: none;
+ padding: 0;
+}
+
+/* Calendar Widget */
+.widget_calendar #wp-calendar {
+ color: #555;
+ width: 95%;
+ text-align: center;
+}
+.widget_calendar #wp-calendar caption,
+.widget_calendar #wp-calendar td,
+.widget_calendar #wp-calendar th {
+ text-align: center;
+}
+.widget_calendar #wp-calendar caption {
+ font-size: 11px;
+ font-weight: 500;
+ padding: 5px 0 3px 0;
+ text-transform: uppercase;
+}
+.widget_calendar #wp-calendar th {
+ background: #f4f4f4;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ font-weight: bold;
+}
+.widget_calendar #wp-calendar tfoot td {
+ background: #f4f4f4;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+}
+
+/* Recent Comments */
+.widget_recent_comments td.recentcommentstexttop,
+.widget_recent_comments td.recentcommentstextend {
+ vertical-align: top;
+}
+
+/* Authors Widget */
+.widget_authors ul {
+ margin-left: 0;
+}
+.widget_authors li {
+ background: none !important;
+ overflow: hidden;
+}
+.widget_authors ul ul li {
+ overflow: hidden;
+}
+.widget_authors img {
+ float: left;
+ padding-right: 0.833em;
+ vertical-align: text-top;
+}
+
+/*Flickr Widget */
+.widget_flickr #flickr_badge_wrapper {
+ background-color: transparent;
+ border: none;
+}
+#flickr_badge_uber_wrapper a:hover,
+#flickr_badge_uber_wrapper a:link,
+#flickr_badge_uber_wrapper a:active,
+#flickr_badge_uber_wrapper a:visited {
+ color: #00a4bc !important;
+}
+
+
+/* =Comments
+----------------------------------------------- */
+
+#comments {
+ margin-top: 1.5em;
+}
+#comments-title {
+ color: #000;
+ font-size: 1.154em;
+ font-weight: bold;
+ line-height: 1em;
+ padding: 1em 0;
+}
+#comment-nav-below {
+ overflow: hidden;
+}
+.nopassword,
+.nocomments {
+ color: #aaa;
+ font-size: 1.846em;
+ font-weight: 100;
+ margin: 2em 0;
+ text-align: center;
+}
+.commentlist {
+ list-style: none;
+ margin: 0 auto;
+ width: 100%;
+}
+.commentlist > li.comment {
+ background: #f6f6f6;
+ border: 1px solid #ddd;
+ border-width: 1px 0;
+ margin: 0 -2.5% 0.5em;
+ padding: .8em;
+ position: relative;
+}
+.commentlist > li.comment,
+.commentlist .pingback {
+ width: auto;
+}
+
+/* Reblogs */
+.commentlist > li.reblog {
+ border: 1px solid #eee;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ margin: 0 0 1.625em;
+ padding: 1.625em;
+ position: relative;
+}
+.commentlist .reblog .comment-meta {
+ display: none;
+}
+.commentlist .reblog p:first-child {
+ color: #999;
+ font-size: 1em;
+}
+.commentlist .reblog p:first-child a {
+ font-weight: bold;
+}
+.commentlist .pingback,
+.commentlist .pingback p {
+ margin: 0 0 .8em;
+}
+.commentlist .children {
+ list-style: none;
+ margin: 0;
+}
+.commentlist .children li.comment {
+ background: #fff;
+ border-left: 1px solid #ddd;
+ -moz-border-radius: 0 3px 3px 0;
+ border-radius: 0 3px 3px 0;
+ margin: 1.625em 0 0;
+ padding: 1.625em;
+ position: relative;
+}
+.commentlist .children li.comment .fn {
+ display: block;
+}
+.comment-meta .fn {
+ font-style: normal;
+}
+.comment-meta,
+.comment-content {
+ margin-left: 4em;
+}
+.comment-meta {
+ color: #666;
+ font-size: 0.923em;
+}
+.comment-content {
+ padding-top: 0.2em;
+}
+.commentlist .children li.comment .comment-meta {
+ line-height: 1.625em;
+ margin-left: 3.462em;
+}
+.commentlist .children li.comment .comment-content {
+ margin: 1.625em 0 0;
+}
+.comment-meta a {
+ font-weight: bold;
+}
+.comment-meta a:focus,
+.comment-meta a:active,
+.comment-meta a:hover {
+}
+.commentlist .avatar {
+ background: transparent;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ display: block;
+ padding: 0;
+ position: absolute;
+ left: 13px;
+ top: 13px;
+}
+.commentlist .children .avatar {
+ background: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+ left: 2.2em;
+ padding: 0;
+ position: absolute;
+ top: 2.2em;
+}
+a.comment-reply-link {
+ background: #eee;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ color: #666;
+ display: inline-block;
+ font-size: 0.923em;
+ padding: 0 0.615em;
+ text-decoration: none;
+}
+a.comment-reply-link:hover,
+a.comment-reply-link:focus,
+a.comment-reply-link:active {
+ background: #888;
+ color: #fff;
+}
+a.comment-reply-link > span {
+ display: inline-block;
+ position: relative;
+ top: -1px;
+}
+
+/* Post author highlighting */
+.commentlist > li.bypostauthor {
+ background: #ddd;
+ border-color: #d3d3d3;
+}
+.commentlist > li.bypostauthor .comment-meta {
+ color: #575757;
+}
+.commentlist > li.bypostauthor .comment-meta a:focus,
+.commentlist > li.bypostauthor .comment-meta a:active,
+.commentlist > li.bypostauthor .comment-meta a:hover {
+}
+/* Post Author threaded comments */
+.commentlist .children > li.bypostauthor {
+ background: #ddd;
+ border-color: #d3d3d3;
+}
+
+/* Comment Form */
+#respond {
+ margin: 0 auto 1.625em;
+ width: auto;
+}
+#respond input[type="text"],
+#respond textarea {
+ background: #fff;
+ position: relative;
+ padding: 0.615em;
+}
+#respond .comment-form-author,
+#respond .comment-form-email,
+#respond .comment-form-url,
+#respond .comment-form-comment {
+ position: relative;
+}
+#respond .comment-form-author label,
+#respond .comment-form-email label,
+#respond .comment-form-url label,
+#respond .comment-form-comment label {
+ color: #555;
+ display: inline-block;
+ font-size: 1.077em;
+ font-weight: bold;
+ padding: 0.154em 0 0;
+ position: relative;
+}
+#respond textarea {
+ resize: vertical;
+ width: 95%;
+}
+#respond .comment-form-author .required,
+#respond .comment-form-email .required {
+ color: #bd3500;
+ font-size: 1.692em;
+ font-weight: bold;
+ left: 95%;
+ position: absolute;
+ top: 45px;
+ z-index: 1;
+}
+#respond .comment-notes,
+#respond .logged-in-as {
+ font-size: 0.8em;
+ color: #666;
+}
+#respond p {
+ margin: 0.769em 0 0;
+}
+#respond .form-submit {
+ margin: 0;
+}
+#respond input#submit {
+ background: #00a4bc;
+ border: none;
+ border-radius: 3px;
+ box-shadow: 0px 1px 2px rgba(0,0,0,0.3);
+ color: #fff;
+ cursor: pointer;
+ font-size: 1em;
+ font-weight: bold;
+ margin: 0.462em 0;
+ padding: 1em;
+ left: 30px;
+ text-shadow: 0 -1px 0 rgba(0,0,0,0.3);
+}
+#respond input#submit:active {
+ background: #00879c;
+ color: #fff;
+}
+#respond #cancel-comment-reply-link {
+ color: #666;
+ text-decoration: none;
+}
+#respond .logged-in-as a:hover,
+#respond #cancel-comment-reply-link:hover {
+ text-decoration: underline;
+}
+.commentlist #respond {
+ margin: 1.625em 0 0;
+ width: auto;
+}
+#respond .comment-subscription-form {
+ margin: 6px 0;
+}
+#reply-title {
+ color: #373737;
+ font-size: 1.5em;
+ font-weight: bold;
+ line-height: 0.733em;
+}
+.comment #reply-title {
+ margin-top: 1em;
+}
+#cancel-comment-reply-link {
+ color: #888;
+ display: block;
+ font-size: 0.923em;
+ font-weight: normal;
+ line-height: 2.2em;
+ text-decoration: none;
+ text-transform: uppercase;
+}
+#cancel-comment-reply-link:focus,
+#cancel-comment-reply-link:active,
+#cancel-comment-reply-link:hover {
+ color: #ff4b33;
+}
+#respond label {
+ line-height: 2.2em;
+}
+#respond input[type=text] {
+ display: block;
+ height: 1.846em;
+ width: 95%;
+}
+#respond p {
+ font-size: 0.923em;
+}
+p.comment-form-comment {
+ margin: 0;
+}
+.form-allowed-tags {
+ display: none;
+}
+
+
+/* =Footer
+----------------------------------------------- */
+
+#colophon {
+ background: #434343;
+ clear: both;
+ margin-bottom: -2em;
+ padding-bottom: 1em;
+}
+
+/* Site Generator Line */
+#site-generator {
+ background: #434343;
+ border-top: 1px solid #ddd;
+ color: #fff;
+ font-size: 0.923em;
+ line-height: 2.2em;
+ padding: 2.2em 0.5em;
+ text-align: center;
+}
+#site-generator a {
+ color: #00a4bc;
+ font-weight: bold;
+}
+#site-generator .sep {
+ color: transparent;
+ display: inline-block;
+ height: 16px;
+ line-height: 1.231em;
+ margin: 0 0.538em;
+ text-indent: 40px; /* Push the separator just out of the way */
+ width: 3.077em;
+}
+
+
+/* =WP.com
+----------------------------------------------- */
+
+.video-player {
+ max-width: 100% !important;
+}
+.videopress-placeholder,
+.video-player img {
+ max-width: 100% !important;
+ height: auto !important;
+}
+.syntaxhighlighter {
+ overflow: auto;
+}
+.single #content #wp-likebox,
+.page #content #wp-likebox {
+ display: block;
+}
+#wpl-mustlogin {
+width: 240px !important;
+margin-left: -60px !important;
+}
+
+/* WP.com comment form */
+#comments #respond {
+ max-width: 75%;
+ margin: 0 auto 15px;
+}
+.content #comments #respond,
+#comments .commentlist #respond {
+ max-width: 100%;
+}
+#respond textarea {
+ text-indent: 0;
+}
+.singular #content .wpl-likebox {
+ width: 100%;
+}
+#comments #respond {
+ max-width: 100%;
+}
+#wpstats {
+ display: block;
+ margin: -1.8em auto 0;
+}
+#wpstats2 {
+ display: none;
+}
+
+/* Adjust the width of PollDaddy polls */
+.PDS_Poll .pds-box {
+ width: 99% !important;
+}
+
+
+/* Remove margins and padding on outer containers for super-tiny screens */
+@media only screen and (min-device-width: 100px) and (max-device-width: 300px) {
+ #wrapper {
+ margin: 0;
+ padding: 0;
+ }
+ #access {
+ padding: 0.385em 0;
+ }
+ #page,
+ .widget-area,
+ #main {
+ width: 100%;
+ margin: 0;
+ }
+ .widget-area {
+ padding: 0.417em;
+ }
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/mobile-push.php b/plugins/jetpack/modules/mobile-push.php
new file mode 100644
index 00000000..8981348b
--- /dev/null
+++ b/plugins/jetpack/modules/mobile-push.php
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Module Name: Mobile Push Notifications
+ * Module Description: Receive notifications on your Apple device.
+ * Sort Order: 100
+ * First Introduced: 1.9
+ */
+
+Jetpack_Sync::sync_comments( __FILE__, array(
+ 'comment_stati' => array( 'approved', 'unapproved' ),
+) );
diff --git a/plugins/jetpack/modules/module-extras.php b/plugins/jetpack/modules/module-extras.php
new file mode 100644
index 00000000..5013f7cc
--- /dev/null
+++ b/plugins/jetpack/modules/module-extras.php
@@ -0,0 +1,58 @@
+<?php
+/*
+ * Load module code that is needed even when a module isn't active.
+ * For example, if a module shouldn't be activatable unless certain conditions are met, the code belongs in this file.
+ */
+
+/**
+ * INFINITE SCROLL
+ */
+
+/**
+ * Load theme's infinite scroll annotation file, if present in the IS plugin.
+ * The `setup_theme` action is used because the annotation files should be using `after_setup_theme` to register support for IS.
+ *
+ * As released in Jetpack 2.0, a child theme's parent wasn't checked for in the plugin's bundled support, hence the convoluted way the parent is checked for now.
+ *
+ * @uses is_admin, wp_get_theme, get_theme, get_current_theme, apply_filters
+ * @action setup_theme
+ * @return null
+ */
+function jetpack_load_infinite_scroll_annotation() {
+ if ( is_admin() && isset( $_GET['page'] ) && 'jetpack' == $_GET['page'] ) {
+ $theme = function_exists( 'wp_get_theme' ) ? wp_get_theme() : get_theme( get_current_theme() );
+
+ if ( ! is_a( $theme, 'WP_Theme' ) && ! is_array( $theme ) )
+ return;
+
+ $customization_file = apply_filters( 'infinite_scroll_customization_file', dirname( __FILE__ ) . "/infinite-scroll/themes/{$theme['Stylesheet']}.php", $theme['Stylesheet'] );
+
+ if ( is_readable( $customization_file ) ) {
+ require_once( $customization_file );
+ }
+ elseif ( ! empty( $theme['Template'] ) ) {
+ $customization_file = dirname( __FILE__ ) . "/infinite-scroll/themes/{$theme['Template']}.php";
+
+ if ( is_readable( $customization_file ) )
+ require_once( $customization_file );
+ }
+ }
+}
+add_action( 'setup_theme', 'jetpack_load_infinite_scroll_annotation' );
+
+/**
+ * Prevent IS from being activated if theme doesn't support it
+ *
+ * @param bool $can_activate
+ * @filter jetpack_can_activate_infinite-scroll
+ * @return bool
+ */
+function jetpack_can_activate_infinite_scroll( $can_activate ) {
+ return (bool) current_theme_supports( 'infinite-scroll' );
+}
+add_filter( 'jetpack_can_activate_infinite-scroll', 'jetpack_can_activate_infinite_scroll' );
+
+// Happy Holidays!
+require_once( dirname( __FILE__ ) . '/holiday-snow.php' );
+
+require_once( dirname( __FILE__ ) . '/featured-content/featured-content.php' );
diff --git a/plugins/jetpack/modules/module-info.php b/plugins/jetpack/modules/module-info.php
index d1038208..218a9e80 100644
--- a/plugins/jetpack/modules/module-info.php
+++ b/plugins/jetpack/modules/module-info.php
@@ -42,7 +42,7 @@ function vaultpress_jetpack_load_more_link() {
$vaultpress_url = 'http://vaultpress.com/jetpack/';
}
- echo '<a class="button more-info-link" href="' . $vaultpress_url . '">' . __( "Learn More", 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="' . $vaultpress_url . '">' . __( "Learn More", 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_vaultpress', 'vaultpress_jetpack_load_more_link' );
@@ -78,7 +78,7 @@ function grofiles_more_info_connected() { ?>
add_action( 'jetpack_module_more_info_connected_gravatar-hovercards', 'grofiles_more_info_connected' );
function grofiles_load_more_link() {
- echo '<a class="button more-info-link" href="http://blog.gravatar.com/2010/10/06/gravatar-hovercards-on-wordpress-com/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://blog.gravatar.com/2010/10/06/gravatar-hovercards-on-wordpress-com/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_gravatar-hovercards', 'grofiles_load_more_link' );
@@ -112,11 +112,8 @@ function jetpack_shortcodes_more_info_connected() { ?>
'audio' => 'http://support.wordpress.com/audio/',
'blip.tv' => 'http://support.wordpress.com/videos/bliptv/',
'dailymotion' => 'http://support.wordpress.com/videos/dailymotion/',
- 'digg' => 'http://support.wordpress.com/digg/',
'flickr' => 'http://support.wordpress.com/videos/flickr-video/',
- 'googlevideo' => 'http://support.wordpress.com/videos/google-video/',
'scribd' => 'http://support.wordpress.com/scribd/',
- 'slide' => 'http://support.wordpress.com/slideshows/slide/',
'slideshare' => 'http://support.wordpress.com/slideshows/slideshare/',
'soundcloud' => 'http://support.wordpress.com/audio/soundcloud-audio-player/',
'vimeo' => 'http://support.wordpress.com/videos/vimeo/',
@@ -138,7 +135,7 @@ function jetpack_shortcodes_more_info_connected() { ?>
add_action( 'jetpack_module_more_info_connected_shortcodes', 'jetpack_shortcodes_more_info_connected' );
function jetpack_shortcodes_load_more_link( $description ) {
- echo '<a class="button more-info-link" href="http://en.support.wordpress.com/shortcodes/">' . esc_html__( 'Learn More' , 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://en.support.wordpress.com/shortcodes/">' . esc_html__( 'Learn More' , 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_shortcodes', 'jetpack_shortcodes_load_more_link' );
@@ -173,7 +170,7 @@ function wpme_more_info_connected() { ?>
add_action( 'jetpack_module_more_info_connected_shortlinks', 'wpme_more_info_connected' );
function wpme_load_more_link( $description ) {
- echo '<a class="button more-info-link" href="http://wp.me/sf2B5-shorten">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://wp.me/sf2B5-shorten">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_shortlinks', 'wpme_load_more_link' );
@@ -207,10 +204,73 @@ function stats_more_info_connected() { ?>
add_action( 'jetpack_module_more_info_connected_stats', 'stats_more_info_connected' );
function stats_load_more_link( $description ) {
- echo '<a class="button more-info-link" href="http://en.support.wordpress.com/stats/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://en.support.wordpress.com/stats/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_stats', 'stats_load_more_link' );
+// Publicize
+function publicize_more_info() { ?>
+ <div class="jp-info-img">
+ <a href="http://en.support.wordpress.com/publicize/">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/publicize.png' ) ?>" alt="<?php esc_attr_e( 'Publicize', 'jetpack' ) ?>" width="328" height="123" />
+ </a>
+ </div>
+
+ <h4><?php esc_html_e( 'Publicize' , 'jetpack' ); ?></h4>
+ <p><?php esc_html_e( 'Publicize allows you to connect your blog to popular social networking sites and automatically share new posts with your friends. You can make a connection for just yourself or for all users on your blog.', 'jetpack' ) ?></p>
+ <p><?php esc_html_e( 'Publicize allows you to share your posts on Facebook, Twitter, Tumblr, Yahoo!, and Linkedin.', 'jetpack' ); ?></p>
+
+<?php if ( 'jetpack_module_more_info_connected_publicize' == current_filter() ) : ?>
+
+ <p><?php printf( __( 'Manage your <a href="%s">Publicize settings</a>.', 'jetpack' ), menu_page_url( 'sharing', false ) ); ?>
+
+<?php endif; ?>
+
+ <p>&rarr; <a href="http://jetpack.me/support/publicize/"><?php esc_html_e( 'More information on using Publicize.', 'jetpack' ); ?></a></p>
+<?php
+}
+
+add_action( 'jetpack_module_more_info_publicize', 'publicize_more_info' );
+add_action( 'jetpack_module_more_info_connected_publicize', 'publicize_more_info' );
+
+function publicize_load_more_link( $description ) {
+ echo '<a class="button-secondary more-info-link" href="http://jetpack.me/support/publicize/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+}
+add_filter( 'jetpack_learn_more_button_publicize', 'publicize_load_more_link' );
+
+// Notifications
+function notes_more_info() { ?>
+ <div class="jp-info-img">
+ <a href="http://support.wordpress.com/notifications/">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/notes.png' ) ?>" alt="<?php esc_attr_e( 'Notifications', 'jetpack' ) ?>" width="300" height="150" />
+ </a>
+ </div>
+
+ <h4><?php esc_html_e( 'Notifications' , 'jetpack' ); ?></h4>
+ <p><?php esc_html_e( 'Keep up with the latest happenings on all your WordPress sites and interact with other WordPress.com users.', 'jetpack' ) ?></p>
+<?php
+}
+add_action( 'jetpack_module_more_info_notes', 'notes_more_info' );
+
+function notes_more_info_connected() { ?>
+ <div class="jp-info-img">
+ <a href="http://support.wordpress.com/notifications/">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/notes.png' ) ?>" alt="<?php esc_attr_e( 'Notifications', 'jetpack' ) ?>" width="300" height="150" />
+ </a>
+ </div>
+
+ <h4><?php esc_html_e( 'Notifications' , 'jetpack' ); ?></h4>
+ <p><?php esc_html_e( 'Keep up with the latest happenings on all your WordPress sites and interact with other WordPress.com users.', 'jetpack' ) ?></p>
+ <p><?php printf( __( 'You can view your notifications in the Toolbar and <a href="%s">on WordPress.com</a>.', 'jetpack' ), 'http://wordpress.com/#!/notifications/' ); ?></p>
+<?php
+}
+add_filter( 'jetpack_module_more_info_connected_notes', 'notes_more_info_connected' );
+
+function notes_load_more_link( $description ) {
+ echo '<a class="button-secondary more-info-link" href="http://support.wordpress.com/notifications/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+}
+add_filter( 'jetpack_learn_more_button_notes', 'notes_load_more_link' );
+
// LaTeX
function latex_more_info() { ?>
@@ -220,9 +280,9 @@ function latex_more_info() { ?>
</a>
</div>
- <h4><img src="http://l.wordpress.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -27%" /> Makes Beautiful Math</h4>
- <p><?php printf( esc_html__( '%s is a powerful markup language for writing complex mathematical equations, formulas, etc.', 'jetpack' ), '<a href="http://www.latex-project.org/" target="_blank"><img src="http://l.wordpress.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" /></a>' ); ?></p>
- <p><?php printf( esc_html__( 'Jetpack combines the power of %s and the simplicity of WordPress to give you the ultimate in math blogging platforms.', 'jetpack' ), '<img src="http://l.wordpress.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" />' ); ?></p>
+ <h4><img src="//s0.wp.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -27%" /> Makes Beautiful Math</h4>
+ <p><?php printf( esc_html__( '%s is a powerful markup language for writing complex mathematical equations, formulas, etc.', 'jetpack' ), '<a href="http://www.latex-project.org/" target="_blank"><img src="//s0.wp.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" /></a>' ); ?></p>
+ <p><?php printf( esc_html__( 'Jetpack combines the power of %s and the simplicity of WordPress to give you the ultimate in math blogging platforms.', 'jetpack' ), '<img src="//s0.wp.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" />' ); ?></p>
<p><?php esc_html_e( 'Wow, that sounds nerdy.', 'jetpack' ) ?></p>
<?php
}
@@ -235,15 +295,15 @@ function latex_more_info_connected() { ?>
</a>
</div>
- <h4><img src="http://l.wordpress.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -27%;" /> Makes Beautiful Math</h4>
- <p><?php printf( esc_html__( '%s is a powerful markup language for writing complex mathematical equations, formulas, etc.', 'jetpack' ), '<a href="http://www.latex-project.org/" target="_blank"><img src="http://l.wordpress.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" /></a>' ); ?></p>
- <p><?php printf( __( 'Use <code>$latex your latex code here$</code> or <code>[latex]your latex code here[/latex]</code> to include %s in your posts and comments. There are <a href="%s" target="_blank">all sorts of options</a> available.', 'jetpack' ), '<img src="http://l.wordpress.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" />', 'http://support.wordpress.com/latex/' ); ?></p>
+ <h4><img src="//s0.wp.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -27%;" /> Makes Beautiful Math</h4>
+ <p><?php printf( esc_html__( '%s is a powerful markup language for writing complex mathematical equations, formulas, etc.', 'jetpack' ), '<a href="http://www.latex-project.org/" target="_blank"><img src="//s0.wp.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" /></a>' ); ?></p>
+ <p><?php printf( __( 'Use <code>$latex your latex code here$</code> or <code>[latex]your latex code here[/latex]</code> to include %s in your posts and comments. There are <a href="%s" target="_blank">all sorts of options</a> available.', 'jetpack' ), '<img src="//s0.wp.com/latex.php?latex=%5CLaTeX&amp;bg=transparent&amp;fg=000&amp;s=-1" alt="LaTeX logo" title="LaTeX" style="vertical-align: -25%" />', 'http://support.wordpress.com/latex/' ); ?></p>
<?php
}
add_action( 'jetpack_module_more_info_connected_latex', 'latex_more_info_connected' );
function latex_load_more_link( $description ) {
- echo '<a class="button more-info-link" href="http://support.wordpress.com/latex/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://support.wordpress.com/latex/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_latex', 'latex_load_more_link' );
@@ -294,7 +354,7 @@ function sharedaddy_more_info_connected() { ?>
add_action( 'jetpack_module_more_info_connected_sharedaddy', 'sharedaddy_more_info_connected' );
function sharedaddy_load_more_link( $description ) {
- echo '<a class="button more-info-link" href="http://support.wordpress.com/sharing/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://support.wordpress.com/sharing/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_sharedaddy', 'sharedaddy_load_more_link' );
@@ -316,7 +376,7 @@ function jpatd_more_info() { ?>
add_action( 'jetpack_module_more_info_after-the-deadline', 'jpatd_more_info' );
function jpatd_load_more_link( $description ) {
- echo '<a class="button more-info-link" href="http://en.support.wordpress.com/proofreading/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://en.support.wordpress.com/proofreading/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_after-the-deadline', 'jpatd_load_more_link' );
@@ -328,7 +388,7 @@ function jetpack_widgets_more_info() { ?>
</div>
<h4><?php esc_html_e( 'Extra Sidebar Widgets' , 'jetpack' ); ?></h4>
-
+
<p><strong><?php esc_html_e( 'The RSS Links Widget ', 'jetpack' ); ?></strong> <?php esc_html_e( "allows you to add links to your blog&#8217;s post and comment RSS feeds in your sidebar. This makes it easy for your readers to stay updated when you post new content or receive new comments.", 'jetpack' ) ?></p>
<p><strong><?php esc_html_e( 'The Twitter Widget ', 'jetpack' ); ?></strong> <?php esc_html_e( "shows your latest tweets within a sidebar on your theme. It&#8217;s an easy way to add more activity to your site. There are also a number of customization options.", 'jetpack' ) ?> <strong><?php esc_html_e( 'The Facebook Like Box Widget ', 'jetpack' ); ?></strong> <?php esc_html_e( "shows your Facebook Like Box within a sidebar on your theme. It&#8217;s a great way to let your readers show their support.", 'jetpack' ) ?> <strong><?php esc_html_e( 'The Image Widget ', 'jetpack' ); ?></strong><?php esc_html_e( "allows you to easily add images to widget areas in your theme. It&#8217;s an easy way to add more visual interest to your site.", 'jetpack' ) ?></p>
@@ -354,7 +414,7 @@ function jetpack_widgets_more_info_connected() { ?>
add_action( 'jetpack_module_more_info_connected_widgets', 'jetpack_widgets_more_info_connected' );
function jetpack_widgets_load_more_link( $description ) {
- echo '<a class="button more-info-link" href="http://en.support.wordpress.com/widgets/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://en.support.wordpress.com/widgets/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_filter( 'jetpack_learn_more_button_widgets', 'jetpack_widgets_load_more_link' );
@@ -373,12 +433,13 @@ function jetpack_subscriptions_more_info() { ?>
if ( 'jetpack_module_more_info_connected_subscriptions' == current_filter() )
printf( '<p>' . __( 'To use the Subscriptions widget, go to Appearance &#8594; <a href="%s">Widgets</a>. Drag the widget labeled &#8220;Blog Subscriptions (Jetpack)&#8221; into one of your sidebars and configure away.', 'jetpack' ) . '</p>', admin_url( 'widgets.php' ) );
+ printf( '<p>' . __( 'You can also make changes to your Subscription settings at the bottom of the <a href="%s">Discussion Settings</a> page.', 'jetpack' ) . '</p>', admin_url( 'options-discussion.php#jetpack-subscriptions-settings' ) );
}
add_action( 'jetpack_module_more_info_subscriptions', 'jetpack_subscriptions_more_info' );
add_action( 'jetpack_module_more_info_connected_subscriptions', 'jetpack_subscriptions_more_info' );
function jetpack_subscriptions_load_more_link() {
- echo '<a class="button more-info-link" href="http://en.support.wordpress.com/following/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://en.support.wordpress.com/following/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_action( 'jetpack_learn_more_button_subscriptions', 'jetpack_subscriptions_load_more_link' );
@@ -396,13 +457,32 @@ add_action( 'jetpack_module_more_info_enhanced-distribution', 'jetpack_enhanced_
add_action( 'jetpack_module_more_info_connected_enhanced-distribution', 'jetpack_enhanced_distribution_more_info' );
function jetpack_enhanced_distribution_more_link() {
- echo '<a class="button more-info-link" href="http://en.wordpress.com/firehose/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://en.wordpress.com/firehose/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
}
add_action( 'jetpack_learn_more_button_enhanced-distribution', 'jetpack_enhanced_distribution_more_link' );
+// JSON API
+function jetpack_json_api_more_info() { ?>
+ <h4><?php esc_html_e( 'JSON API' , 'jetpack' ); ?></h4>
+
+ <p><?php esc_html_e( 'Jetpack will allow you to authorize applications and services to securely connect to your blog and allow them to use your content in new ways and offer you new functionality.', 'jetpack' ); ?>
+
+ <p><?php _e( "Developers can use WordPress.com's <a href='http://developer.wordpress.com/docs/oauth2/'>OAuth2</a> authentication system and <a href='http://developer.wordpress.com/docs/api/'>WordPress.com REST API</a> to manage and access your site's content.", 'jetpack' ); ?></p>
+
+<?php
+}
+
+add_action( 'jetpack_module_more_info_json-api', 'jetpack_json_api_more_info' );
+add_action( 'jetpack_module_more_info_connected_json-api', 'jetpack_json_api_more_info' );
+
+function jetpack_json_api_more_link() {
+ echo '<a class="button-secondary more-info-link" href="http://jetpack.me/support/json-api/">' . esc_html__( 'Learn More', 'jetpack' ) . '</a>';
+}
+add_action( 'jetpack_learn_more_button_json-api', 'jetpack_json_api_more_link' );
+
// Contact Form: START
function jetpack_contact_form_learn_more_button() {
- echo '<a class="button more-info-link" href="http://support.wordpress.com/contact-form/">' . __( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="http://support.wordpress.com/contact-form/">' . __( 'Learn More', 'jetpack' ) . '</a>';
}
function jetpack_contact_form_more_info() {
@@ -429,7 +509,7 @@ add_action( 'jetpack_module_more_info_connected_contact-form', 'jetpack_contact_
// Jetpack Comments: START
function jetpack_comments_learn_more_button() {
- echo '<a class="button more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
}
function jetpack_comments_more_info() {
@@ -460,13 +540,13 @@ add_action( 'jetpack_module_more_info_connected_comments', 'jetpack_comments_mor
// Gallery Carousel: START
function jetpack_carousel_learn_more_button() {
- echo '<a class="button more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+ echo '<a class="button-secondary more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
}
function jetpack_carousel_more_info() {
?>
<div class="jp-info-img">
- <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/screenshot-6.png' ) ?>" alt="<?php esc_attr_e( 'Gallery Carousel Screenshot', 'jetpack' ) ?>" width="300" height="188" />
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/carousel.png' ) ?>" alt="<?php esc_attr_e( 'Gallery Carousel Screenshot', 'jetpack' ) ?>" width="300" height="188" />
</div>
<h4><?php esc_html_e( 'Carousel', 'jetpack' ); ?></h4>
@@ -479,3 +559,220 @@ add_action( 'jetpack_learn_more_button_carousel', 'jetpack_carousel_learn_more_b
add_action( 'jetpack_module_more_info_carousel', 'jetpack_carousel_more_info' );
add_action( 'jetpack_module_more_info_connected_carousel', 'jetpack_carousel_more_info' );
// Gallery Carousel: STOP
+
+// Custom CSS: START
+function jetpack_custom_css_more_info() {
+ ?>
+ <div class="jp-info-img">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/custom-css.png' ) ?>" alt="<?php esc_attr_e( 'Custom CSS', 'jetpack' ) ?>" width="300" height="150" />
+ </div>
+
+ <h4><?php esc_html_e( 'Custom CSS', 'jetpack' ); ?></h4>
+ <p><?php esc_html_e( "The Custom CSS editor gives you the ability to add to or replace your theme's CSS, all while supplying syntax coloring, auto-indentation, and immediate feedback on the validity of the CSS you're writing.", 'jetpack' ); ?></p>
+ <p><?php printf( __( 'To use the CSS editor, go to Appearance &#8594; <a href="%s">Edit CSS</a>.', 'jetpack' ), admin_url( 'themes.php?page=editcss' ) ); ?></p>
+
+ <?php
+}
+
+function jetpack_custom_css_more_button() {
+ echo '<a class="button-secondary more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+
+add_action( 'jetpack_learn_more_button_custom-css', 'jetpack_custom_css_more_button' );
+add_action( 'jetpack_module_more_info_custom-css', 'jetpack_custom_css_more_info' );
+// Custom CSS: STOP
+
+// Minileven: START
+function jetpack_minileven_more_info() {
+ ?>
+ <div class="jp-info-img">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/mobile-theme.png' ) ?>" alt="<?php esc_attr_e( 'Mobile Theme', 'jetpack' ) ?>" width="300" height="150" />
+ </div>
+
+ <h4><?php esc_html_e( 'Mobile Theme', 'jetpack' ); ?></h4>
+ <p><?php esc_html_e( "There's a good chance that visitors to your site will be using a smartphone, and it's important to provide them with a great reading experience while on the small screen.", 'jetpack' ); ?></p>
+ <p><?php esc_html_e( "Jetpack's mobile theme is optimized for small screens. It uses the header image, background, and widgets from your current theme for a great custom look. Post format support is included, so your photos and galleries will look fantastic on a smartphone.", 'jetpack' ); ?></p>
+ <p><?php esc_html_e( 'Visitors on iPhone, Android, Windows Phone, and other mobile devices will automatically see the mobile theme, with the option to view the full site. You can enable or disable the mobile theme by clicking the "Activate" or "Deactive" button above.', 'jetpack' ); ?></p>
+ <?php
+}
+
+function jetpack_minileven_more_button() {
+ echo '<a class="button-secondary more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+
+add_action( 'jetpack_learn_more_button_minileven', 'jetpack_minileven_more_button' );
+add_action( 'jetpack_module_more_info_minileven', 'jetpack_minileven_more_info' );
+// Minileven: STOP
+
+
+// Mobile Push Notifications: START
+function jetpack_mobile_push_notifications_more_info() { ?>
+ <div class="jp-info-img">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/mobile-push-notifications.jpg' ) ?>" alt="<?php esc_attr_e( 'Mobile Push Notifications', 'jetpack' ) ?>" width="300" height="150" />
+ </div>
+
+ <h4><?php esc_html_e( 'Mobile Push Notifications' , 'jetpack' ); ?></h4>
+
+ <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>
+
+<?php
+}
+
+function jetpack_mobile_push_notifications_more_link() {
+ echo '<a class="button-secondary more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+
+add_action( 'jetpack_learn_more_button_mobile-push', 'jetpack_mobile_push_notifications_more_link' );
+add_action( 'jetpack_module_more_info_mobile-push', 'jetpack_mobile_push_notifications_more_info' );
+// Mobile Push Notifications: STOP
+
+// Infinite Scroll: START
+/**
+ *
+ */
+function jetpack_infinite_scroll_more_info() {
+ $support_text = sprintf( __( 'If you are a theme author, you can learn about adding support for Infinite Scroll at <a href="%1$s">%1$s</a>.', 'jetpack' ), 'http://jetpack.me/support/infinite-scroll/' );
+
+ ?>
+ <h4><?php esc_html_e( 'Infinite Scroll', 'jetpack' ); ?></h4>
+
+ <?php if ( ! Jetpack::is_active() || ( Jetpack::is_active() && current_theme_supports( 'infinite-scroll' ) ) ) : ?>
+ <p><?php esc_html_e( 'When you write great content, all you really want is people to find it, right?', 'jetpack' ); ?></p>
+
+ <p><?php esc_html_e( "With the Infinite Scroll module and a supported theme, that's exactly what happens. Instead of the old way of navigating down a page by scrolling and then clicking a link to get to the next page, waiting for a page refresh&mdash;the document model of the web&mdash;infinite scrolling pulls the next set of posts automatically into view when the reader approaches the bottom of the page, more like an application.", 'jetpack' ); ?></p>
+
+ <?php else : ?>
+ <p><?php echo esc_html( sprintf( __( "At this time, your theme, %s, doesn't support Infinite Scroll. Unlike other Jetpack modules, Infinite Scroll needs information from your theme to function properly.", 'jetpack' ), ( function_exists( 'wp_get_theme' ) ? wp_get_theme()->Name : get_current_theme() ) ) ); ?></p>
+
+ <p><?php esc_html_e( "Until your theme supports Infinite Scroll, you won't be able to activate this module.", 'jetpack' ); ?></p>
+
+ <?php
+
+ if ( current_user_can( 'update_themes' ) ) :
+ ob_start();
+ theme_update_available( function_exists( 'wp_get_theme' ) ? wp_get_theme() : (object) get_theme( get_current_theme() ) );
+ $theme_update_available = ob_get_clean();
+
+ if ( ! empty( $theme_update_available ) ) : ?>
+ <p><?php printf( __( 'There is an update available for your theme. You may wish to check if this update adds Infinite Scroll support by visiting the <a href="%s">WordPress Updates</a> page.', 'jetpack' ), esc_url( admin_url( 'update-core.php' ) ) ); ?></p>
+ <?php else : ?>
+ <p><?php echo $support_text; ?></p>
+ <?php endif; ?>
+ <?php else : ?>
+ <p><?php echo $support_text; ?></p>
+ <?php endif; ?>
+ <?php endif;
+}
+add_action( 'jetpack_module_more_info_infinite-scroll', 'jetpack_infinite_scroll_more_info' );
+
+/**
+ *
+ */
+function jetpack_infinite_scroll_more_button() {
+ echo '<a class="button more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+add_action( 'jetpack_learn_more_button_infinite-scroll', 'jetpack_infinite_scroll_more_button' );
+// Infinite Scroll: STOP
+
+
+// Post by Email: START
+function jetpack_post_by_email_more_info() { ?>
+ <div class="jp-info-img">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/post-by-email.png' ) ?>" alt="<?php esc_attr_e( 'Post by Email', 'jetpack' ) ?>" width="300" height="115" />
+ </div>
+
+ <h4><?php esc_html_e( 'Post by Email' , 'jetpack' ); ?></h4>
+
+ <p><?php esc_html_e( 'Post by Email is a way of publishing posts on your blog by email. Any email client can be used to send the email, allowing you to publish quickly and easily from devices such as cell phones.', 'jetpack' ); ?></p>
+
+<?php if ( 'jetpack_module_more_info_connected_post-by-email' == current_filter() ) : ?>
+
+ <p><?php printf( __( 'Manage your Post By Email address from your <a href="%s">profile settings</a>.', 'jetpack' ), esc_url( get_edit_profile_url( get_current_user_id() ) . '#post-by-email' ) ); ?>
+
+<?php endif; ?>
+
+ <p>&rarr; <a href="http://jetpack.me/support/post-by-email/"><?php esc_html_e( 'More information on sending emails, attachments, and customizing your posts.', 'jetpack' ); ?></a></p>
+
+<?php
+}
+
+function jetpack_post_by_email_more_link() {
+ echo '<a class="button-secondary more-info-link" href="http://jetpack.me/support/post-by-email/">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+
+add_action( 'jetpack_module_more_info_post-by-email', 'jetpack_post_by_email_more_info' );
+add_action( 'jetpack_module_more_info_connected_post-by-email', 'jetpack_post_by_email_more_info' );
+add_action( 'jetpack_learn_more_button_post-by-email', 'jetpack_post_by_email_more_link' );
+// Post by Email: STOP
+
+
+// Photon: START
+/**
+ *
+ */
+function jetpack_photon_more_info() { ?>
+ <h4><?php esc_html_e( 'Photon' , 'jetpack' ); ?></h4>
+
+ <p><?php esc_html_e( "Give your site a boost by loading images in posts from the WordPress.com content delivery network. We cache your images and serve them from our super-fast network, reducing the burden on your Web host with the click of a button.", 'jetpack' ); ?></p>
+<?php
+}
+add_action( 'jetpack_module_more_info_photon', 'jetpack_photon_more_info' );
+
+/**
+ * Display "Learn More" button for Photon module
+ * @uses __
+ * @action jetpack_learn_more_button_photon
+ * @return string
+ */
+function jetpack_photon_more_link() {
+ echo '<a class="button-secondary more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+add_action( 'jetpack_learn_more_button_photon', 'jetpack_photon_more_link' );
+// Photon: STOP
+
+// Tiled Galleries: START
+function jetpack_tiled_gallery_more_info() { ?>
+ <h4><?php esc_html_e( 'Tiled Galleries' , 'jetpack' ); ?></h4>
+
+ <div class="jp-info-img">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/tiled-gallery.png' ) ?>" alt="<?php esc_attr_e( 'Tiled Galleries', 'jetpack' ) ?>" width="300" height="150" />
+ </div>
+
+ <p><?php esc_html_e( 'Create elegant magazine-style mosaic layouts for your photos without having to use an external graphic editor.', 'jetpack' ); ?></p>
+ <p><?php printf( __( 'When adding a gallery to your post, you now have the option to select a layout style for your images. We\'ve added support for Rectangular, Square, and Circular galleries. By default, galleries will continue to display using the standard thumbnail grid layout. To make the rectangular layout the default for all of your site\'s galleries, head over to <a href="%s">Settings &rarr; Media</a> and check the box next to "Display all your gallery pictures in a cool mosaic."', 'jetpack' ), admin_url( 'options-media.php' ) ); ?></p>
+ <p><em><?php esc_html_e( 'Note: Images in tiled galleries require extra-special processing, so they will be served from WordPress.com\'s CDN even if the Photon module is disabled.', 'jetpack' ); ?></em></p>
+<?php
+}
+add_action( 'jetpack_module_more_info_tiled-gallery', 'jetpack_tiled_gallery_more_info' );
+
+function jetpack_tiled_gallery_more_link() {
+ echo '<a class="button-secondary more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+add_action( 'jetpack_learn_more_button_tiled-gallery', 'jetpack_tiled_gallery_more_link' );
+// Tiled Galleries: STOP
+
+// Likes: START
+function jetpack_likes_more_info() { ?>
+
+ <div class="jp-info-img">
+ <a href="http://jetpack.me/support/likes/">
+ <img class="jp-info-img" src="<?php echo plugins_url( basename( dirname( dirname( __FILE__ ) ) ) . '/_inc/images/screenshots/likes.png' ) ?>" alt="<?php esc_attr_e( 'Likes', 'jetpack' ) ?>" width="323" height="69" />
+ </a>
+ </div>
+
+ <h4><?php esc_html_e( 'Likes' , 'jetpack' ); ?></h4>
+
+ <p><?php esc_html_e( 'Likes allow your readers to show their appreciation for your posts and other published content using their WordPress.com accounts. Your readers will then be able to review their liked posts from WordPress.com.', 'jetpack' ) ?></p>
+ <p><?php esc_html_e( 'Displayed below your posts will be how many people have liked your posts and the Gravatars of those who have liked them.', 'jetpack' ); ?></p>
+
+ <p>&rarr; <a href="http://jetpack.me/support/likes/"><?php esc_html_e( 'More information on using Likes.', 'jetpack' ); ?></a></p>
+
+<?php
+}
+add_action( 'jetpack_module_more_info_likes', 'jetpack_likes_more_info' );
+
+function jetpack_likes_more_link() {
+ echo '<a class="button-secondary more-info-link" href="#">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+add_action( 'jetpack_learn_more_button_likes', 'jetpack_likes_more_link' );
+// Likes: STOP
diff --git a/plugins/jetpack/modules/notes.php b/plugins/jetpack/modules/notes.php
new file mode 100644
index 00000000..e33f7ff8
--- /dev/null
+++ b/plugins/jetpack/modules/notes.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Module Name: Notifications
+ * Module Description: Monitor and manage your site's activity with Notifications in your Toolbar and on WordPress.com.
+ * Sort Order: 1
+ * First Introduced: 1.9
+ */
+
+if ( !defined( 'JETPACK_NOTES__CACHE_BUSTER' ) ) define( 'JETPACK_NOTES__CACHE_BUSTER', JETPACK__VERSION . '-' . gmdate( 'oW' ) );
+
+Jetpack_Sync::sync_options( __FILE__,
+ 'home',
+ 'blogname',
+ 'siteurl',
+ 'permalink_structure',
+ 'category_base',
+ 'tag_base',
+ 'comment_moderation',
+ 'default_comment_status',
+ 'thread_comments',
+ 'thread_comments_depth'
+);
+
+class Jetpack_Notifications {
+ var $jetpack = false;
+
+ /**
+ * Singleton
+ * @static
+ */
+ function &init() {
+ static $instance = array();
+
+ if ( !$instance ) {
+ $instance[0] = new Jetpack_Notifications;
+ }
+
+ return $instance[0];
+ }
+
+ function Jetpack_Notifications() {
+ $this->jetpack = Jetpack::init();
+
+ add_action( 'init', array( &$this, 'action_init' ) );
+
+ //post types that support comments
+ $filt_post_types = array();
+ foreach ( get_post_types() as $post_type ) {
+ if ( post_type_supports( $post_type, 'comments' ) ) {
+ $filt_post_types[] = $post_type;
+ }
+ }
+
+ Jetpack_Sync::sync_posts( __FILE__, array(
+ 'post_types' => $filt_post_types,
+ 'post_stati' => array( 'publish' ),
+ ) );
+ Jetpack_Sync::sync_comments( __FILE__, array(
+ 'post_types' => $filt_post_types,
+ 'post_stati' => array( 'publish' ),
+ 'comment_stati' => array( 'approve', 'approved', '1', 'hold', 'unapproved', 'unapprove', '0', 'spam', 'trash' ),
+ ) );
+ }
+
+ function wpcom_static_url($file) {
+ $i = hexdec( substr( md5( $file ), -1 ) ) % 2;
+ $http = is_ssl() ? 'https' : 'http';
+ $url = $http . '://s' . $i . '.wp.com' . $file;
+ return $url;
+ }
+
+ // return the major version of Internet Explorer the viewer is using or false if it's not IE
+ public static function get_internet_explorer_version() {
+ static $version;
+ if ( isset( $version ) ) {
+ return $version;
+ }
+
+ preg_match( '/MSIE (\d+)/', $_SERVER['HTTP_USER_AGENT'], $matches );
+ $version = empty( $matches[1] ) ? null : $matches[1];
+ if ( empty( $version ) || !$version ) {
+ return false;
+ }
+ return $version;
+ }
+
+ public static function current_browser_is_supported() {
+ static $supported;
+
+ if ( isset( $supported ) ) {
+ return $supported;
+ }
+
+ $ie_version = self::get_internet_explorer_version();
+ if ( false === $ie_version ) {
+ return $supported = true;
+ }
+
+ if ( $ie_version < 8 ) {
+ return $supported = false;
+ }
+
+ return $supported = true;
+ }
+
+ function action_init() {
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
+ return;
+
+ if ( !has_filter( 'show_admin_bar', '__return_true' ) && !is_user_logged_in() )
+ return;
+
+ if ( !self::current_browser_is_supported() )
+ return;
+
+ add_action( 'admin_bar_menu', array( &$this, 'admin_bar_menu'), 120 );
+ add_action( 'wp_head', array( &$this, 'styles_and_scripts'), 120 );
+ add_action( 'admin_head', array( &$this, 'styles_and_scripts') );
+ }
+
+ function styles_and_scripts() {
+ wp_enqueue_style( 'notes-admin-bar-rest', $this->wpcom_static_url( '/wp-content/mu-plugins/notes/admin-bar-rest.css' ), array(), JETPACK_NOTES__CACHE_BUSTER );
+ wp_enqueue_style( 'noticons', $this->wpcom_static_url( '/i/noticons/noticons.css' ), array(), JETPACK_NOTES__CACHE_BUSTER );
+
+ $this->print_js();
+
+ // attempt to use core or plugin libraries if registered
+ if ( wp_script_is( 'mustache', 'registered' ) ) {
+ if ( !wp_script_is( 'mustache', 'queue' ) ) {
+ wp_enqueue_script( 'mustache' );
+ }
+ }
+ else {
+ wp_enqueue_script( 'mustache', $this->wpcom_static_url( '/wp-content/js/mustache.js' ), null, JETPACK_NOTES__CACHE_BUSTER );
+ }
+
+ if ( wp_script_is( 'underscore', 'registered' ) ) {
+ if ( !wp_script_is( 'underscore', 'queue' ) ) {
+ wp_enqueue_script( 'underscore' );
+ }
+ }
+ else {
+ wp_enqueue_script( 'underscore', $this->wpcom_static_url( '/wp-content/js/underscore.js' ), null, JETPACK_NOTES__CACHE_BUSTER );
+ }
+ if ( wp_script_is( 'backbone', 'registered' ) ) {
+ if ( !wp_script_is( 'backbone', 'queue' ) ) {
+ wp_enqueue_script( 'backbone' );
+ }
+ }
+ else {
+ wp_enqueue_script( 'backbone', $this->wpcom_static_url( '/wp-content/js/backbone.js' ), array( 'jquery', 'underscore' ), JETPACK_NOTES__CACHE_BUSTER );
+ }
+
+ wp_enqueue_script( 'notes-postmessage', $this->wpcom_static_url( '/wp-content/js/postmessage.js' ), array(), JETPACK_NOTES__CACHE_BUSTER );
+ wp_enqueue_script( 'notes-rest-common', $this->wpcom_static_url( '/wp-content/mu-plugins/notes/notes-rest-common.js' ), array( 'backbone', 'mustache', 'jquery.spin' ), JETPACK_NOTES__CACHE_BUSTER );
+ wp_enqueue_script( 'notes-admin-bar-rest', $this->wpcom_static_url( '/wp-content/mu-plugins/notes/admin-bar-rest.js' ), array( 'jquery', 'underscore', 'backbone', 'jquery.spin' ), JETPACK_NOTES__CACHE_BUSTER );
+ }
+
+ function admin_bar_menu() {
+ global $wp_admin_bar, $current_blog;
+
+ if ( !is_object( $wp_admin_bar ) )
+ return;
+
+ $classes = 'wpnt-loading wpn-read';
+ $wp_admin_bar->add_menu( array(
+ 'id' => 'notes',
+ 'title' => '<span id="wpnt-notes-unread-count" class="' . esc_attr( $classes ) . '">
+ <span class="noticon noticon-notification" /></span>
+ </span>',
+ 'meta' => array(
+ 'html' => '<div id="wpnt-notes-panel" style="display:none"><div class="wpnt-notes-panel-header"><span class="wpnt-notes-header">' . __('Notifications', 'jetpack') . '</span><span class="wpnt-notes-panel-link"></span></div></div>',
+ 'class' => 'menupop',
+ ),
+ 'parent' => 'top-secondary',
+ ) );
+ }
+
+ function print_js() {
+ $link_accounts_url = is_user_logged_in() && !Jetpack::is_user_connected() ? Jetpack::admin_url() : false;
+?>
+<script type="text/javascript">
+/* <![CDATA[ */
+ var wpNotesIsJetpackClient = true;
+<?php if ( $link_accounts_url ) : ?>
+ var wpNotesLinkAccountsURL = '<?php print $link_accounts_url; ?>';
+<?php endif; ?>
+/* ]]> */
+</script>
+<?php
+ }
+
+}
+
+Jetpack_Notifications::init();
diff --git a/plugins/jetpack/modules/photon.php b/plugins/jetpack/modules/photon.php
new file mode 100644
index 00000000..06db8680
--- /dev/null
+++ b/plugins/jetpack/modules/photon.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * Module Name: Photon
+ * Module Description: Give your site a boost by loading images from the WordPress.com content delivery network.
+ * Sort Order: 15
+ * First Introduced: 2.0
+ */
+
+Jetpack_Photon::instance(); \ No newline at end of file
diff --git a/plugins/jetpack/modules/photon/photon.js b/plugins/jetpack/modules/photon/photon.js
new file mode 100644
index 00000000..050e73b6
--- /dev/null
+++ b/plugins/jetpack/modules/photon/photon.js
@@ -0,0 +1,42 @@
+(function($){
+ /**
+ * For images lacking explicit dimensions and needing them, try to add them.
+ */
+ var restore_dims = function() {
+ $( 'img[data-recalc-dims]' ).each( function() {
+ if ( this.complete ) {
+ var width = this.width,
+ height = this.height;
+
+ if ( width && width > 0 && height && height > 0 ) {
+ $( this ).attr( {
+ width: width,
+ height: height
+ } );
+
+ reset_for_retina( this );
+ }
+ }
+ else {
+ $( this ).load( arguments.callee );
+ }
+ } );
+ },
+
+ /**
+ * Modify given image's markup so that devicepx-jetpack.js will act on the image and it won't be reprocessed by this script.
+ */
+ reset_for_retina = function( img ) {
+ $( img ).removeAttr( 'data-recalc-dims' ).removeAttr( 'scale' );
+ };
+
+ /**
+ * Check both when page loads, and when IS is triggered.
+ */
+ $( document ).ready( restore_dims );
+
+ if ( "on" in $.fn )
+ $( document.body ).on( 'post-load', restore_dims );
+ else
+ $( document ).delegate( 'body', 'post-load', restore_dims );
+})(jQuery); \ No newline at end of file
diff --git a/plugins/jetpack/modules/post-by-email.php b/plugins/jetpack/modules/post-by-email.php
new file mode 100644
index 00000000..e8cd8873
--- /dev/null
+++ b/plugins/jetpack/modules/post-by-email.php
@@ -0,0 +1,240 @@
+<?php
+
+/**
+ * Module Name: Post by Email
+ * Module Description: Publish posts to your blog directly from your personal email account.
+ * First Introduced: 2.0
+ * Sort Order: 4
+ */
+
+add_action( 'jetpack_modules_loaded', array( 'Jetpack_Post_By_Email', 'init' ) );
+
+Jetpack_Sync::sync_options( __FILE__,
+ 'large_size_w',
+ 'large_size_h',
+ 'thumbnail_size_w',
+ 'thumbnail_size_h',
+ 'medium_size_w',
+ 'medium_size_h'
+);
+
+add_action( 'jetpack_activate_module_post-by-email', array( 'Jetpack_Post_By_Email', 'module_toggle' ) );
+add_action( 'jetpack_deactivate_module_post-by-email', array( 'Jetpack_Post_By_Email', 'module_toggle' ) );
+
+Jetpack::enable_module_configurable( __FILE__ );
+Jetpack::module_configuration_load( __FILE__, array( 'Jetpack_Post_By_Email', 'configuration_redirect' ) );
+
+class Jetpack_Post_By_Email {
+ function &init() {
+ static $instance = NULL;
+
+ if ( !$instance ) {
+ $instance = new Jetpack_Post_By_Email;
+ }
+
+ return $instance;
+ }
+
+ function __construct() {
+ add_action( 'init', array( &$this, 'action_init' ) );
+ }
+
+ function module_toggle() {
+ $jetpack = Jetpack::init();
+ $jetpack->sync->register( 'noop' );
+ }
+
+ function configuration_redirect() {
+ wp_safe_redirect( get_edit_profile_url( get_current_user_id() ) . '#post-by-email' );
+ exit;
+ }
+
+ function action_init() {
+ if ( ! current_user_can( 'edit_posts' ) )
+ return;
+
+ add_action( 'profile_personal_options', array( &$this, 'user_profile' ) );
+ add_action( 'admin_print_scripts-profile.php', array( &$this, 'profile_scripts' ) );
+
+ add_action( 'wp_ajax_jetpack_post_by_email_enable', array( &$this, 'create_post_by_email_address' ) );
+ add_action( 'wp_ajax_jetpack_post_by_email_regenerate', array( &$this, 'regenerate_post_by_email_address' ) );
+ add_action( 'wp_ajax_jetpack_post_by_email_disable', array( &$this, 'delete_post_by_email_address' ) );
+ }
+
+ function profile_scripts() {
+ wp_enqueue_script( 'post-by-email', plugins_url( 'post-by-email/post-by-email.js', __FILE__ ), array( 'jquery' ) );
+ wp_enqueue_style( 'post-by-email', plugins_url( 'post-by-email/post-by-email.css', __FILE__ ) );
+ Jetpack::init()->admin_styles();
+ }
+
+ function check_user_connection() {
+ $user_token = Jetpack_Data::get_access_token( get_current_user_id() );
+ $is_user_connected = $user_token && !is_wp_error( $user_token );
+
+ // If the user is already connected via Jetpack, then we're good
+ if ( $is_user_connected )
+ return true;
+
+ return false;
+ }
+
+ function user_profile() {
+ $blog_name = get_bloginfo( 'blogname' );
+ if ( empty( $blog_name ) ) {
+ $blog_name = home_url( '/' );
+ }
+
+ ?>
+ <div id="post-by-email" class="jetpack-targetable">
+ <h3><?php esc_html_e( 'Post by Email', 'jetpack' ); ?></h3>
+ <table class="form-table">
+ <tr>
+ <th scope="row"><?php esc_html_e( 'Email Address', 'jetpack' ); ?><span id="jp-pbe-spinner" class="spinner"></span></th>
+ <td>
+ <div id="jp-pbe-error" class="jetpack-inline-error"></div> <?php
+
+ if ( $this->check_user_connection() ) {
+ $email = $this->get_post_by_email_address();
+
+ if ( empty( $email ) ) {
+ $enable_hidden = '';
+ $info_hidden = ' style="display: none;"';
+ } else {
+ $enable_hidden = ' style="display: none;"';
+ $info_hidden = '';
+ } ?>
+
+ <input type="button" name="jp-pbe-enable" id="jp-pbe-enable" class="button" value="<?php esc_attr_e( 'Enable Post By Email', 'jetpack' ); ?> "<?php echo $enable_hidden; ?> />
+ <div id="jp-pbe-info"<?php echo $info_hidden; ?>>
+ <p id="jp-pbe-email-wrapper">
+ <input type="text" id="jp-pbe-email" value="<?php echo esc_attr( $email ); ?>" readonly="readonly" class="regular-text" />
+ <span class="description"><a target="_blank" href="http://jetpack.me/support/post-by-email/"><?php esc_html_e( 'More information', 'jetpack' ); ?></a></span>
+ </p>
+ <p>
+ <input type="button" name="jp-pbe-regenerate" id="jp-pbe-regenerate" class="button" value="<?php esc_attr_e( 'Regenerate Address', 'jetpack' ); ?> " />
+ <input type="button" name="jp-pbe-disable" id="jp-pbe-disable" class="button" value="<?php esc_attr_e( 'Disable Post By Email', 'jetpack' ); ?> " />
+ </p>
+ </div> <?php
+ } else {
+ $jetpack = Jetpack::init(); ?>
+
+ <p class="jetpack-inline-message">
+ <?php printf(
+ esc_html( wptexturize( __( 'To use Post By Email, you need to link your %s account to your WordPress.com account.', 'jetpack' ) ) ),
+ '<strong>' . esc_html( $blog_name ) . '</strong>'
+ ); ?><br />
+ <?php echo esc_html( wptexturize( __( "If you don't have a WordPress.com account yet, you can sign up for free in just a few seconds.", 'jetpack' ) ) ); ?>
+ </p>
+ <p>
+ <a href="<?php echo $jetpack->build_connect_url( false, get_edit_profile_url( get_current_user_id() ) . '#post-by-email' ); ?>" class="button button-connector" id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack' ); ?></a>
+ </p>
+ <?php
+ } ?>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <?php
+ }
+
+ function get_post_by_email_address() {
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client( array(
+ 'user_id' => get_current_user_id(),
+ ) );
+ $xml->query( 'jetpack.getPostByEmailAddress' );
+
+ if ( $xml->isError() )
+ return NULL;
+
+ $response = $xml->getResponse();
+ if ( empty( $response ) )
+ return NULL;
+
+ return $response;
+ }
+
+ function create_post_by_email_address() {
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client( array(
+ 'user_id' => get_current_user_id(),
+ ) );
+ $xml->query( 'jetpack.createPostByEmailAddress' );
+
+ if ( $xml->isError() ) {
+ echo json_encode( array(
+ 'response' => 'error',
+ 'message' => __( 'Unable to create your Post By Email address. Please try again later.', 'jetpack' )
+ ) );
+ die();
+ }
+
+ $response = $xml->getResponse();
+ if ( empty( $response ) ) {
+ echo json_encode( array(
+ 'response' => 'error',
+ 'message' => __( 'Unable to create your Post By Email address. Please try again later.', 'jetpack' )
+ ) );
+ die();
+ }
+
+ echo $response;
+ die();
+ }
+
+ function regenerate_post_by_email_address() {
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client( array(
+ 'user_id' => get_current_user_id(),
+ ) );
+ $xml->query( 'jetpack.regeneratePostByEmailAddress' );
+
+ if ( $xml->isError() ) {
+ echo json_encode( array(
+ 'response' => 'error',
+ 'message' => __( 'Unable to regenerate your Post By Email address. Please try again later.', 'jetpack' )
+ ) );
+ die();
+ }
+
+ $response = $xml->getResponse();
+ if ( empty( $response ) ) {
+ echo json_encode( array(
+ 'response' => 'error',
+ 'message' => __( 'Unable to regenerate your Post By Email address. Please try again later.', 'jetpack' )
+ ) );
+ die();
+ }
+
+ echo $response;
+ die();
+ }
+
+ function delete_post_by_email_address() {
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client( array(
+ 'user_id' => get_current_user_id(),
+ ) );
+ $xml->query( 'jetpack.deletePostByEmailAddress' );
+
+ if ( $xml->isError() ) {
+ echo json_encode( array(
+ 'response' => 'error',
+ 'message' => __( 'Unable to disable your Post By Email address. Please try again later.', 'jetpack' )
+ ) );
+ die();
+ }
+
+ $response = $xml->getResponse();
+ if ( empty( $response ) ) {
+ echo json_encode( array(
+ 'response' => 'error',
+ 'message' => __( 'Unable to disable your Post By Email address. Please try again later.', 'jetpack' )
+ ) );
+ die();
+ }
+
+ echo $response;
+ die();
+ }
+}
diff --git a/plugins/jetpack/modules/post-by-email/post-by-email.css b/plugins/jetpack/modules/post-by-email/post-by-email.css
new file mode 100644
index 00000000..c3b88def
--- /dev/null
+++ b/plugins/jetpack/modules/post-by-email/post-by-email.css
@@ -0,0 +1,6 @@
+#jp-pbe-error {
+ display: none;
+}
+#post-by-email:target .jetpack-inline-message {
+ background-color: #fff;
+}
diff --git a/plugins/jetpack/modules/post-by-email/post-by-email.js b/plugins/jetpack/modules/post-by-email/post-by-email.js
new file mode 100644
index 00000000..7ba14bd7
--- /dev/null
+++ b/plugins/jetpack/modules/post-by-email/post-by-email.js
@@ -0,0 +1,129 @@
+jetpack_post_by_email = {
+ init: function() {
+ jQuery( '#jp-pbe-enable' ).click( jetpack_post_by_email.enable );
+ jQuery( '#jp-pbe-regenerate' ).click( jetpack_post_by_email.regenerate );
+ jQuery( '#jp-pbe-disable' ).click( jetpack_post_by_email.disable );
+ },
+
+ enable: function() {
+ jQuery( '#jp-pbe-enable' ).attr( 'disabled', 'disabled' );
+ jQuery( '#jp-pbe-error' ).fadeOut();
+ jQuery( '#jp-pbe-spinner' ).fadeIn();
+
+ var data = {
+ action: 'jetpack_post_by_email_enable'
+ };
+
+ jQuery.post( ajaxurl, data, jetpack_post_by_email.handle_enabled );
+ },
+
+ handle_enabled: function( response ) {
+ var enabled = false;
+ var error;
+ try {
+ error = JSON.parse( response );
+ } catch ( e ) {
+ enabled = true;
+ }
+
+ jQuery( '#jp-pbe-regenerate' ).removeAttr( 'disabled' );
+ jQuery( '#jp-pbe-disable' ).removeAttr( 'disabled' );
+
+ if ( enabled ) {
+ jQuery( '#jp-pbe-enable' ).fadeOut( 400, function() {
+ jQuery( '#jp-pbe-enable' ).removeAttr( 'disabled' );
+ jQuery( '#jp-pbe-email' ).val( response );
+ jQuery( '#jp-pbe-info' ).fadeIn();
+ });
+ } else {
+ jQuery( '#jp-pbe-error' ).text( error.message );
+ jQuery( '#jp-pbe-error' ).fadeIn();
+ jQuery( '#jp-pbe-enable' ).removeAttr( 'disabled' );
+ }
+
+ jQuery( '#jp-pbe-spinner' ).fadeOut();
+ },
+
+ regenerate: function() {
+ jQuery( '#jp-pbe-regenerate' ).attr( 'disabled', 'disabled' );
+ jQuery( '#jp-pbe-disable' ).attr( 'disabled', 'disabled' );
+ jQuery( '#jp-pbe-error' ).fadeOut();
+ jQuery( '#jp-pbe-spinner' ).fadeIn();
+
+ var data = {
+ action: 'jetpack_post_by_email_regenerate'
+ };
+
+ jQuery.post( ajaxurl, data, jetpack_post_by_email.handle_regenerated );
+ },
+
+ handle_regenerated: function( response ) {
+ var regenerated = false;
+ var error;
+ try {
+ error = JSON.parse( response );
+ } catch ( e ) {
+ regenerated = true;
+ }
+
+ if ( regenerated ) {
+ jQuery( '#jp-pbe-email-wrapper' ).fadeOut( 400, function() {
+ jQuery( '#jp-pbe-email' ).val( response );
+ jQuery( '#jp-pbe-email-wrapper' ).fadeIn();
+ });
+ } else {
+ jQuery( '#jp-pbe-error' ).text( error.message );
+ jQuery( '#jp-pbe-error' ).fadeIn();
+ }
+
+ jQuery( '#jp-pbe-regenerate' ).removeAttr( 'disabled' );
+ jQuery( '#jp-pbe-disable' ).removeAttr( 'disabled' );
+ jQuery( '#jp-pbe-spinner' ).fadeOut();
+ },
+
+ disable: function() {
+ jQuery( '#jp-pbe-regenerate' ).attr( 'disabled', 'disabled' );
+ jQuery( '#jp-pbe-disable' ).attr( 'disabled', 'disabled' );
+ jQuery( '#jp-pbe-error' ).fadeOut();
+ jQuery( '#jp-pbe-spinner' ).fadeIn();
+
+ var data = {
+ action: 'jetpack_post_by_email_disable'
+ };
+
+ jQuery.post( ajaxurl, data, jetpack_post_by_email.handle_disabled );
+ },
+
+ handle_disabled: function( response ) {
+ var disabled = false;
+ var error;
+ try {
+ error = JSON.parse( response );
+ } catch ( e ) {
+ disabled = true;
+ }
+
+ if ( 'error' != error.response ) {
+ disabled = true;
+ }
+
+ if ( disabled ) {
+ jQuery( '#jp-pbe-enable' ).removeAttr( 'disabled' );
+ jQuery( '#jp-pbe-info' ).fadeOut( 400, function() {
+ jQuery( '#jp-pbe-regenerate' ).removeAttr( 'disabled' );
+ jQuery( '#jp-pbe-disable' ).removeAttr( 'disabled' );
+ jQuery( '#jp-pbe-enable' ).fadeIn();
+ });
+ } else {
+ jQuery( '#jp-pbe-regenerate' ).removeAttr( 'disabled' );
+ jQuery( '#jp-pbe-disable' ).removeAttr( 'disabled' );
+
+ jQuery( '#jp-pbe-error' ).text( error.message );
+ jQuery( '#jp-pbe-error' ).fadeIn();
+ }
+
+ jQuery( '#jp-pbe-spinner' ).fadeOut();
+ }
+};
+
+jQuery( function() { jetpack_post_by_email.init(); } );
diff --git a/plugins/jetpack/modules/publicize.php b/plugins/jetpack/modules/publicize.php
new file mode 100644
index 00000000..c9a37e5d
--- /dev/null
+++ b/plugins/jetpack/modules/publicize.php
@@ -0,0 +1,283 @@
+<?php
+/**
+ * Module Name: Publicize
+ * Module Description: Connect your site to popular social networks and automatically share new posts with your friends.
+ * Sort Order: 1
+ * First Introduced: 2.0
+ */
+
+class Jetpack_Publicize {
+
+ var $in_jetpack = true;
+
+ function __construct() {
+ global $publicize_ui;
+
+ $this->in_jetpack = ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'enable_module_configurable' ) ) ? true : false;
+
+ if ( $this->in_jetpack && method_exists( 'Jetpack', 'module_configuration_load' ) ) {
+ Jetpack::enable_module_configurable( __FILE__ );
+ Jetpack::module_configuration_load( __FILE__, array( $this, 'jetpack_configuration_load' ) );
+ Jetpack_Sync::sync_posts( __FILE__ );
+ }
+
+ require_once dirname( __FILE__ ) . '/publicize/publicize.php';
+
+ if ( $this->in_jetpack )
+ require_once dirname( __FILE__ ) . '/publicize/publicize-jetpack.php';
+ else {
+ require_once dirname( dirname( __FILE__ ) ) . '/mu-plugins/keyring/keyring.php';
+ require_once dirname( __FILE__ ) . '/publicize/publicize-wpcom.php';
+ }
+
+ require_once dirname( __FILE__ ) . '/publicize/ui.php';
+ $publicize_ui = new Publicize_UI();
+ $publicize_ui->in_jetpack = $this->in_jetpack;
+
+ // Jetpack specific checks / hooks
+ if ( $this->in_jetpack) {
+ add_action( 'jetpack_activate_module_publicize', array( $this, 'module_state_toggle' ) );
+ add_action( 'jetpack_deactivate_module_publicize', array( $this, 'module_state_toggle' ) );
+
+ // if sharedaddy isn't active, the sharing menu hasn't been added yet
+ $active = Jetpack::get_active_modules();
+ if ( in_array( 'publicize', $active ) && !in_array( 'sharedaddy', $active ) )
+ add_action( 'admin_menu', array( &$publicize_ui, 'sharing_menu' ) );
+ }
+ }
+
+ function module_state_toggle() {
+ // extra check that we are on the JP blog, just incase
+ if ( class_exists( 'Jetpack' ) && $this->in_jetpack ) {
+ $jetpack = Jetpack::init();
+ $jetpack->sync->register( 'noop' );
+ }
+ }
+
+ function jetpack_configuration_load() {
+ wp_safe_redirect( menu_page_url( 'sharing', false ) );
+ exit;
+ }
+}
+
+global $publicize_ui;
+new Jetpack_Publicize;
+
+/**
+* Helper functions for shared use in the services files
+*/
+class Publicize_Util {
+ /**
+ * Truncates a string to be shorter than or equal to the length specified
+ * Attempts to truncate on word boundaries
+ *
+ * @param string $string
+ * @param int $length
+ * @return string
+ */
+ function crop_str( $string, $length = 256 ) {
+ $string = wp_strip_all_tags( (string) $string, true ); // true: collapse Linear Whitespace into " "
+ $length = absint( $length );
+
+ if ( mb_strlen( $string, 'UTF-8' ) <= $length ) {
+ return $string;
+ }
+
+ // @see wp_trim_words()
+ if ( 'characters' == _x( 'words', 'word count: words or characters?', 'jetpack' ) ) {
+ return trim( mb_substr( $string, 0, $length - 1, 'UTF-8' ) ) . "\xE2\x80\xA6"; // ellipsis
+ }
+
+ $words = explode( ' ', $string );
+
+ $return = '';
+ while ( strlen( $word = array_shift( $words ) ) ) {
+ $new_return = $return ? "$return $word" : $word;
+ $new_return_length = mb_strlen( $new_return, 'UTF-8' );
+ if ( $new_return_length < $length - 1 ) {
+ $return = $new_return;
+ continue;
+ } elseif ( $new_return_length == $length - 1 ) {
+ $return = $new_return;
+ break;
+ }
+
+ if ( !$return ) {
+ $return = mb_substr( $new_return, 0, $length - 1, 'UTF-8' );
+ }
+
+ break;
+ }
+
+ return "$return\xE2\x80\xA6"; // ellipsis
+ }
+
+
+ /**
+ * Returns an array of DOMNodes that are comments (including recursing child nodes)
+ *
+ * @param DOMNode $node
+ * @return array
+ */
+
+ function get_comment_nodes( $node ) {
+ $comment_nodes = array();
+ foreach ( $node->childNodes as $child ) {
+
+ if ( XML_COMMENT_NODE === $child->nodeType ) {
+ $comment_nodes[] = $child;
+ }
+
+ if ( $child->hasChildNodes() ) {
+ $child_comment_nodes = self::get_comment_nodes( $child );
+ $comment_nodes = array_merge( $comment_nodes, $child_comment_nodes );
+ }
+ }
+
+ return $comment_nodes;
+ }
+
+ /**
+ * Truncates HTML so that its textContent (text without markup) is shorter than or equal to the length specified.
+ * The length of the returned string may be larger than the specified length due to the markup.
+ * Attempts to truncate on word boundaries.
+ *
+ * @param string $string
+ * @param int $length
+ * @param array $allowed_tags KSES input
+ * @return string
+ */
+ function crop_html( $string, $length = 256, $allowed_tags = array() ) {
+ $tags = $GLOBALS['allowedtags']; // Markup allowed in comments...
+
+ $tags['img'] = array( // ... plus images ...
+ 'alt' => true,
+ 'height' => true,
+ 'src' => true,
+ 'width' => true,
+ );
+
+ // ... and some other basics
+ $tags['p'] = array();
+ $tags['ul'] = array();
+ $tags['ol'] = array();
+ $tags['li'] = array();
+ $tags['br'] = array();
+
+ $tags = array_merge( $tags, $allowed_tags );
+
+ // Clean up, then KSES to really lock it down
+ $string = trim( (string) $string );
+ $string = preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $string );
+ $string = wp_kses( $string, $tags );
+
+ $string = mb_convert_encoding( $string, 'HTML-ENTITIES', 'UTF-8' );
+ $dom = new DOMDocument( '1.0', 'UTF-8' );
+ @$dom->loadHTML( "<html><body>$string</body></html>" ); // suppress parser warning
+
+ // Strip comment nodes, if any
+ $comment_nodes = self::get_comment_nodes( $dom->documentElement );
+ foreach ( $comment_nodes as &$comment_node ) {
+ $comment_node->parentNode->removeChild( $comment_node );
+ }
+ if ( $comment_nodes ) {
+ // Update the $string (some return paths work from just $string)
+ $string = $dom->saveHTML();
+ $string = preg_replace( '/^<!DOCTYPE.+?>/', '', $string );
+ $string = str_replace( array('<html>', '</html>', '<body>', '</body>' ), array( '', '', '', '' ), $string );
+ $string = trim( $string );
+ }
+
+ // Find the body
+ $body = false;
+ foreach ( $dom->childNodes as $child ) {
+ if ( XML_ELEMENT_NODE === $child->nodeType && 'html' === strtolower( $child->tagName ) ) {
+ $body = $child->firstChild;
+ break;
+ }
+ }
+
+ if ( !$body ) {
+ return self::crop_str( $string, $length );
+ }
+
+ // If the text (without the markup) is shorter than $length, just return
+ if ( mb_strlen( $body->textContent, 'UTF-8' ) <= $length ) {
+ return $string;
+ }
+
+ $node = false;
+ do {
+ $node = self::remove_innermost_last_child( $body, $node_removed_from );
+ $new_string_length = mb_strlen( $body->textContent, 'UTF-8' );
+ } while ( $new_string_length > $length );
+
+ $new_string = $dom->saveHTML( $body );
+ $new_string = mb_substr( $new_string, 6, -7, 'UTF-8' ); // 6: <body>, 7: </body>
+
+ if ( !$node ) {
+ return $new_string ? $new_string : self::crop_str( $string, $length );
+ }
+
+ $append_string_length = $length - $new_string_length;
+
+ if ( !$append_string_length ) {
+ return $new_string;
+ }
+
+ if ( $append_string_length > 1 && XML_TEXT_NODE === $node->nodeType ) { // 1: ellipsis
+ $append_string = self::crop_str( $node->textContent, $append_string_length ); // includes ellipsis
+ $append_node = $dom->createTextNode( $append_string );
+ $node_removed_from->appendChild( $append_node );
+ $new_string = $dom->saveHTML( $body );
+ $new_string = mb_substr( $new_string, 6, -7, 'UTF-8' );
+ } elseif ( $append_string_length > 9 && XML_ELEMENT_NODE === $node->nodeType && 'p' == strtolower( $node->nodeName ) ) { // 9: '<p>X{\xE2\x80\xA6}</p>'
+ $new_string .= '<p>' . self::crop_str( $node->textContent, $append_string_length - 8 ) . '</p>';
+ }
+
+ // Clean up any empty Paragraphs that might have occurred after removing their children
+ return trim( preg_replace( '#<p>\s*</p>#i', '', $new_string ) );
+ }
+
+ function remove_innermost_last_child( $node, &$node_removed_from ) {
+ $node_removed_from = $node;
+
+ if ( !$node->lastChild ) {
+ return false;
+ }
+
+ if ( $node->lastChild->hasChildNodes() ) {
+ return self::remove_innermost_last_child( $node->lastChild, $node_removed_from );
+ }
+
+ $innermost_last_child = $node->lastChild;
+ $node->removeChild( $innermost_last_child );
+
+ return $innermost_last_child;
+ }
+
+ function bump_stats_extras_publicize_url( $bin, $post_id ) {
+ static $done = array();
+ if ( isset( $done[$post_id] ) ) {
+ return;
+ }
+ $done[$post_id] = true;
+
+ if ( function_exists( 'bump_stats_extras' ) )
+ bump_stats_extras( 'publicize_url', $bin );
+ }
+
+ public static function build_sprintf( $args ) {
+ $search = array();
+ $replace = array();
+ foreach ( $args as $k => $arg ) {
+ if ( 0 == $k ) {
+ $string = $arg;
+ continue;
+ }
+ $search[] = "%$arg%";
+ $replace[] = "%$k\$s";
+ }
+ return str_replace( $search, $replace, $string );
+ }
+}
diff --git a/plugins/jetpack/modules/publicize/assets/connected.gif b/plugins/jetpack/modules/publicize/assets/connected.gif
new file mode 100644
index 00000000..24e0c11f
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/connected.gif
Binary files differ
diff --git a/plugins/jetpack/modules/publicize/assets/facebook-logo.png b/plugins/jetpack/modules/publicize/assets/facebook-logo.png
new file mode 100644
index 00000000..b9181cc4
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/facebook-logo.png
Binary files differ
diff --git a/plugins/jetpack/modules/publicize/assets/linkedin-logo.png b/plugins/jetpack/modules/publicize/assets/linkedin-logo.png
new file mode 100644
index 00000000..27018dcd
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/linkedin-logo.png
Binary files differ
diff --git a/plugins/jetpack/modules/publicize/assets/publicize.css b/plugins/jetpack/modules/publicize/assets/publicize.css
new file mode 100644
index 00000000..4065cb01
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/publicize.css
@@ -0,0 +1,175 @@
+div#publicize-services-block {
+ display: inline-block;
+ clear: both;
+ margin-bottom: 25px;
+ background-color: #fff;
+ width: 100%;
+}
+
+/* Add the logos for the Publicize services */
+span.pub-logos {
+ float: left;
+ display: block;
+ width: 130px;
+ height: 75px;
+ margin-top: -18px;
+ margin-left: 5px;
+ vertical-align: top;
+}
+
+span#facebook { background: url( facebook-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+span#twitter { background: url( twitter-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+span#yahoo { background: url( yahoo-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+span#linkedin { background: url( linkedin-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+span#tumblr { background: url( tumblr-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+
+a.publicize-profile-link, a.publicize-profile-link:visited {
+ text-decoration: none;
+}
+
+a.publicize-profile-link:hover {
+ color: #f1831e;
+}
+
+a.publicize-add-connection, a.publicize-add-connection:visited {
+ display: block;
+ vertical-align: middle;
+ text-decoration: none;
+}
+
+a.publicize-add-connection:hover {
+ color: #f1831e;
+}
+
+div.publicize-service-entry {
+ width: 100%;
+ clear: both;
+ margin-bottom: 10px;
+}
+
+div.publicize-service-left {
+ display: inline-block;
+ width: 150px;
+ vertical-align: top;
+}
+
+div.publicize-service-right {
+ display: inline-block;
+ margin-left: 5px;
+ margin-top: 5px;
+ width: 300px;
+ padding: 10px;
+ background-color: #f1f1f1;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ border-radius: 10px;
+ border: 1px solid #e5e5e5;
+}
+
+div.publicize-service-right ul {
+ margin-top: 0;
+}
+
+div.publicize-service-right li {
+ list-style-type: none;
+}
+
+.pub-disconnect-button {
+ -webkit-border-image: none;
+ border-bottom-color: #CCC;
+ border-bottom-style: none;
+ border-bottom-width: 0px;
+ border-left-color: #CCC;
+ border-left-style: none;
+ border-left-width: 0px;
+ border-right-color: #CCC;
+ border-right-style: none;
+ border-right-width: 0px;
+ border-top-color: #CCC;
+ border-top-style: none;
+ border-top-width: 0px;
+ color: #CCC;
+ cursor: auto;
+ display: inline;
+ font-family: sans-serif;
+ font-size: 15px;
+ font-style: normal;
+ font-weight: normal;
+ height: auto;
+ line-height: 22px;
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ margin-bottom: 0px;
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: 0px;
+ outline-color: #CCC;
+ outline-style: none;
+ outline-width: 0px;
+ overflow-y: visible;
+ padding-bottom: 0px;
+ padding-left: 0px;
+ padding-right: 0px;
+ padding-top: 0px;
+ position: static;
+ right: auto;
+ text-align: left;
+ text-decoration: none;
+ top: auto;
+ vertical-align: baseline;
+ width: auto;
+ z-index: auto;
+}
+
+.pub-disconnect-button:hover {
+ color: #f1831e;
+}
+
+table#option-profile {
+ padding-bottom: 8px;
+}
+
+table#option-profile td {
+ font-family: "Lucida Grande",Verdana,Arial,sans-serif;
+ vertical-align: middle;
+}
+
+table#option-profile td.radio {
+ padding-right: 20px;
+}
+
+table#option-profile td.thumbnail {
+ padding-right: 20px;
+}
+
+table#option-profile td.details {
+ font-weight: bold; color: #333333
+}
+
+table#option-fb-fanpage td {
+ font-family: "Lucida Grande",Verdana,Arial,sans-serif;
+ vertical-align: middle;
+}
+
+table#option-fb-fanpage td.thumbnail {
+ padding: 5px 20px 5px 20px;
+}
+
+table#option-fb-fanpage td.details {
+ width: 130px;
+ padding-right: 10px;
+}
+
+table#option-fb-fanpage td.details span.name {
+ font-weight: bold; color: #333333;
+}
+
+table#option-fb-fanpage td.details span.category {
+ font-size: 10px; color: #888888;
+}
+
+input.fb-options {
+ font-family: "Lucida Grande",Verdana,Arial,sans-serif;
+ font-size: 12px;
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/publicize/assets/publicize.js b/plugins/jetpack/modules/publicize/assets/publicize.js
new file mode 100644
index 00000000..bb1f8d4c
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/publicize.js
@@ -0,0 +1,108 @@
+var showOptionsPage;
+
+jQuery( function( $ ) {
+
+ showOptionsPage = function( service, nonce, connection, blogId ) {
+ tb_show( null, null, null );
+ $("body").append( "<div id='TB_load'><img src='" + tb_pathToImage + "' /></div>" );
+ $('#TB_load').show();
+
+ var query = '';
+ if ( null != connection ) {
+ query += '&connection=' + encodeURIComponent( connection );
+ }
+ if ( 'undefined' != typeof( blogId ) && null != blogId ) {
+ query += '&blog_id=' + Number( blogId );
+ }
+
+ $.post( ajaxurl, 'action=publicize_' + service + '_options_page&_wpnonce=' + nonce + query, function( response ) {
+ $("#TB_load").remove();
+
+ try {
+ var obj = jQuery.parseJSON( response );
+ if ( null != obj && 'object' == typeof( obj ) ) {
+ if ( obj.hasOwnProperty( 'fb_redirect' ) ) {
+ location.href = obj.fb_redirect + '&redirect_uri=' + encodeURIComponent( location.href );
+ return;
+ }
+ }
+ } catch (err) {
+ // Do nothing and move on
+ }
+
+ if ( response != '' ) {
+ var blogID = $( 'input[name=wpas_ajax_blog_id]' ).val();
+
+ var message = $( '<div id="wpas-ajax-' + blogID + '" class="wrap"></div>' ).append( response );
+ message.append( '<a href="#TB_inline?thickbox&height=420&width=555&inlineId=wpas-ajax-' + blogID + '" id="wpas-click-' + blogID + '" class="new-thickbox" style="display: none;"></a>' );
+ $('#wpas-message').html( message );
+
+
+ tb_init( 'a.new-thickbox' );
+ $('#wpas-click-' + blogID).click();
+
+ var tb_height = parseInt( $('#TB_ajaxContent').css('height') );
+ var content_height = $('#thickbox-content').height();
+ if ( content_height < tb_height ) {
+ var new_height = content_height + 15;
+ $('#TB_ajaxContent').css( 'height', new_height );
+
+ var new_margin = parseInt( $('#TB_window').css( 'margin-top') ) + (tb_height - new_height) / 2 + 'px'
+ $('#TB_window').css( 'margin-top', new_margin);
+ }
+
+ $('.save-options').unbind('click').click( function() {
+ var sel = $( "input[name='option']:checked" );
+ var global = $( "input[name='global']:checked" );
+
+ var connection = $(this).data('connection');
+ var token = encodeURIComponent( sel.val() );
+ var id = encodeURIComponent( sel.attr( 'id' ) );
+ var type = encodeURIComponent( sel.attr( 'data-type' ) );
+ var nonce = $(this).attr('rel');
+ var global_conn = 'off';
+ var global_nonce = '';
+
+ if ( global.length ) {
+ global_conn = 'on';
+ global_nonce = global.val();
+ }
+
+ $.post( ajaxurl, 'action=publicize_'+ service + '_options_save&connection=' + connection + '&selected_id=' + id + '&token=' + token + '&type=' + type + '&_wpnonce=' + nonce + '&global=' + global_conn + '&global_nonce=' + global_nonce, function( response ) {
+ tb_remove();
+ window.location = 'options-general.php?page=sharing';
+ } );
+
+ } );
+ }
+
+ }, 'html' );
+ }
+
+ $( 'body' ).append( '<div id="wpas-message" style="display: none"></div>' );
+ var messageDiv = $( '#wpas-message' );
+
+ $( '.wpas-posts' ).change( function() {
+ var inputs = $(this).parents( 'td:first' ).find( ':input' );
+ var _this = this;
+ var blogID = inputs.filter( '[name=wpas_ajax_blog_id]' ).val();
+
+ $( '#waiting_' + blogID ).show();
+ $.post( ajaxurl, inputs.serialize() + '&action=wpas_post', function( response ) { myblogsResponse.call( _this, blogID, response ) }, 'html' );
+ } );
+
+ $( '.options' ).unbind('click').bind( 'click', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ var service = $(this).attr('class').replace( 'options ', '' );
+
+ var blogId = null;
+ if( 'undefined' != typeof( $(this).attr('id') ) )
+ blogId = parseInt( $(this).attr('id').replace( 'options-', '' ) );
+
+ var nonce = $(this).attr('href').replace( '#nonce=', '' );
+ var connection = $(this).data( 'connection' );
+ showOptionsPage.call( this, service, nonce, connection, blogId );
+ });
+} );
diff --git a/plugins/jetpack/modules/publicize/assets/rtl/publicize-rtl.css b/plugins/jetpack/modules/publicize/assets/rtl/publicize-rtl.css
new file mode 100644
index 00000000..b56ab2fb
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/rtl/publicize-rtl.css
@@ -0,0 +1,177 @@
+/* This file was automatically generated on Dec 18 2012 19:58:18 */
+
+div#publicize-services-block {
+ display: inline-block;
+ clear: both;
+ margin-bottom: 25px;
+ background-color: #fff;
+ width: 100%;
+}
+
+/* Add the logos for the Publicize services */
+span.pub-logos {
+ float: right;
+ display: block;
+ width: 130px;
+ height: 75px;
+ margin-top: -18px;
+ margin-right: 5px;
+ vertical-align: top;
+}
+
+span#facebook { background: url( ../facebook-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+span#twitter { background: url( ../twitter-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+span#yahoo { background: url( ../yahoo-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+span#linkedin { background: url( ../linkedin-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+span#tumblr { background: url( ../tumblr-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
+
+a.publicize-profile-link, a.publicize-profile-link:visited {
+ text-decoration: none;
+}
+
+a.publicize-profile-link:hover {
+ color: #f1831e;
+}
+
+a.publicize-add-connection, a.publicize-add-connection:visited {
+ display: block;
+ vertical-align: middle;
+ text-decoration: none;
+}
+
+a.publicize-add-connection:hover {
+ color: #f1831e;
+}
+
+div.publicize-service-entry {
+ width: 100%;
+ clear: both;
+ margin-bottom: 10px;
+}
+
+div.publicize-service-left {
+ display: inline-block;
+ width: 150px;
+ vertical-align: top;
+}
+
+div.publicize-service-right {
+ display: inline-block;
+ margin-right: 5px;
+ margin-top: 5px;
+ width: 300px;
+ padding: 10px;
+ background-color: #f1f1f1;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ border-radius: 10px;
+ border: 1px solid #e5e5e5;
+}
+
+div.publicize-service-right ul {
+ margin-top: 0;
+}
+
+div.publicize-service-right li {
+ list-style-type: none;
+}
+
+.pub-disconnect-button {
+ -webkit-border-image: none;
+ border-bottom-color: #CCC;
+ border-bottom-style: none;
+ border-bottom-width: 0px;
+ border-right-color: #CCC;
+ border-right-style: none;
+ border-right-width: 0px;
+ border-left-color: #CCC;
+ border-left-style: none;
+ border-left-width: 0px;
+ border-top-color: #CCC;
+ border-top-style: none;
+ border-top-width: 0px;
+ color: #CCC;
+ cursor: auto;
+ display: inline;
+ font-family: sans-serif;
+ font-size: 15px;
+ font-style: normal;
+ font-weight: normal;
+ height: auto;
+ line-height: 22px;
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ margin-bottom: 0px;
+ margin-right: 0px;
+ margin-left: 0px;
+ margin-top: 0px;
+ outline-color: #CCC;
+ outline-style: none;
+ outline-width: 0px;
+ overflow-y: visible;
+ padding-bottom: 0px;
+ padding-right: 0px;
+ padding-left: 0px;
+ padding-top: 0px;
+ position: static;
+ left: auto;
+ text-align: right;
+ text-decoration: none;
+ top: auto;
+ vertical-align: baseline;
+ width: auto;
+ z-index: auto;
+}
+
+.pub-disconnect-button:hover {
+ color: #f1831e;
+}
+
+table#option-profile {
+ padding-bottom: 8px;
+}
+
+table#option-profile td {
+ font-family: "Lucida Grande",Verdana,Arial,sans-serif;
+ vertical-align: middle;
+}
+
+table#option-profile td.radio {
+ padding-left: 20px;
+}
+
+table#option-profile td.thumbnail {
+ padding-left: 20px;
+}
+
+table#option-profile td.details {
+ font-weight: bold; color: #333333
+}
+
+table#option-fb-fanpage td {
+ font-family: "Lucida Grande",Verdana,Arial,sans-serif;
+ vertical-align: middle;
+}
+
+table#option-fb-fanpage td.thumbnail {
+ padding: 5px 20px 5px 20px;
+}
+
+table#option-fb-fanpage td.details {
+ width: 130px;
+ padding-left: 10px;
+}
+
+table#option-fb-fanpage td.details span.name {
+ font-weight: bold; color: #333333;
+}
+
+table#option-fb-fanpage td.details span.category {
+ font-size: 10px; color: #888888;
+}
+
+input.fb-options {
+ font-family: "Lucida Grande",Verdana,Arial,sans-serif;
+ font-size: 12px;
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/publicize/assets/spinner.gif b/plugins/jetpack/modules/publicize/assets/spinner.gif
new file mode 100644
index 00000000..6e5bace6
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/spinner.gif
Binary files differ
diff --git a/plugins/jetpack/modules/publicize/assets/tumblr-logo.png b/plugins/jetpack/modules/publicize/assets/tumblr-logo.png
new file mode 100644
index 00000000..1ec62d39
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/tumblr-logo.png
Binary files differ
diff --git a/plugins/jetpack/modules/publicize/assets/twitter-logo.png b/plugins/jetpack/modules/publicize/assets/twitter-logo.png
new file mode 100644
index 00000000..6c7b89b3
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/twitter-logo.png
Binary files differ
diff --git a/plugins/jetpack/modules/publicize/assets/yahoo-logo.png b/plugins/jetpack/modules/publicize/assets/yahoo-logo.png
new file mode 100644
index 00000000..b7ffe2bb
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/assets/yahoo-logo.png
Binary files differ
diff --git a/plugins/jetpack/modules/publicize/publicize-jetpack.php b/plugins/jetpack/modules/publicize/publicize-jetpack.php
new file mode 100644
index 00000000..58e25648
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/publicize-jetpack.php
@@ -0,0 +1,578 @@
+<?php
+
+class Publicize extends Publicize_Base {
+
+ function __construct() {
+ parent::__construct();
+
+ add_action( 'load-settings_page_sharing', array( $this, 'admin_page_load' ), 9 );
+
+ add_action( 'wp_ajax_publicize_tumblr_options_page', array( $this, 'options_page_tumblr' ) );
+ add_action( 'wp_ajax_publicize_facebook_options_page', array( $this, 'options_page_facebook' ) );
+ add_action( 'wp_ajax_publicize_twitter_options_page', array( $this, 'options_page_twitter' ) );
+ add_action( 'wp_ajax_publicize_linkedin_options_page', array( $this, 'options_page_linkedin' ) );
+ add_action( 'wp_ajax_publicize_yahoo_options_page', array( $this, 'options_page_yahoo' ) );
+
+ add_action( 'wp_ajax_publicize_tumblr_options_save', array( $this, 'options_save_tumblr' ) );
+ add_action( 'wp_ajax_publicize_facebook_options_save', array( $this, 'options_save_facebook' ) );
+ add_action( 'wp_ajax_publicize_twitter_options_save', array( $this, 'options_save_twitter' ) );
+ add_action( 'wp_ajax_publicize_linkedin_options_save', array( $this, 'options_save_linkedin' ) );
+ add_action( 'wp_ajax_publicize_yahoo_options_save', array( $this, 'options_save_yahoo' ) );
+
+ add_action( 'load-settings_page_sharing', array( $this, 'force_user_connection' ) );
+
+ add_action( 'transition_post_status', array( $this, 'save_publicized' ), 10, 3 );
+ }
+
+ function force_user_connection() {
+ global $current_user;
+ $user_token = Jetpack_Data::get_access_token( $current_user->ID );
+ $is_user_connected = $user_token && !is_wp_error( $user_token );
+
+ // If the user is already connected via Jetpack, then we're good
+ if ( $is_user_connected )
+ return;
+
+ // If they're not connected, then remove the Publicize UI and tell them they need to connect first
+ global $publicize_ui;
+ remove_action( 'pre_admin_screen_sharing', array( $publicize_ui, 'admin_page' ) );
+
+ Jetpack::init()->admin_styles();
+ add_action( 'pre_admin_screen_sharing', array( $this, 'admin_page_warning' ), 1 );
+ }
+
+ function admin_page_warning() {
+ $jetpack = Jetpack::init();
+ $blog_name = get_bloginfo( 'blogname' );
+ if ( empty( $blog_name ) ) {
+ $blog_name = home_url( '/' );
+ }
+
+ ?>
+ <div id="message" class="updated jetpack-message jp-connect">
+ <div class="jetpack-wrap-container">
+ <div class="jetpack-text-container">
+ <h4>
+ <p><?php printf(
+ esc_html( wptexturize( __( "To use Publicize, you'll need to link your %s account to your WordPress.com account using the button to the right.", 'jetpack' ) ) ),
+ '<strong>' . esc_html( $blog_name ) . '</strong>'
+ ); ?></p>
+ <p><?php echo esc_html( wptexturize( __( "If you don't have a WordPress.com account yet, you can sign up for free in just a few seconds.", 'jetpack' ) ) ); ?></p>
+ </h4>
+ </div>
+ <div class="jetpack-install-container">
+ <p class="submit"><a href="<?php echo $jetpack->build_connect_url( false, menu_page_url( 'sharing', false ) ); ?>" class="button-connector" id="wpcom-connect"><?php esc_html_e( 'Link account with WordPress.com', 'jetpack' ); ?></a></p>
+ </div>
+ </div>
+ </div>
+ <?php
+ }
+
+ function get_connections( $service_name, $_blog_id = false, $_user_id = false ) {
+ $connections = Jetpack::get_option( 'publicize_connections' );
+ $connections_to_return = array();
+ if ( !empty( $connections ) && is_array( $connections ) ) {
+ if ( !empty( $connections[$service_name] ) ) {
+ foreach( $connections[$service_name] as $id => $connection ) {
+ if ( 0 == $connection['connection_data']['user_id'] || $this->user_id() == $connection['connection_data']['user_id'] ) {
+ $connections_to_return[$id] = $connection;
+ }
+ }
+ }
+ return $connections_to_return;
+ }
+ return false;
+ }
+
+ function get_connection_id( $connection ) {
+ return $connection['connection_data']['id'];
+ }
+
+ function get_connection_meta( $connection ) {
+ $connection['user_id'] = $connection['connection_data']['user_id']; // Allows for shared connections
+ return $connection;
+ }
+
+ function admin_page_load() {
+ if ( isset( $_GET['action'] ) ) {
+ if ( isset( $_GET['service'] ) )
+ $service_name = $_GET['service'];
+
+ switch ( $_GET['action'] ) {
+ case 'error':
+ add_action( 'pre_admin_screen_sharing', array( $this, 'display_connection_error' ), 9 );
+ break;
+
+ case 'request':
+ check_admin_referer( 'keyring-request', 'kr_nonce' );
+ check_admin_referer( "keyring-request-$service_name", 'nonce' );
+
+ $verification = Jetpack::create_nonce( 'publicize' );
+
+ $stats_options = get_option( 'stats_options' );
+ $wpcom_blog_id = Jetpack::get_option('id');
+ $wpcom_blog_id = !empty( $wpcom_blog_id ) ? $wpcom_blog_id : $stats_options['blog_id'];
+
+ $user = wp_get_current_user();
+ $redirect = $this->api_url( $service_name, urlencode_deep( array(
+ 'action' => 'request',
+ 'redirect_uri' => add_query_arg( array( 'action' => 'done' ), menu_page_url( 'sharing', false ) ),
+ 'for' => 'publicize', // required flag that says this connection is intended for publicize
+ 'siteurl' => site_url(),
+ 'state' => $user->ID,
+ 'blog_id' => $wpcom_blog_id,
+ 'secret_1' => $verification['secret_1'],
+ 'secret_2' => $verification['secret_2'],
+ 'eol' => $verification['eol'],
+ ) ) );
+ wp_redirect( $redirect );
+ exit;
+ break;
+
+ case 'completed':
+ // Jetpack blog requests Publicize Connections via new XML-RPC method
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client();
+ $xml->query( 'jetpack.fetchPublicizeConnections' );
+
+ if ( !$xml->isError() ) {
+ $response = $xml->getResponse();
+ Jetpack::update_option( 'publicize_connections', $response );
+ }
+ break;
+
+ case 'delete':
+ $id = $_GET['id'];
+
+ check_admin_referer( 'keyring-request', 'kr_nonce' );
+ check_admin_referer( "keyring-request-$service_name", 'nonce' );
+
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client();
+ $xml->query( 'jetpack.deletePublicizeConnection', $id );
+
+ if ( !$xml->isError() ) {
+ $response = $xml->getResponse();
+ Jetpack::update_option( 'publicize_connections', $response );
+ }
+ add_action( 'admin_notices', array( $this, 'display_disconnected' ) );
+ break;
+ }
+ }
+
+ // Errors encountered on WordPress.com's end are passed back as a code
+ if ( isset( $_GET['action'] ) && 'error' == $_GET['action'] ) {
+ // Load Jetpack's styles to handle the box
+ Jetpack::init()->admin_styles();
+ }
+ }
+
+ function display_connection_error() {
+ $code = false;
+ if ( isset( $_GET['service'] ) ) {
+ $service_name = $_GET['service'];
+ $error = sprintf( __( 'There was a problem connecting to %s to create an authorized connection. Please try again in a moment.', 'jetpack' ), Publicize::get_service_label( $service_name ) );
+ } else {
+ if ( isset( $_GET['publicize_error'] ) ) {
+ $code = strtolower( $_GET['publicize_error'] );
+ switch ( $code ) {
+ case '400':
+ $error = __( 'An invalid request was made. This normally means that something intercepted or corrupted the request from your server to the Jetpack Server. Try again and see if it works this time.', 'jetpack' );
+ break;
+ case 'secret_mismatch':
+ $error = __( 'We could not verify that your server is making an authorized request. Please try again, and make sure there is nothing interfering with requests from your server to the Jetpack Server.', 'jetpack' );
+ break;
+ case 'empty_blog_id':
+ $error = __( 'No blog_id was included in your request. Please try disconnecting Jetpack from WordPress.com and then reconnecting it. Once you have done that, try connecting Publicize again.', 'jetpack' );
+ break;
+ case 'empty_state':
+ $error = sprintf( __( 'No user information was included in your request. Please make sure that your user account has connected to Jetpack. Connect your user account by going to the <a href="%s">Jetpack page</a> within wp-admin.', 'jetpack' ), Jetpack::admin_url() );
+ break;
+ default:
+ $error = __( 'Something which should never happen, happened. Sorry about that. If you try again, maybe it will work.', 'jetpack' );
+ break;
+ }
+ } else {
+ $error = __( 'There was a problem connecting with Publicize. Please try again in a moment.', 'jetpack' );
+ }
+ }
+ // Using the same formatting/style as Jetpack::admin_notices() error
+ ?>
+ <div id="message" class="jetpack-message jetpack-err">
+ <div class="squeezer">
+ <h4><?php echo wp_kses( $error, array( 'a' => array( 'href' => true ), 'code' => true, 'strong' => true, 'br' => true, 'b' => true ) ); ?></h4>
+ <?php if ( $code ) : ?>
+ <p><?php printf( __( 'Error code: %s', 'jetpack' ), esc_html( stripslashes( $code ) ) ); ?></p>
+ <?php endif; ?>
+ </div>
+ </div>
+ <?php
+ }
+
+ function display_disconnected() {
+ echo "<div class='updated'>\n";
+ echo '<p>' . esc_html( __( 'That connection has been removed.', 'jetpack' ) ) . "</p>\n";
+ echo "</div>\n\n";
+ }
+
+ function globalization() {
+ if ( 'on' == $_REQUEST['global'] ) {
+ $id = $_REQUEST['connection'];
+
+ if ( !current_user_can( Publicize::GLOBAL_CAP ) )
+ return;
+
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client();
+ $xml->query( 'jetpack.globalizePublicizeConnection', $id, 'globalize' );
+
+ if ( !$xml->isError() ) {
+ $response = $xml->getResponse();
+ Jetpack::update_option( 'publicize_connections', $response );
+ }
+ }
+ }
+
+ /**
+ * Gets a URL to the public-api actions. Works like WP's admin_url
+ *
+ * @param string $service Shortname of a specific service.
+ * @return URL to specific public-api process
+ */
+ // on WordPress.com this is/calls Keyring::admin_url
+ function api_url( $service = false, $params = array() ) {
+ $url = apply_filters( 'publicize_api_url', 'https://public-api.wordpress.com/connect/?jetpack=publicize' );
+
+ if ( $service )
+ $url = add_query_arg( array( 'service' => $service ), $url );
+
+ if ( count ( $params ) )
+ $url = add_query_arg( $params, $url );
+
+ return $url;
+ }
+
+ function connect_url( $service_name ) {
+ return add_query_arg( array(
+ 'action' => 'request',
+ 'service' => $service_name,
+ 'kr_nonce' => wp_create_nonce( 'keyring-request' ),
+ 'nonce' => wp_create_nonce( "keyring-request-$service_name" ),
+ ), menu_page_url( 'sharing', false ) );
+ }
+
+ function disconnect_url( $service_name, $id ) {
+ return add_query_arg( array (
+ 'action' => 'delete',
+ 'service' => $service_name,
+ 'id' => $id,
+ 'kr_nonce' => wp_create_nonce( 'keyring-request' ),
+ 'nonce' => wp_create_nonce( "keyring-request-$service_name" ),
+ ), menu_page_url( 'sharing', false ) );
+ }
+
+ function get_services( $filter ) {
+ if ( !in_array( $filter, array( 'all', 'connected' ) ) )
+ $filter = 'all';
+
+ $services = array(
+ 'facebook' => array(),
+ 'twitter' => array(),
+ 'linkedin' => array(),
+ 'tumblr' => array(),
+ 'yahoo' => array(),
+ );
+
+ if ( 'all' == $filter ) {
+ return $services;
+ } else {
+ $connected_services = array();
+ foreach ( $services as $service => $empty ) {
+ $connections = $this->get_connections( $service );
+ if ( $connections )
+ $connected_services[$service] = $connections;
+ }
+ return $connected_services;
+ }
+ }
+
+ function get_connection( $service, $id, $_blog_id = false, $_user_id = false ) {
+ // Stub
+ }
+
+ function flag_post_for_publicize( $new_status, $old_status, $post ) {
+ // Stub only. Doesn't need to do anything on Jetpack Client
+ }
+
+ /**
+ * Save a flag locally to indicate that this post has already been Publicized via the selected
+ * connections.
+ */
+ function save_publicized( $new_status, $old_status, $post ) {
+ // Only do this when a post transitions to being published
+ if ( 'publish' == $new_status && 'publish' != $old_status ) {
+ update_post_meta( $post->ID, $this->POST_DONE . 'all', true );
+ }
+ }
+
+ /**
+ * Options Code
+ */
+
+ function options_page_facebook() {
+ $connected_services = Jetpack::get_option( 'publicize_connections' );
+ $connection = $connected_services['facebook'][$_REQUEST['connection']];
+ $options_to_show = $connection['connection_data']['meta']['options_responses'];
+
+ // Nonce check
+ check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
+
+ $me = $options_to_show[0];
+ $pages = $options_to_show[1]['data'];
+
+ $profile_checked = true;
+ $page_selected = false;
+
+ if ( !empty( $connection['connection_data']['meta']['facebook_page'] ) ) {
+ $found = false;
+ if ( is_array( $pages->data ) ) {
+ foreach ( $pages->data as $page ) {
+ if ( $page->id == $connection['connection_data']['meta']['facebook_page'] ) {
+ $found = true;
+ break;
+ }
+ }
+ }
+
+ if ( $found ) {
+ $profile_checked = false;
+ $page_selected = $connection['connection_data']['meta']['facebook_page'];
+ }
+ }
+
+ ?>
+
+ <div id="thickbox-content">
+
+ <?php
+ ob_start();
+ Publicize_UI::connected_notice( 'Facebook' );
+ $update_notice = ob_get_clean();
+
+ if ( ! empty( $update_notice ) )
+ echo $update_notice;
+ ?>
+
+ <?php if ( !empty( $me['name'] ) ) : ?>
+ <p><?php printf(
+ esc_html__( 'Publicize to my %s:', 'jetpack' ),
+ '<strong>' . esc_html__( 'Facebook Wall', 'jetpack' ) . '</strong>'
+ ); ?></p>
+ <table id="option-profile">
+ <tbody>
+ <tr>
+ <td class="radio"><input type="radio" name="option" data-type="profile" id="<?php echo esc_attr( $me['id'] ) ?>" value="" <?php checked( $profile_checked, true ); ?> /></td>
+ <td class="thumbnail"><label for="<?php echo esc_attr( $me['id'] ) ?>"><img src="<?php echo esc_url( $me['picture']['data']['url'] ) ?>" width="50" height="50" /></label></td>
+ <td class="details"><label for="<?php echo esc_attr( $me['id'] ) ?>"><?php echo esc_html( $me['name'] ) ?></label></td>
+ </tr>
+ </tbody>
+ </table>
+ <?php endif; ?>
+
+ <?php if ( $pages ) : ?>
+
+ <p><?php printf(
+ esc_html__( 'Publicize to my %s:', 'jetpack' ),
+ '<strong>' . esc_html__( 'Facebook Page', 'jetpack' ) . '</strong>'
+ ); ?></p>
+ <table id="option-fb-fanpage">
+ <tbody>
+
+ <?php foreach ( $pages as $i => $page ) : ?>
+ <?php if ( ! isset( $page['perms'] ) ) { continue; } ?>
+ <?php if ( ! ( $i % 2 ) ) : ?>
+ <tr>
+ <?php endif; ?>
+ <td class="radio"><input type="radio" name="option" data-type="page" id="<?php echo esc_attr( $page['id'] ) ?>" value="<?php echo esc_attr( $page['id'] ) ?>" <?php checked( $page_selected && $page_selected == $page['id'], true ); ?> /></td>
+ <td class="thumbnail"><label for="<?php echo esc_attr( $page['id'] ) ?>"><img src="<?php echo esc_url( str_replace( '_s', '_q', $page['picture']['data']['url'] ) ) ?>" width="50" height="50" /></label></td>
+ <td class="details">
+ <label for="<?php echo esc_attr( $page['id'] ) ?>">
+ <span class="name"><?php echo esc_html( $page['name'] ) ?></span><br/>
+ <span class="category"><?php echo esc_html( $page['category'] ) ?></span>
+ </label>
+ </td>
+ <?php if ( ( $i % 2 ) || ( $i == count( $pages ) - 1 ) ): ?>
+ </tr>
+ <?php endif; ?>
+ <?php endforeach; ?>
+
+ </tbody>
+ </table>
+
+ <?php endif; ?>
+
+ <?php Publicize_UI::global_checkbox( 'facebook', $_REQUEST['connection'] ); ?>
+
+ <p style="text-align: center;">
+ <input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>" class="button fb-options save-options" name="save" data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>" rel="<?php echo wp_create_nonce('save_fb_token_' . $_REQUEST['connection'] ) ?>" />
+ </p><br/>
+ </div>
+
+ <?php
+ }
+
+ function options_save_facebook() {
+ // Nonce check
+ check_admin_referer( 'save_fb_token_' . $_REQUEST['connection'] );
+
+ $id = $_POST['connection'];
+
+ // Check for a numeric page ID
+ $page_id = $_POST['selected_id'];
+ if ( !ctype_digit( $page_id ) )
+ die( 'Security check' );
+
+ if ( isset( $_POST['selected_id'] ) && 'profile' == $_POST['type'] ) {
+ // Publish to User Wall/Profile
+ $options = array(
+ 'facebook_page' => null,
+ 'facebook_profile' => true
+ );
+
+ } else {
+ if ( 'page' != $_POST['type'] || !isset( $_POST['selected_id'] ) ) {
+ return;
+ }
+
+ // Publish to Page
+ $options = array(
+ 'facebook_page' => $page_id,
+ 'facebook_profile' => null
+ );
+ }
+
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client();
+ $xml->query( 'jetpack.setPublicizeOptions', $id, $options );
+
+ if ( !$xml->isError() ) {
+ $response = $xml->getResponse();
+ Jetpack::update_option( 'publicize_connections', $response );
+ }
+
+ $this->globalization();
+ }
+
+ function options_page_tumblr() {
+ // Nonce check
+ check_admin_referer( 'options_page_tumblr_' . $_REQUEST['connection'] );
+
+ $connected_services = Jetpack::get_option( 'publicize_connections' );
+ $connection = $connected_services['tumblr'][$_POST['connection']];
+ $options_to_show = $connection['connection_data']['meta']['options_responses'];
+ $request = $options_to_show[0];
+
+ $blogs = $request['response']['user']['blogs'];
+
+ $blog_selected = false;
+
+ if ( !empty( $connection['connection_data']['meta']['tumblr_base_hostname'] ) ) {
+ foreach ( $blogs as $blog ) {
+ if ( $connection['connection_data']['meta']['tumblr_base_hostname'] == $this->get_basehostname( $blog['url'] ) ) {
+ $blog_selected = $connection['connection_data']['meta']['tumblr_base_hostname'];
+ break;
+ }
+ }
+
+ }
+
+ // Use their Primary blog if they haven't selected one yet
+ if ( !$blog_selected ) {
+ foreach ( $blogs as $blog ) {
+ if ( $blog['primary'] )
+ $blog_selected = $this->get_basehostname( $blog['url'] );
+ }
+ } ?>
+
+ <div id="thickbox-content">
+
+ <?php
+ ob_start();
+ Publicize_UI::connected_notice( 'Tumblr' );
+ $update_notice = ob_get_clean();
+
+ if ( ! empty( $update_notice ) )
+ echo $update_notice;
+ ?>
+
+ <p><?php printf(
+ esc_html__( 'Publicize to my %s:', 'jetpack' ),
+ '<strong>' . esc_html__( 'Tumblr blog', 'jetpack' ) . '</strong>'
+ ); ?></p>
+
+ <ul id="option-tumblr-blog">
+
+ <?php
+ foreach ( $blogs as $blog ) {
+ $url = $this->get_basehostname( $blog['url'] ); ?>
+ <li>
+ <input type="radio" name="option" data-type="blog" id="<?php echo esc_attr( $url ) ?>" value="<?php echo esc_attr( $url ) ?>" <?php checked( $blog_selected == $url, true ); ?> />
+ <label for="<?php echo esc_attr( $url ) ?>"><span class="name"><?php echo esc_html( $blog['title'] ) ?></span></label>
+ </li>
+ <?php } ?>
+
+ </ul>
+
+ <?php Publicize_UI::global_checkbox( 'tumblr', $_REQUEST['connection'] ); ?>
+
+ <p style="text-align: center;">
+ <input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>" class="button tumblr-options save-options" name="save" data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>" rel="<?php echo wp_create_nonce( 'save_tumblr_blog_' . $_REQUEST['connection'] ) ?>" />
+ </p> <br />
+ </div>
+
+ <?php
+ }
+
+ function get_basehostname( $url ) {
+ return parse_url( $url, PHP_URL_HOST );
+ }
+
+ function options_save_tumblr() {
+ // Nonce check
+ check_admin_referer( 'save_tumblr_blog_' . $_REQUEST['connection'] );
+
+ $id = $_POST['connection'];
+
+ $options = array( 'tumblr_base_hostname' => $_POST['selected_id'] );
+
+ Jetpack::load_xml_rpc_client();
+ $xml = new Jetpack_IXR_Client();
+ $xml->query( 'jetpack.setPublicizeOptions', $id, $options );
+
+ if ( !$xml->isError() ) {
+ $response = $xml->getResponse();
+ Jetpack::update_option( 'publicize_connections', $response );
+ }
+
+ $this->globalization();
+ }
+
+ function options_page_twitter() { Publicize_UI::options_page_other( 'twitter' ); }
+ function options_page_linkedin() { Publicize_UI::options_page_other( 'linkedin' ); }
+ function options_page_yahoo() { Publicize_UI::options_page_other( 'yahoo' ); }
+
+ function options_save_twitter() { $this->options_save_other( 'twitter' ); }
+ function options_save_linkedin() { $this->options_save_other( 'linkedin' ); }
+ function options_save_yahoo() { $this->options_save_other( 'yahoo' ); }
+
+ function options_save_other( $service_name ) {
+ // Nonce check
+ check_admin_referer( 'save_' . $service_name . '_token_' . $_REQUEST['connection'] );
+ $this->globalization();
+ }
+
+ // stub
+ function refresh_tokens_message() {
+
+ }
+}
diff --git a/plugins/jetpack/modules/publicize/publicize.php b/plugins/jetpack/modules/publicize/publicize.php
new file mode 100644
index 00000000..16d4541c
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/publicize.php
@@ -0,0 +1,328 @@
+<?php
+
+abstract class Publicize_Base {
+
+ /**
+ * Services that are currently connected to the given user
+ * through publicize.
+ */
+ var $connected_services = array();
+
+ /**
+ * Sservices that are supported by publicize. They don't
+ * neccessarly need to be connected to the current user.
+ */
+ var $services;
+
+ /**
+ * key names for post meta
+ */
+ var $ADMIN_PAGE = 'wpas';
+ var $POST_MESS = '_wpas_mess';
+ var $POST_SKIP = '_wpas_skip_'; // connection id appended to indicate that a connection should NOT be publicized to
+ var $POST_DONE = '_wpas_done_'; // connection id appended to indicate a connection has already been publicized to
+ var $USER_AUTH = 'wpas_authorize';
+ var $USER_OPT = 'wpas_';
+ var $PENDING = '_publicize_pending'; // ready for Publicize to do its thing
+ var $POST_SERVICE_DONE = '_publicize_done_external'; // array of external ids where we've Publicized
+
+ /**
+ * default pieces of the message used in constructing the
+ * content pushed out to other social networks
+ */
+ var $default_prefix = '';
+ var $default_message = '%title%';
+ var $default_suffix = ' %url%';
+
+ /**
+ * What WP capability is require to create/delete global connections?
+ * All users with this cap can unglobalize all other global connections, and globalize any of their own
+ * Globalized connections cannot be unselected by users without this capability when publishing
+ */
+ const GLOBAL_CAP = 'edit_others_posts';
+
+ /**
+ * Sets up the basics of Publicize
+ */
+ function __construct() {
+ $this->default_message = Publicize_Util::build_sprintf( array(
+ apply_filters( 'wpas_default_message', $this->default_message ),
+ 'title',
+ 'url',
+ ) );
+
+ $this->default_prefix = Publicize_Util::build_sprintf( array(
+ apply_filters( 'wpas_default_prefix', $this->default_prefix ),
+ 'url',
+ ) );
+
+ $this->default_suffix = Publicize_Util::build_sprintf( array(
+ apply_filters( 'wpas_default_suffix', $this->default_suffix ),
+ 'url',
+ ) );
+
+
+ // stage 1 and 2 of 3-stage Publicize. Flag for Publicize on creation, save meta,
+ // then check meta and publicze based on that. stage 3 implemented on wpcom
+ add_action( 'transition_post_status', array( $this, 'flag_post_for_publicize' ), 10, 3 );
+ add_action( 'save_post', array( &$this, 'save_meta' ), 20, 2 );
+ }
+
+ /**
+ * Functions to be implemented by the extended class (publicize-wpcom or publicize-jetpack)
+ */
+ abstract function get_connection_id( $connection );
+ abstract function connect_url( $service_name );
+ abstract function disconnect_url( $service_name, $id );
+ abstract function get_connection_meta( $connection );
+ abstract function get_services( $filter );
+ abstract function get_connections( $service, $_blog_id = false, $_user_id = false );
+ abstract function get_connection( $service, $id, $_blog_id = false, $_user_id = false );
+ abstract function flag_post_for_publicize( $new_status, $old_status, $post );
+
+ /**
+ * Shared Functions
+ */
+
+ /**
+ * Returns an external URL to the connection's profile
+ */
+ function get_profile_link( $service_name, $c ) {
+ $cmeta = $this->get_connection_meta( $c );
+
+ if ( isset( $cmeta['connection_data']['meta']['link'] ) ) {
+ return $cmeta['connection_data']['meta']['link'];
+ } elseif ( 'facebook' == $service_name && isset( $cmeta['connection_data']['meta']['facebook_page'] ) ) {
+ return 'http://facebook.com/' . $cmeta['connection_data']['meta']['facebook_page'];
+ } elseif ( 'facebook' == $service_name ) {
+ return 'http://www.facebook.com/' . $cmeta['external_id'];
+ } elseif ( 'tumblr' == $service_name && isset( $cmeta['connection_data']['meta']['tumblr_base_hostname'] ) ) {
+ return 'http://' . $cmeta['connection_data']['meta']['tumblr_base_hostname'];
+ } elseif ( 'twitter' == $service_name ) {
+ return 'http://twitter.com/' . substr( $cmeta['external_display'], 1 ); // Has a leading '@'
+ } else if ( 'yahoo' == $service_name ) {
+ return 'http://profile.yahoo.com/' . $cmeta['external_id'];
+ } else if ( 'linkedin' == $service_name ) {
+ if ( !isset( $cmeta['connection_data']['meta']['profile_url'] ) ) {
+ return false;
+ }
+
+ $profile_url_query = parse_url( $cmeta['connection_data']['meta']['profile_url'], PHP_URL_QUERY );
+ wp_parse_str( $profile_url_query, $profile_url_query_args );
+ if ( !isset( $profile_url_query_args['key'] ) ) {
+ return false;
+ }
+
+ return esc_url_raw( add_query_arg( 'id', urlencode( $profile_url_query_args['key'] ), 'http://www.linkedin.com/profile/view' ) );
+ } else {
+ return false; // no fallback. we just won't link it
+ }
+ }
+
+ /**
+ * Returns a display name for the connection
+ */
+ function get_display_name( $service_name, $c ) {
+ $cmeta = $this->get_connection_meta( $c );
+
+ if ( isset( $cmeta['connection_data']['meta']['display_name'] ) ) {
+ return $cmeta['connection_data']['meta']['display_name'];
+ } elseif ( $service_name == 'tumblr' && isset( $cmeta['connection_data']['meta']['tumblr_base_hostname'] ) ) {
+ return $cmeta['connection_data']['meta']['tumblr_base_hostname'];
+ } elseif ( $service_name == 'twitter' ) {
+ return $cmeta['external_display'];
+ } else {
+ $connection_display = $cmeta['external_display'];
+ if ( empty( $connection_display ) )
+ $connection_display = $cmeta['external_name'];
+ return $connection_display;
+ }
+ }
+
+ function get_service_label( $service_name ) {
+ switch ( $service_name ) {
+ case 'yahoo':
+ return 'Yahoo!';
+ break;
+ case 'linkedin':
+ return 'LinkedIn';
+ break;
+ case 'twitter':
+ case 'facebook':
+ case 'tumblr':
+ default:
+ return ucfirst( $service_name );
+ break;
+ }
+ }
+
+ function show_options_popup( $service_name, $c ) {
+ $cmeta = $this->get_connection_meta( $c );
+
+ // always show if no selection has been made for facebook
+ if ( 'facebook' == $service_name && empty( $cmeta['connection_data']['meta']['facebook_profile'] ) && empty( $cmeta['connection_data']['meta']['facebook_page'] ) )
+ return true;
+
+ // always show if no selection has been made for tumblr
+ if ( 'tumblr' == $service_name && empty ( $cmeta['connection_data']['meta']['tumblr_base_hostname'] ) )
+ return true;
+
+ // if we have the specific conncetion info..
+ if ( isset( $_GET['id'] ) ) {
+ if ( $cmeta['connection_data']['id'] == $_GET['id'] )
+ return true;
+ } else {
+ // otherwise, just show if this is the completed step / first load
+ if ( !empty( $_GET['action'] ) && 'completed' == $_GET['action'] && !empty( $_GET['service'] ) && $service_name == $_GET['service'] && ! in_array( $_GET['service'], array( 'facebook', 'tumblr' ) ) )
+ return true;
+ }
+
+ return false;
+ }
+
+ function user_id() {
+ global $current_user;
+ return $current_user->ID;
+ }
+
+ function blog_id() {
+ return get_current_blog_id();
+ }
+
+ /**
+ * Returns true if a user has a connection to a particular service, false otherwise
+ */
+ function is_enabled( $service, $_blog_id = false, $_user_id = false ) {
+ if ( !$_blog_id )
+ $_blog_id = $this->blog_id();
+
+ if ( !$_user_id )
+ $_user_id = $this->user_id();
+
+ $connections = $this->get_connections( $service, $_blog_id, $_user_id );
+ return ( is_array( $connections ) && count( $connections ) > 0 ? true : false );
+ }
+
+ /**
+ * Fires when a post is saved, checks conditions and saves state in postmeta so that it
+ * can be picked up later by @see ::publicize_post()
+ */
+ function save_meta( $post_id, $post ) {
+ $cron_user = null;
+ $submit_post = true;
+
+ // don't do anything if its not actually a post
+ if ( 'post' !== $post->post_type )
+ return;
+
+ // Don't Publicize during certain contexts:
+
+ // - import
+ if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING )
+ $submit_post = false;
+
+ // - on quick edit, autosave, etc but do fire on p2, quickpress, and instapost ajax
+ if (
+ defined( 'DOING_AJAX' )
+ &&
+ DOING_AJAX
+ &&
+ !did_action( 'p2_ajax' )
+ &&
+ !did_action( 'wp_ajax_json_quickpress_post' )
+ &&
+ !did_action( 'wp_ajax_instapost_publish' )
+ &&
+ !did_action( 'wp_ajax_post_reblog' )
+ ) {
+ $submit_post = false;
+ }
+
+ // - bulk edit
+ if ( isset( $_GET['bulk_edit'] ) )
+ $submit_post = false;
+
+ // - API/XML-RPC Test Posts
+ if (
+ (
+ defined( 'XMLRPC_REQUEST' )
+ &&
+ XMLRPC_REQUEST
+ ||
+ defined( 'APP_REQUEST' )
+ &&
+ APP_REQUEST
+ )
+ &&
+ 0 === strpos( $post->post_title, 'Temporary Post Used For Theme Detection' )
+ ) {
+ $submit_post = false;
+ }
+
+ // only work with certain statuses (avoids inherits, auto drafts etc)
+ if ( !in_array( $post->post_status, array( 'publish', 'draft', 'future' ) ) )
+ $submit_post = false;
+
+ // don't publish password protected posts
+ if ( '' !== $post->post_password )
+ $submit_post = false;
+
+ // Did this request happen via wp-admin?
+ $from_web = 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && isset( $_POST[$this->ADMIN_PAGE] );
+
+ if ( ( $from_web || defined( 'POST_BY_EMAIL' ) ) && !empty( $_POST['wpas_title'] ) )
+ update_post_meta( $post_id, $this->POST_MESS, trim( stripslashes( $_POST['wpas_title'] ) ) );
+
+ // change current user to provide context for get_services() if we're running during cron
+ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
+ $cron_user = (int) $GLOBALS['user_ID'];
+ wp_set_current_user( $post->post_author );
+ }
+
+ /**
+ * In this phase, we mark connections that we want to SKIP. When Publicize is actually triggered,
+ * it will Publicize to everything *except* those marked for skipping.
+ */
+ foreach ( (array) $this->get_services( 'connected' ) as $service_name => $connections ) {
+ foreach ( $connections as $connection ) {
+ if ( false == apply_filters( 'wpas_submit_post?', $submit_post, $post_id, $service_name ) ) {
+ delete_post_meta( $post_id, $this->PENDING );
+ continue;
+ }
+
+ if ( !empty( $connection->unique_id ) )
+ $unique_id = $connection->unique_id;
+ else if ( !empty( $connection['connection_data']['token_id'] ) )
+ $unique_id = $connection['connection_data']['token_id'];
+
+ // This was a wp-admin request, so we need to check the state of checkboxes
+ if ( $from_web ) {
+ // We *unchecked* this stream from the admin page, or it's set to readonly, or it's a new addition
+ if ( empty( $_POST[$this->ADMIN_PAGE]['submit'][$unique_id] ) ) {
+ // Also make sure that the service-specific input isn't there.
+ // If the user connected to a new service 'in-page' then a hidden field with the service
+ // name is added, so we just assume they wanted to Publicize to that service.
+ if ( empty( $_POST[$this->ADMIN_PAGE]['submit'][$service_name] ) ) {
+ // Nothing seems to be checked, so we're going to mark this one to be skipped
+ update_post_meta( $post_id, $this->POST_SKIP . $unique_id, 1 );
+ continue;
+ }
+ } else {
+ // The checkbox for this connection is explicitly checked -- make sure we DON'T skip it
+ delete_post_meta( $post_id, $this->POST_SKIP . $unique_id );
+ }
+ }
+
+ // Users may hook in here and do anything else they need to after meta is written,
+ // and before the post is processed for Publicize.
+ do_action( 'publicize_save_meta', $submit_post, $post_id, $service_name, $connection );
+ }
+ }
+
+ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
+ wp_set_current_user( $cron_user );
+ }
+
+ // Next up will be ::publicize_post()
+ }
+}
diff --git a/plugins/jetpack/modules/publicize/ui.php b/plugins/jetpack/modules/publicize/ui.php
new file mode 100644
index 00000000..d9d2b37c
--- /dev/null
+++ b/plugins/jetpack/modules/publicize/ui.php
@@ -0,0 +1,545 @@
+<?php
+
+/**
+* Only user facing pieces of Publicize are found here.
+*/
+class Publicize_UI {
+
+ /**
+ * Contains an instance of class 'publicize' which loads Keyring, sets up services, etc.
+ */
+ var $publicize;
+
+ /**
+ * Hooks into WordPress to display the various pieces of UI and load our assets
+ */
+ function __construct() {
+ global $publicize;
+
+ $this->publicize = $publicize = new Publicize;
+
+ // assets (css, js)
+ add_action( 'load-settings_page_sharing', array( &$this, 'load_assets' ) );
+ add_action( 'admin_head-post.php', array( &$this, 'post_page_metabox_assets' ) );
+ add_action( 'admin_head-post-new.php', array( &$this, 'post_page_metabox_assets' ) );
+
+ // management of publicize (sharing screen, ajax/lightbox popup, and metabox on post screen)
+ add_action( 'pre_admin_screen_sharing', array( &$this, 'admin_page' ) );
+ add_action( 'post_submitbox_misc_actions', array( &$this, 'post_page_metabox' ) );
+ }
+
+ /**
+ * If the ShareDaddy plugin is not active we need to add the sharing settings page to the menu still
+ */
+ function sharing_menu() {
+ add_submenu_page( 'options-general.php', __( 'Sharing Settings', 'jetpack' ), __( 'Sharing', 'jetpack' ), 'publish_posts', 'sharing', array( &$this, 'management_page' ) );
+ }
+
+
+ /**
+ * Management page to load if Sharedaddy is not active so the 'pre_admin_screen_sharing' action exists.
+ */
+ function management_page() { ?>
+ <div class="wrap">
+ <div class="icon32" id="icon-options-general"><br /></div>
+ <h2><?php _e( 'Sharing Settings', 'jetpack' ); ?></h2>
+
+ <?php do_action( 'pre_admin_screen_sharing' ) ?>
+
+ </div> <?php
+ }
+
+ /**
+ * styling for the sharing screen and popups
+ * JS for the options and switching
+ */
+ function load_assets() {
+ wp_enqueue_script(
+ 'publicize',
+ plugins_url( 'assets/publicize.js', __FILE__ ),
+ array( 'jquery', 'thickbox' ),
+ '20121019'
+ );
+
+ wp_enqueue_style(
+ 'publicize',
+ plugins_url( 'assets/publicize.css', __FILE__ ),
+ array(),
+ '20120925'
+ );
+
+ add_thickbox();
+ }
+
+ function connected_notice( $service_name ) { ?>
+ <div class='updated'>
+ <p><?php printf( __( 'You have successfully connected your blog with your %s account.', 'jetpack' ), Publicize::get_service_label( $service_name ) ); ?></p>
+ </div><?php
+ }
+
+ /**
+ * Lists the current user's publicized accounts for the blog
+ * looks exactly like Publicize v1 for now, UI and functionality updates will come after the move to keyring
+ */
+ function admin_page() {
+ $_blog_id = get_current_blog_id();
+ ?>
+
+ <form action="" id="publicize-form">
+ <h3 id="publicize"><?php _e( 'Publicize', 'jetpack' ) ?></h3>
+ <p>
+ <?php esc_html_e( 'Connect your blog to popular social networking sites and automatically share new posts with your friends.', 'jetpack' ) ?>
+ <?php esc_html_e( 'You can make a connection for just yourself or for all users on your blog. Shared connections are marked with the (Shared) text.', 'jetpack' ); ?>
+ </p>
+
+ <?php
+ if ( $this->in_jetpack )
+ $doc_link = "http://jetpack.me/support/publicize/";
+ else
+ $doc_link = "http://en.support.wordpress.com/publicize/";
+ ?>
+
+ <p>&rarr; <a href="<?php echo esc_url( $doc_link ); ?>"><?php esc_html_e( 'More information on using Publicize.', 'jetpack' ); ?></a></p>
+
+ <div id="publicize-services-block">
+ <?php
+ foreach ( $this->publicize->get_services( 'all' ) as $name => $service ) :
+ $connect_url = $this->publicize->connect_url( $name );
+ ?>
+ <div class="publicize-service-entry">
+ <div id="<?php echo esc_attr( $name ); ?>" class="publicize-service-left">
+ <a href="<?php echo esc_url( $connect_url ); ?>"><span class="pub-logos" id="<?php echo esc_attr( $name ); ?>">&nbsp;</span></a>
+ </div>
+
+ <div class="publicize-service-right">
+ <?php if ( $this->publicize->is_enabled( $name ) && $connections = $this->publicize->get_connections( $name ) ) : ?>
+ <ul>
+ <?php
+ foreach( $connections as $c ) :
+ $id = $this->publicize->get_connection_id( $c );
+ $disconnect_url = $this->publicize->disconnect_url( $name, $id );
+
+ $cmeta = $this->publicize->get_connection_meta( $c );
+ $profile_link = $this->publicize->get_profile_link( $name, $c );
+ $connection_display = $this->publicize->get_display_name( $name, $c );
+
+ $options_nonce = wp_create_nonce( 'options_page_' . $name . '_' . $id ); ?>
+
+ <?php if ( $this->publicize->show_options_popup( $name, $c ) ): ?>
+ <script type="text/javascript">
+ jQuery(document).ready( function($) {
+ showOptionsPage.call(
+ this,
+ '<?php echo esc_js( $name ); ?>',
+ '<?php echo esc_js( $options_nonce ); ?>',
+ '<?php echo esc_js( $id ); ?>'
+ );
+ } );
+ </script>
+ <?php endif; ?>
+
+ <li>
+ <?php
+ if ( !empty( $profile_link ) ) : ?>
+ <a class="publicize-profile-link" href="<?php echo esc_url( $profile_link ); ?>">
+ <?php echo esc_html( $connection_display ); ?>
+ </a><?php
+ else :
+ echo esc_html( $connection_display );
+ endif;
+ ?>
+
+ <?php if ( 0 == $cmeta['connection_data']['user_id'] ) : ?>
+ <small>(<?php esc_html_e( 'Shared', 'jetpack' ); ?>)</small>
+
+ <?php if ( current_user_can( Publicize::GLOBAL_CAP ) ) : ?>
+ <a class="pub-disconnect-button" title="<?php esc_html_e( 'Disconnect', 'jetpack' ); ?>" href="<?php echo esc_url( $disconnect_url ); ?>">×</a>
+ <?php endif; ?>
+
+ <?php else : ?>
+ <a class="pub-disconnect-button" title="<?php esc_html_e( 'Disconnect', 'jetpack' ); ?>" href="<?php echo esc_url( $disconnect_url ); ?>">×</a>
+ <?php endif; ?>
+ </li>
+
+ <?php
+ endforeach;
+ ?>
+ </ul>
+ <?php endif; ?>
+ <a id="<?php echo esc_attr( $name ); ?>" class="publicize-add-connection" href="<?php echo esc_url( $connect_url); ?>"><?php echo esc_html( sprintf( __( 'Add new %s connection.', 'jetpack' ), $this->publicize->get_service_label( $name ) ) ); ?></a>
+ </div>
+ </div>
+ <?php endforeach; ?>
+ </div>
+
+ <?php wp_nonce_field( "wpas_posts_{$_blog_id}", "_wpas_posts_{$_blog_id}_nonce" ); ?>
+ <input type="hidden" id="wpas_ajax_blog_id" name="wpas_ajax_blog_id" value="<?php echo $_blog_id; ?>" />
+ </form><?php
+
+ }
+
+ function global_checkbox( $service_name, $id ) {
+ if ( current_user_can( Publicize::GLOBAL_CAP ) ) : ?>
+ <p>
+ <input id="globalize_<?php echo $service_name; ?>" type="checkbox" name="global" value="<?php echo wp_create_nonce( 'publicize-globalize-' . $id ) ?>" />
+ <label for="globalize_<?php echo $service_name; ?>"><?php _e( 'Make this connection available to all users of this blog?', 'jetpack' ); ?></label>
+ </p>
+ <?php endif;
+ }
+
+ function broken_connection( $service_name, $id ) { ?>
+ <div id="thickbox-content">
+ <div class='error'>
+ <p><?php printf( __( 'There was a problem connecting to %s. Please disconnect and try again.', 'jetpack' ), Publicize::get_service_label( $service_name ) ); ?></p>
+ </div>
+ </div><?php
+ }
+
+ function options_page_other( $service_name ) {
+ // Nonce check
+ check_admin_referer( "options_page_{$service_name}_" . $_REQUEST['connection'] );
+ ?>
+ <div id="thickbox-content">
+ <?php
+ ob_start();
+ Publicize_UI::connected_notice( $service_name );
+ $update_notice = ob_get_clean();
+ if ( ! empty( $update_notice ) )
+ echo $update_notice;
+ ?>
+
+ <?php Publicize_UI::global_checkbox( $service_name, $_REQUEST['connection'] ); ?>
+
+ <p style="text-align: center;">
+ <input type="submit" value="<?php esc_attr_e( 'OK', 'jetpack' ) ?>" class="button <?php echo $service_name; ?>-options save-options" name="save" data-connection="<?php echo esc_attr( $_REQUEST['connection'] ); ?>" rel="<?php echo wp_create_nonce( 'save_'.$service_name.'_token_' . $_REQUEST['connection'] ) ?>" />
+ </p> <br />
+ </div>
+ <?php
+ }
+
+ /**
+ * CSS for styling the publicize message box and counter that displays on the post page.
+ * There is also some Javascript for length counting and some basic display effects.
+ */
+ function post_page_metabox_assets() {
+ global $post;
+ $user_id = empty( $post->post_author ) ? $GLOBALS['user_ID'] : $post->post_author;
+
+ $default_prefix = $this->publicize->default_prefix;
+ $default_prefix = preg_replace( '/%([0-9])\$s/', "' + %\\1\$s + '", esc_js( $default_prefix ) );
+
+ $default_message = $this->publicize->default_message;
+ $default_message = preg_replace( '/%([0-9])\$s/', "' + %\\1\$s + '", esc_js( $default_message ) );
+
+ $default_suffix = $this->publicize->default_suffix;
+ $default_suffix = preg_replace( '/%([0-9])\$s/', "' + %\\1\$s + '", esc_js( $default_suffix ) ); ?>
+
+<script type="text/javascript">
+jQuery( function($) {
+ var wpasTitleCounter = $( '#wpas-title-counter' ),
+ wpasTwitterCheckbox = $( '.wpas-submit-twitter' ).size(),
+ wpasTitle = $('#wpas-title').keyup( function() {
+ var length = wpasTitle.val().length;
+ wpasTitleCounter.text( length );
+ if ( wpasTwitterCheckbox && length > 140 ) {
+ wpasTitleCounter.addClass( 'wpas-twitter-length-limit' );
+ } else {
+ wpasTitleCounter.removeClass( 'wpas-twitter-length-limit' );
+ }
+ } ),
+ authClick = false;
+
+ $('#publicize-disconnected-form-show').click( function() {
+ $('#publicize-form').slideDown( 'fast' );
+ $(this).hide();
+ } );
+
+ $('#publicize-disconnected-form-hide').click( function() {
+ $('#publicize-form').slideUp( 'fast' );
+ $('#publicize-disconnected-form-show').show();
+ } );
+
+ $('#publicize-form-edit').click( function() {
+ $('#publicize-form').slideDown( 'fast', function() {
+ wpasTitle.focus();
+ if ( !wpasTitle.text() ) {
+ var url = $('#shortlink').size() ? $('#shortlink').val() : '';
+
+ var defaultMessage = $.trim( '<?php printf( $default_prefix, 'url' ); printf( $default_message, '$("#title").val()', 'url' ); printf( $default_suffix, 'url' ); ?>' );
+
+ wpasTitle.append( defaultMessage.replace( /<[^>]+>/g,'') );
+
+ var selBeg = defaultMessage.indexOf( $("#title").val() );
+ if ( selBeg < 0 ) {
+ selBeg = 0;
+ selEnd = 0;
+ } else {
+ selEnd = selBeg + $("#title").val().length;
+ }
+
+ var domObj = wpasTitle.get(0);
+ if ( domObj.setSelectionRange ) {
+ domObj.setSelectionRange( selBeg, selEnd );
+ } else if ( domObj.createTextRange ) {
+ var r = domObj.createTextRange();
+ r.moveStart( 'character', selBeg );
+ r.moveEnd( 'character', selEnd );
+ r.select();
+ }
+ }
+ wpasTitle.keyup();
+ } );
+ $('#publicize-defaults').hide();
+ $(this).hide();
+ return false;
+ } );
+
+ $('#publicize-form-hide').click( function() {
+ var newList = $.map( $('#publicize-form').slideUp( 'fast' ).find( ':checked' ), function( el ) {
+ return $.trim( $(el).parent( 'label' ).text() );
+ } );
+ $('#publicize-defaults').html( '<strong>' + newList.join( '</strong>, <strong>' ) + '</strong>' ).show();
+ $('#publicize-form-edit').show();
+ return false;
+ } );
+
+ $('.authorize-link').click( function() {
+ if ( authClick ) {
+ return false;
+ }
+ authClick = true;
+ $(this).after( '<img src="images/loading.gif" class="alignleft" style="margin: 0 .5em" />' );
+ $.ajaxSetup( { async: false } );
+ autosave();
+ return true;
+ } );
+
+ $( '.pub-service' ).click( function() {
+ var service = $(this).data( 'service' ),
+ fakebox = '<input id="wpas-submit-' + service + '" type="hidden" value="1" name="wpas[submit][' + service + ']" />';
+ $( '#add-publicize-check' ).append( fakebox );
+ } );
+} );
+</script>
+
+<style type="text/css">
+#publicize {
+ line-height: 1.5;
+}
+#publicize ul {
+ margin: 4px 0 4px 6px;
+}
+#publicize li {
+ margin: 0;
+}
+#publicize textarea {
+ margin: 4px 0 0;
+ width: 100%
+}
+#publicize ul.not-connected {
+ list-style: square;
+ padding-left: 1em;
+}
+.post-new-php .authorize-link, .post-php .authorize-link {
+ line-height: 1.5em;
+}
+.post-new-php .authorize-message, .post-php .authorize-message {
+ margin-bottom: 0;
+}
+#poststuff #publicize .updated p {
+ margin: .5em 0;
+}
+.wpas-twitter-length-limit {
+ color: red;
+}
+</style><?php
+ }
+
+ /**
+ * Controls the metabox that is displayed on the post page
+ * Allows the user to customize the message that will be sent out to the social network, as well as pick which
+ * networks to publish to. Also displays the character counter and some other information.
+ */
+ function post_page_metabox() {
+ global $post;
+
+ if ( 'post' != $post->post_type )
+ return;
+
+ $user_id = empty( $post->post_author ) ? $GLOBALS['user_ID'] : $post->post_author;
+ $services = $this->publicize->get_services( 'connected' );
+ $available_services = $this->publicize->get_services( 'all' );
+
+ if ( ! is_array( $available_services ) )
+ $available_services = array();
+
+ if ( ! is_array( $services ) )
+ $services = array();
+
+ $active = array(); ?>
+
+ <div id="publicize" class="misc-pub-section misc-pub-section-last">
+ <?php
+ _e( 'Publicize:', 'jetpack' );
+
+ if ( 0 < count( $services ) ) :
+ ob_start();
+ ?>
+
+ <div id="publicize-form" class="hide-if-js">
+ <ul>
+
+ <?php
+ // We can set an _all flag to indicate that this post is completely done as
+ // far as Publicize is concerned. Jetpack uses this approach. All published posts in Jetpack
+ // have Publicize disabled.
+ $all_done = get_post_meta( $post->ID, $this->publicize->POST_DONE . 'all', true ) || ( $this->in_jetpack && 'publish' == $post->post_status );
+
+ // We don't allow Publicizing to the same external id twice, to prevent spam
+ $service_id_done = (array) get_post_meta( $post->ID, $this->publicize->POST_SERVICE_DONE, true );
+
+ foreach ( $services as $name => $connections ) {
+ foreach ( $connections as $connection ) {
+ if ( !$continue = apply_filters( 'wpas_submit_post?', true, $post->ID, $name ) )
+ continue;
+
+ if ( !empty( $connection->unique_id ) )
+ $unique_id = $connection->unique_id;
+ else if ( !empty( $connection['connection_data']['token_id'] ) )
+ $unique_id = $connection['connection_data']['token_id'];
+
+ // Should we be skipping this one?
+ $skip = (
+ get_post_meta( $post->ID, $this->publicize->POST_SKIP . $unique_id, true )
+ ||
+ (
+ is_array( $connection )
+ &&
+ (
+ ( isset( $connection['meta']['external_id'] ) && ! empty( $service_id_done[ $name ][ $connection['meta']['external_id'] ] ) )
+ ||
+ // Jetpack's connection data looks a little different.
+ ( isset( $connection['external_id'] ) && ! empty( $service_id_done[ $name ][ $connection['external_id'] ] ) )
+ )
+ )
+ );
+
+ // Was this connections (OR, old-format service) already Publicized to?
+ $done = ( 1 == get_post_meta( $post->ID, $this->publicize->POST_DONE . $unique_id, true ) || 1 == get_post_meta( $post->ID, $this->publicize->POST_DONE . $name, true ) ); // New and old style flags
+
+ // If this one has already been publicized to, don't let it happen again
+ $disabled = '';
+ if ( $done )
+ $disabled = ' disabled="disabled"';
+
+ // If this is a global connection and this user doesn't have enough permissions to modify
+ // those connections, don't let them change it
+ $cmeta = $this->publicize->get_connection_meta( $connection );
+ $hidden_checkbox = false;
+ if ( !$done && ( 0 == $cmeta['connection_data']['user_id'] && !current_user_can( Publicize::GLOBAL_CAP ) ) ) {
+ $disabled = ' disabled="disabled"';
+ $hidden_checkbox = true;
+ }
+
+ // Determine the state of the checkbox (on/off) and allow filtering
+ $checked = $skip != 1 || $done;
+ $checked = apply_filters( 'publicize_checkbox_default', $checked, $post->ID, $name, $connection );
+
+ // This post has been handled, so disable everything
+ if ( $all_done )
+ $disabled = ' disabled="disabled"';
+
+ $label = sprintf(
+ _x( '%1$s: %2$s', 'Service: Account connected as', 'jetpack' ),
+ esc_html( $this->publicize->get_service_label( $name ) ),
+ esc_html( $this->publicize->get_display_name( $name, $connection ) )
+ );
+ if ( !$skip || $done ) {
+ $active[] = $label;
+ }
+ ?>
+ <li>
+ <label for="wpas-submit-<?php echo esc_attr( $unique_id ); ?>">
+ <input type="checkbox" name="wpas[submit][<?php echo $unique_id; ?>]" id="wpas-submit-<?php echo $unique_id; ?>" class="wpas-submit-<?php echo $name; ?>" value="1" <?php
+ checked( true, $checked );
+ echo $disabled;
+ ?> />
+ <?php
+ if ( $hidden_checkbox ) {
+ // Need to submit a value to force a global connection to post
+ echo '<input type="hidden" name="wpas[submit][' . $unique_id . ']" value="1" />';
+ }
+ echo esc_html( $label );
+ ?>
+ </label>
+ </li>
+ <?php
+ }
+ }
+
+ if ( $title = get_post_meta( $post->ID, $this->publicize->POST_MESS, true ) )
+ $title = esc_html( $title );
+ else
+ $title = '';
+ ?>
+
+ </ul>
+
+ <label for="wpas-title"><?php _e( 'Custom Message:', 'jetpack' ); ?></label>
+ <span id="wpas-title-counter" class="alignright hide-if-no-js">0</span>
+
+ <textarea name="wpas_title" id="wpas-title"<?php disabled( $all_done ); ?>><?php echo $title; ?></textarea>
+
+ <a href="#" class="hide-if-no-js" id="publicize-form-hide"><?php _e( 'Hide', 'jetpack' ); ?></a>
+ <input type="hidden" name="wpas[0]" value="1" />
+
+ </div> <?php // #publicize-form
+
+ $this->publicize->refresh_tokens_message();
+
+ $publicize_form = ob_get_clean();
+ else :
+ echo "&nbsp;" . __( 'Not Connected', 'jetpack' );
+ ob_start();
+ ?>
+
+ <div id="publicize-form" class="hide-if-js">
+ <div id="add-publicize-check" style="display: none;"></div>
+
+ <strong><?php _e( 'Connect to', 'jetpack' ); ?>:</strong>
+
+ <ul class="not-connected">
+ <?php foreach ( $available_services as $service_name => $service ) : ?>
+ <li>
+ <a class="pub-service" data-service="<?php echo esc_attr( $service_name ); ?>" title="<?php echo esc_attr( sprintf( __( 'Connect and share your posts on %s', 'jetpack' ), $this->publicize->get_service_label( $service_name ) ) ); ?>" target="_blank" href="<?php echo $this->publicize->connect_url( $service_name ); ?>">
+ <?php echo esc_html( $this->publicize->get_service_label( $service_name ) ); ?>
+ </a>
+ </li>
+ <?php endforeach; ?>
+ </ul>
+
+ <?php if ( 0 < count( $services ) ) : ?>
+ <a href="#" class="hide-if-no-js" id="publicize-form-hide"><?php _e( 'Hide', 'jetpack' ); ?></a>
+ <?php else : ?>
+ <a href="#" class="hide-if-no-js" id="publicize-disconnected-form-hide"><?php _e( 'Hide', 'jetpack' ); ?></a>
+ <?php endif; ?>
+ </div> <?php // #publicize-form
+
+ $publicize_form = ob_get_clean();
+ endif;
+ ?>
+
+ <span id="publicize-defaults"><strong><?php echo join( '</strong>, <strong>', array_map( 'esc_html', $active ) ); ?></strong></span>
+
+ <?php if ( 0 < count( $services ) ) : ?>
+ <a href="#" id="publicize-form-edit"><?php _e( 'Edit', 'jetpack' ); ?></a>&nbsp;<a href="<?php echo admin_url( 'options-general.php?page=sharing' ); ?>" target="_blank"><?php _e( 'Settings', 'jetpack' ); ?></a><br />
+ <?php else : ?>
+ <a href="#" id="publicize-disconnected-form-show"><?php _e( 'Show', 'jetpack' ); ?></a><br />
+ <?php endif; ?>
+
+ <?php echo apply_filters( 'publicize_form', $publicize_form ); ?>
+
+ </div> <?php // #publicize
+ }
+
+}
diff --git a/plugins/jetpack/modules/sharedaddy.php b/plugins/jetpack/modules/sharedaddy.php
index fa7b36a1..f6f4ad6e 100644
--- a/plugins/jetpack/modules/sharedaddy.php
+++ b/plugins/jetpack/modules/sharedaddy.php
@@ -18,6 +18,6 @@ function sharedaddy_loaded() {
}
function sharedaddy_configuration_load() {
- wp_safe_redirect( menu_page_url( 'sharing', false ) );
+ wp_safe_redirect( menu_page_url( 'sharing', false ) . "#sharing-buttons" );
exit;
}
diff --git a/plugins/jetpack/modules/sharedaddy/admin-sharing.css b/plugins/jetpack/modules/sharedaddy/admin-sharing.css
index fd0e3d43..aea30792 100644
--- a/plugins/jetpack/modules/sharedaddy/admin-sharing.css
+++ b/plugins/jetpack/modules/sharedaddy/admin-sharing.css
@@ -95,54 +95,6 @@
-@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) {
-
- .services ul li#facebook, #available-services .preview-facebook div.option-smart-off{background: #FFF url(images/facebook@2x.png) no-repeat 4px 5px;}
- .services ul li#twitter, #available-services .preview-twitter div.option-smart-off{background: #FFF url(images/twitter@2x.png?1) no-repeat 4px 5px;}
- .services ul li#wordpress, #available-services .preview-wordpress{background: #FFF url(images/wordpress@2x.png?1) no-repeat 4px 5px;}
- .services ul li#digg, #available-services .preview-digg div.option-smart-off{background: #FFF url(images/digg@2x.png) no-repeat 4px 5px;}
- .services ul li#reddit, #available-services .preview-reddit div.option-smart-off{background: #FFF url(images/reddit@2x.png) no-repeat 4px 5px;}
- .services ul li#stumbleupon, #available-services .preview-stumbleupon div.option-smart-off{background: #FFF url(images/stumbleupon@2x.png) no-repeat 4px 5px;}
- .services ul li#email, #available-services .preview-email{background: #FFF url(images/email@2x.png) no-repeat 4px 5px; padding-right: 10px;}
- .services ul li#print, #available-services .preview-print{background: #FFF url(images/print@2x.png) no-repeat 4px 5px; padding-right: 10px;}
- .services ul li#press-this, #available-services .preview-press-this{background: #FFF url(images/wordpress@2x.png) no-repeat 4px 5px; padding-right: 10px;}
- .services ul li#linkedin, #available-services .preview-linkedin div.option-smart-off{background: #FFF url(images/linkedin@2x.png) no-repeat 4px 5px;}
- .services ul li#tumblr,#available-services .preview-tumblr{background: #FFF url(images/tumblr@2x.png) no-repeat 4px 5px; padding-right: 10px;}
- .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;}
- .services ul li#pinterest,#available-services .preview-pinterest{background: #FFF url(images/pinterest@2x.png) no-repeat 4px 5px; padding-right: 10px;}
- .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;}
-
- .services ul li#facebook, #available-services .preview-facebook div.option-smart-off,
- .services ul li#twitter, #available-services .preview-twitter div.option-smart-off,
- .services ul li#wordpress, #available-services .preview-wordpress,
- .services ul li#digg, #available-services .preview-digg div.option-smart-off,
- .services ul li#reddit, #available-services .preview-reddit div.option-smart-off,
- .services ul li#stumbleupon, #available-services .preview-stumbleupon div.option-smart-off,
- .services ul li#email, #available-services .preview-email,
- .services ul li#print, #available-services .preview-print,
- .services ul li#press-this, #available-services .preview-press-this,
- .services ul li#linkedin, #available-services .preview-linkedin div.option-smart-off,
- .services ul li#tumblr,#available-services .preview-tumblr,
- .services ul li#google-plus-1,#available-services .preview-google-plus-1,
- .services ul li#pinterest,#available-services .preview-pinterest,
- .services ul li.share-custom, #available-services .preview-custom{
- background-size: 16px 16px;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-}
-
-
/****************************************************************************/
.preview li.preview-item {
@@ -165,6 +117,7 @@
.preview-digg .option-smart-on {
background: #FFF url(images/smart-digg.png) no-repeat top left;
+ background-size: 76px 17px;
width:76px;
height:17px;
margin-top: 2px;
@@ -172,12 +125,14 @@
.preview-reddit .option-smart-on {
background: #FFF url(images/smart-reddit.png) no-repeat top left;
+ background-size: 104px 21px;
width:104px;
height:21px;
}
.preview-stumbleupon .option-smart-on {
background: #FFF url(images/smart-stumbleupon.png) no-repeat top left;
+ background-size: 74px 18px;
width: 74px;
height: 18px;
margin-top: 1px;
@@ -185,44 +140,47 @@
.preview-facebook .option-smart-on {
background: #FFF url(images/smart-like.png) no-repeat top left;
+ background-size: 50px 20px;
width:50px;
height:20px;
}
.preview-twitter .option-smart-on {
background: #FFF url(images/smart-twitter.png?1) no-repeat top left;
+ background-size: 92px 20px;
width:92px;
height:20px;
}
.preview-linkedin .option-smart-on {
background: #FFF url(images/linkedin-smart.png) no-repeat top center;
+ background-size: 99px 18px;
width:99px;
- height:22px;
+ height:18px;
margin-top: 1px;
}
.preview-google-plus-1 .option-smart-on {
background: #FFF url(images/smart-googleplus1.png) no-repeat top left;
- max-width: 70px;
+ background-size: 60px 20px;
width: 60px;
height: 20px;
}
.preview-tumblr .option-smart-on {
background: #FFF url(images/smart-tumblr.png) no-repeat top left;
+ background-size: 62px 20px;
width: 62px;
height: 20px;
}
.preview-pinterest .option-smart-on {
background: #FFF url(images/smart-pinterest.png) no-repeat top left;
+ background-size: 58px 20px;
width: 58px;
height: 20px;
}
-div.sharedaddy .preview-google-plus-1 .no-text { width: 60px; }
-
.services .preview li.share-custom {
border-radius: 6px;
-moz-border-radius: 6px;
@@ -390,3 +348,81 @@ div.sharedaddy .preview-google-plus-1 .no-text { width: 60px; }
#services-config a.remove:hover {
background: #f00;
}
+
+
+
+
+@media print,
+ (-o-min-device-pixel-ratio: 5/4),
+ (-webkit-min-device-pixel-ratio: 1.25),
+ (min-resolution: 120dpi) {
+
+ .services ul li#facebook, #available-services .preview-facebook div.option-smart-off{background: #FFF url(images/facebook@2x.png) no-repeat 4px 5px;}
+ .services ul li#twitter, #available-services .preview-twitter div.option-smart-off{background: #FFF url(images/twitter@2x.png?1) no-repeat 4px 5px;}
+ .services ul li#wordpress, #available-services .preview-wordpress{background: #FFF url(images/wordpress@2x.png?1) no-repeat 4px 5px;}
+ .services ul li#digg, #available-services .preview-digg div.option-smart-off{background: #FFF url(images/digg@2x.png) no-repeat 4px 5px;}
+ .services ul li#reddit, #available-services .preview-reddit div.option-smart-off{background: #FFF url(images/reddit@2x.png) no-repeat 4px 5px;}
+ .services ul li#stumbleupon, #available-services .preview-stumbleupon div.option-smart-off{background: #FFF url(images/stumbleupon@2x.png) no-repeat 4px 5px;}
+ .services ul li#email, #available-services .preview-email{background: #FFF url(images/email@2x.png) no-repeat 4px 5px; padding-right: 10px;}
+ .services ul li#print, #available-services .preview-print{background: #FFF url(images/print@2x.png) no-repeat 4px 5px; padding-right: 10px;}
+ .services ul li#press-this, #available-services .preview-press-this{background: #FFF url(images/wordpress@2x.png) no-repeat 4px 5px; padding-right: 10px;}
+ .services ul li#linkedin, #available-services .preview-linkedin div.option-smart-off{background: #FFF url(images/linkedin@2x.png) no-repeat 4px 5px;}
+ .services ul li#tumblr,#available-services .preview-tumblr{background: #FFF url(images/tumblr@2x.png) no-repeat 4px 5px; padding-right: 10px;}
+ .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;}
+ .services ul li#pinterest,#available-services .preview-pinterest{background: #FFF url(images/pinterest@2x.png) no-repeat 4px 5px; padding-right: 10px;}
+ .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;}
+
+ .services ul li#facebook, #available-services .preview-facebook div.option-smart-off,
+ .services ul li#twitter, #available-services .preview-twitter div.option-smart-off,
+ .services ul li#wordpress, #available-services .preview-wordpress,
+ .services ul li#digg, #available-services .preview-digg div.option-smart-off,
+ .services ul li#reddit, #available-services .preview-reddit div.option-smart-off,
+ .services ul li#stumbleupon, #available-services .preview-stumbleupon div.option-smart-off,
+ .services ul li#email, #available-services .preview-email,
+ .services ul li#print, #available-services .preview-print,
+ .services ul li#press-this, #available-services .preview-press-this,
+ .services ul li#linkedin, #available-services .preview-linkedin div.option-smart-off,
+ .services ul li#tumblr,#available-services .preview-tumblr,
+ .services ul li#google-plus-1,#available-services .preview-google-plus-1,
+ .services ul li#pinterest,#available-services .preview-pinterest,
+ .services ul li.share-custom, #available-services .preview-custom{
+ background-size: 16px 16px;
+ }
+
+ .preview-digg .option-smart-on {
+ background-image: url(images/smart-digg@2x.png);
+ }
+
+ .preview-reddit .option-smart-on {
+ background-image: url(images/smart-reddit@2x.png);
+ }
+
+ .preview-stumbleupon .option-smart-on {
+ background-image: url(images/smart-stumbleupon@2x.png);
+ }
+
+ .preview-facebook .option-smart-on {
+ background-image: url(images/smart-like@2x.png);
+ }
+
+ .preview-twitter .option-smart-on {
+ background-image: url(images/smart-twitter@2x.png);
+ }
+
+ .preview-linkedin .option-smart-on {
+ background-image: url(images/linkedin-smart@2x.png);
+ }
+
+ .preview-google-plus-1 .option-smart-on {
+ background-image: url(images/smart-googleplus1@2x.png);
+ }
+
+ .preview-tumblr .option-smart-on {
+ background-image: url(images/smart-tumblr@2x.png);
+ }
+
+ .preview-pinterest .option-smart-on {
+ background-image: url(images/smart-pinterest@2x.png);
+ }
+
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.png b/plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.png
new file mode 100644
index 00000000..a5c71943
--- /dev/null
+++ b/plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.png
Binary files differ
diff --git a/plugins/jetpack/modules/sharedaddy/images/icon-facebook.png b/plugins/jetpack/modules/sharedaddy/images/icon-facebook.png
new file mode 100644
index 00000000..de6a8a14
--- /dev/null
+++ b/plugins/jetpack/modules/sharedaddy/images/icon-facebook.png
Binary files differ
diff --git a/plugins/jetpack/modules/sharedaddy/images/icon-twitter-2x.png b/plugins/jetpack/modules/sharedaddy/images/icon-twitter-2x.png
new file mode 100644
index 00000000..85f2f34c
--- /dev/null
+++ b/plugins/jetpack/modules/sharedaddy/images/icon-twitter-2x.png
Binary files differ
diff --git a/plugins/jetpack/modules/sharedaddy/images/icon-twitter.png b/plugins/jetpack/modules/sharedaddy/images/icon-twitter.png
new file mode 100644
index 00000000..ec41046e
--- /dev/null
+++ b/plugins/jetpack/modules/sharedaddy/images/icon-twitter.png
Binary files differ
diff --git a/plugins/jetpack/modules/sharedaddy/images/icon-wordpress-2x.png b/plugins/jetpack/modules/sharedaddy/images/icon-wordpress-2x.png
new file mode 100644
index 00000000..4d81cabc
--- /dev/null
+++ b/plugins/jetpack/modules/sharedaddy/images/icon-wordpress-2x.png
Binary files differ
diff --git a/plugins/jetpack/modules/sharedaddy/images/icon-wordpress.png b/plugins/jetpack/modules/sharedaddy/images/icon-wordpress.png
new file mode 100644
index 00000000..86f1bd35
--- /dev/null
+++ b/plugins/jetpack/modules/sharedaddy/images/icon-wordpress.png
Binary files differ
diff --git a/plugins/jetpack/modules/sharedaddy/sharedaddy.php b/plugins/jetpack/modules/sharedaddy/sharedaddy.php
index 727005e7..ab8085ca 100644
--- a/plugins/jetpack/modules/sharedaddy/sharedaddy.php
+++ b/plugins/jetpack/modules/sharedaddy/sharedaddy.php
@@ -20,21 +20,27 @@ function sharing_email_send_post( $data ) {
function sharing_add_meta_box() {
$post_types = get_post_types( array( 'public' => true ) );
-
+ $title = apply_filters( 'sharing_meta_box_title', __( 'Sharing', 'jetpack' ) );
foreach( $post_types as $post_type ) {
- add_meta_box( 'sharing_meta', __( 'Sharing', 'jetpack' ), 'sharing_meta_box_content', $post_type, 'advanced', 'high' );
+ add_meta_box( 'sharing_meta', $title, 'sharing_meta_box_content', $post_type, 'advanced', 'high' );
}
}
function sharing_meta_box_content( $post ) {
- $sharing_checked = get_post_meta( $post->ID, 'sharing_disabled', false );
+ do_action( 'start_sharing_meta_box_content', $post );
+
+ $disabled = get_post_meta( $post->ID, 'sharing_disabled', true ); ?>
- if ( empty( $sharing_checked ) || $sharing_checked === false )
- $sharing_checked = ' checked="checked"';
- else
- $sharing_checked = '';
+ <p>
+ <label for="enable_post_sharing">
+ <input type="checkbox" name="enable_post_sharing" id="enable_post_sharing" value="1" <?php checked( !$disabled ); ?>>
+ <?php _e( 'Show sharing buttons.' , 'jetpack'); ?>
+ </label>
+ <input type="hidden" name="sharing_status_hidden" value="1" />
+ </p>
- echo '<p><label for="enable_post_sharing"><input name="enable_post_sharing" id="enable_post_sharing" value="1"' . $sharing_checked . ' type="checkbox"> ' . __( 'Show sharing buttons on this post.', 'jetpack' ) . '</label><input type="hidden" name="sharing_status_hidden" value="1" /></p>';
+ <?php
+ do_action( 'end_sharing_meta_box_content', $post );
}
function sharing_meta_box_save( $post_id ) {
@@ -101,10 +107,6 @@ function sharing_disable_js() {
return false;
}
-if ( !function_exists( 'sharing_register_post_for_share_counts' ) ) {
- function sharing_register_post_for_share_counts() {}
-}
-
function sharing_global_resources() {
$disable = get_option( 'sharedaddy_disable_resources' );
?>
@@ -133,20 +135,17 @@ function sharing_email_check( $true, $post, $data ) {
return $recaptcha_result->is_valid;
}
-// Only run if PHP5
-if ( version_compare( phpversion(), '5.0', '>=' ) ) {
- add_action( 'init', 'sharing_init' );
- add_action( 'admin_init', 'sharing_add_meta_box' );
- add_action( 'save_post', 'sharing_meta_box_save' );
- add_action( 'sharing_email_send_post', 'sharing_email_send_post' );
- add_action( 'sharing_global_options', 'sharing_global_resources' );
- add_action( 'sharing_admin_update', 'sharing_global_resources_save' );
- add_filter( 'sharing_services', 'sharing_restrict_to_single' );
- add_action( 'plugin_action_links_'.basename( dirname( __FILE__ ) ).'/'.basename( __FILE__ ), 'sharing_plugin_settings', 10, 4 );
- add_filter( 'plugin_row_meta', 'sharing_add_plugin_settings', 10, 2 );
-
- if ( defined( 'RECAPTCHA_PRIVATE_KEY' ) ) {
- add_action( 'sharing_email_dialog', 'sharing_email_dialog' );
- add_filter( 'sharing_email_check', 'sharing_email_check', 10, 3 );
- }
-}
+add_action( 'init', 'sharing_init' );
+add_action( 'admin_init', 'sharing_add_meta_box' );
+add_action( 'save_post', 'sharing_meta_box_save' );
+add_action( 'sharing_email_send_post', 'sharing_email_send_post' );
+add_action( 'sharing_global_options', 'sharing_global_resources', 30 );
+add_action( 'sharing_admin_update', 'sharing_global_resources_save' );
+add_filter( 'sharing_services', 'sharing_restrict_to_single' );
+add_action( 'plugin_action_links_'.basename( dirname( __FILE__ ) ).'/'.basename( __FILE__ ), 'sharing_plugin_settings', 10, 4 );
+add_filter( 'plugin_row_meta', 'sharing_add_plugin_settings', 10, 2 );
+
+if ( defined( 'RECAPTCHA_PRIVATE_KEY' ) ) {
+ add_action( 'sharing_email_dialog', 'sharing_email_dialog' );
+ add_filter( 'sharing_email_check', 'sharing_email_check', 10, 3 );
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/sharedaddy/sharing-service.php b/plugins/jetpack/modules/sharedaddy/sharing-service.php
index 82d7293d..c8efee33 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing-service.php
+++ b/plugins/jetpack/modules/sharedaddy/sharing-service.php
@@ -2,10 +2,15 @@
include_once dirname( __FILE__ ).'/sharing-sources.php';
-define( 'WP_SHARING_PLUGIN_VERSION', '0.3.1' );
+define( 'WP_SHARING_PLUGIN_VERSION', JETPACK__VERSION );
class Sharing_Service {
private $global = false;
+ var $default_sharing_label = '';
+
+ public function __construct() {
+ $this->default_sharing_label = __( 'Share this:', 'jetpack' );
+ }
/**
* Gets a generic list of all services, without any config
@@ -15,11 +20,11 @@ class Sharing_Service {
$all = $this->get_all_services();
$services = array();
-
+
foreach ( $all AS $id => $name ) {
if ( isset( $all[$id] ) ) {
$config = array();
-
+
// Pre-load custom modules otherwise they won't know who they are
if ( substr( $id, 0, 7 ) == 'custom-' && is_array( $options[$id] ) )
$config = $options[$id];
@@ -30,7 +35,7 @@ class Sharing_Service {
return $services;
}
-
+
/**
* Gets a list of all available service names and classes
*/
@@ -50,29 +55,29 @@ class Sharing_Service {
'tumblr' => 'Share_Tumblr',
'pinterest' => 'Share_Pinterest',
);
-
+
// Add any custom services in
$options = $this->get_global_options();
foreach ( (array)$options['custom'] AS $custom_id ) {
$services[$custom_id] = 'Share_Custom';
}
-
+
return apply_filters( 'sharing_services', $services );
}
-
+
public function new_service( $label, $url, $icon ) {
// Validate
$label = trim( wp_html_excerpt( wp_kses( $label, array() ), 30 ) );
$url = trim( esc_url_raw( $url ) );
$icon = trim( esc_url_raw( $icon ) );
-
+
if ( $label && $url && $icon ) {
$options = get_option( 'sharing-options' );
if ( !is_array( $options ) )
$options = array();
-
+
$service_id = 'custom-'.time();
-
+
// Add a new custom service
$options['global']['custom'][] = $service_id;
@@ -85,23 +90,23 @@ class Sharing_Service {
// Return the service
return $service;
}
-
+
return false;
}
-
+
public function delete_service( $service_id ) {
$options = get_option( 'sharing-options' );
if ( isset( $options[$service_id] ) )
unset( $options[$service_id] );
-
+
$key = array_search( $service_id, $options['global']['custom'] );
if ( $key !== false )
unset( $options['global']['custom'][$key] );
-
+
update_option( 'sharing-options', $options );
return true;
}
-
+
public function set_blog_services( array $visible, array $hidden ) {
$services = $this->get_all_services();
// Validate the services
@@ -113,12 +118,12 @@ class Sharing_Service {
// Ensure we don't have the same ones in hidden and visible
$hidden = array_diff( $hidden, $visible );
-
- do_action( 'sharing_get_services_state', array(
+
+ do_action( 'sharing_get_services_state', array(
'services' => $services,
- 'available' => $available,
- 'hidden' => $hidden,
- 'visible' => $visible,
+ 'available' => $available,
+ 'hidden' => $hidden,
+ 'visible' => $visible,
'currently_enabled' => $this->get_blog_services()
) );
@@ -148,10 +153,10 @@ class Sharing_Service {
// Cleanup after any filters that may have produced duplicate services
$enabled['visible'] = array_unique( $enabled['visible'] );
$enabled['hidden'] = array_unique( $enabled['hidden'] );
-
+
// Form the enabled services
$blog = array( 'visible' => array(), 'hidden' => array() );
-
+
foreach ( $blog AS $area => $stuff ) {
foreach ( (array)$enabled[$area] AS $service ) {
if ( isset( $services[$service] ) ) {
@@ -170,7 +175,7 @@ class Sharing_Service {
$blog['all'] = array_flip( array_merge( array_keys( $blog['visible'] ), array_keys( $blog['hidden'] ) ) );
return $blog;
}
-
+
public function get_service( $service_name ) {
$services = $this->get_blog_services();
@@ -179,10 +184,10 @@ class Sharing_Service {
if ( isset( $services['hidden'][$service_name] ) )
return $services['hidden'][$service_name];
-
+
return false;
}
-
+
public function set_global_options( $data ) {
$options = get_option( 'sharing-options' );
@@ -193,20 +198,25 @@ class Sharing_Service {
// Defaults
$options['global'] = array(
'button_style' => 'icon-text',
- 'sharing_label' => __( 'Share this:', 'jetpack' ),
+ 'sharing_label' => $this->default_sharing_label,
'open_links' => 'same',
'show' => array( 'post', 'page' ),
'custom' => isset( $options['global']['custom'] ) ? $options['global']['custom'] : array()
);
-
+
$options['global'] = apply_filters( 'sharing_default_global', $options['global'] );
// Validate options and set from our data
if ( isset( $data['button_style'] ) && in_array( $data['button_style'], array( 'icon-text', 'icon', 'text', 'official' ) ) )
$options['global']['button_style'] = $data['button_style'];
- if ( isset( $data['sharing_label'] ) )
- $options['global']['sharing_label'] = trim( wp_kses( stripslashes( $data['sharing_label'] ), array() ) );
+ if ( isset( $data['sharing_label'] ) ) {
+ if ( $this->default_sharing_label === $data['sharing_label'] ) {
+ $options['global']['sharing_label'] = false;
+ } else {
+ $options['global']['sharing_label'] = trim( wp_kses( stripslashes( $data['sharing_label'] ), array() ) );
+ }
+ }
if ( isset( $data['open_links'] ) && in_array( $data['open_links'], array( 'new', 'same' ) ) )
$options['global']['open_links'] = $data['open_links'];
@@ -238,7 +248,7 @@ class Sharing_Service {
update_option( 'sharing-options', $options );
return $options['global'];
}
-
+
public function get_global_options() {
if ( $this->global === false ) {
$options = get_option( 'sharing-options' );
@@ -247,7 +257,7 @@ class Sharing_Service {
$this->global = $options['global'];
else
$this->global = $this->set_global_options( $options['global'] );
- }
+ }
if ( ! isset( $this->global['show'] ) ) {
$this->global['show'] = array( 'post', 'page' );
@@ -264,24 +274,29 @@ class Sharing_Service {
break;
}
}
+
+ if ( false === $this->global['sharing_label'] ) {
+ $this->global['sharing_label'] = $this->default_sharing_label;
+ }
+
return $this->global;
}
-
+
public function set_service( $id, Sharing_Source $service ) {
// Update the options for this service
$options = get_option( 'sharing-options' );
-
+
// No options yet
if ( !is_array( $options ) )
$options = array();
-
+
do_action( 'sharing_get_button_state', array( 'id' => $id, 'options' => $options, 'service' => $service ) );
-
+
$options[$id] = $service->get_options();
update_option( 'sharing-options', array_filter( $options ) );
}
-
+
// Soon to come to a .org plugin near you!
public function get_total( $service_name = false, $post_id = false, $_blog_id = false ) {
global $wpdb, $blog_id;
@@ -297,40 +312,40 @@ class Sharing_Service {
return (int) $wpdb->get_var( $wpdb->prepare( "SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d", $_blog_id ) );
}
}
-
+
if ( $post_id > 0 )
return (int) $wpdb->get_var( $wpdb->prepare( "SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s", $_blog_id, $post_id, $service_name ) );
else
return (int) $wpdb->get_var( $wpdb->prepare( "SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s", $_blog_id, $service_name ) );
}
-
+
public function get_services_total( $post_id = false ) {
$totals = array();
$services = $this->get_blog_services();
-
+
if ( !empty( $services ) && isset( $services[ 'all' ] ) )
foreach( $services[ 'all' ] as $key => $value ) {
$totals[$key] = new Sharing_Service_Total( $key, $this->get_total( $key, $post_id ) );
}
usort( $totals, array( 'Sharing_Service_Total', 'cmp' ) );
-
+
return $totals;
- }
-
+ }
+
public function get_posts_total() {
$totals = array();
global $wpdb, $blog_id;
-
+
$my_data = $wpdb->get_results( $wpdb->prepare( "SELECT post_id as id, SUM( count ) as total FROM sharing_stats WHERE blog_id = %d GROUP BY post_id ORDER BY count DESC ", $blog_id ) );
-
+
if ( !empty( $my_data ) )
foreach( $my_data as $row )
$totals[] = new Sharing_Post_Total( $row->id, $row->total );
-
+
usort( $totals, array( 'Sharing_Post_Total', 'cmp' ) );
-
+
return $totals;
- }
+ }
}
class Sharing_Service_Total {
@@ -338,16 +353,16 @@ class Sharing_Service_Total {
var $name = '';
var $service = '';
var $total = 0;
-
+
public function Sharing_Service_Total( $id, $total ) {
$services = new Sharing_Service();
$this->id = esc_html( $id );
$this->service = $services->get_service( $id );
$this->total = (int) $total;
-
+
$this->name = $this->service->get_name();
}
-
+
static function cmp( $a, $b ) {
if ( $a->total == $b->total )
return $a->name < $b->name;
@@ -360,14 +375,14 @@ class Sharing_Post_Total {
var $total = 0;
var $title = '';
var $url = '';
-
+
public function Sharing_Post_Total( $id, $total ) {
$this->id = (int) $id;
$this->total = (int) $total;
- $this->title = get_the_title( $this->id );
- $this->url = get_permalink( $this->id );
+ $this->title = get_the_title( $this->id );
+ $this->url = get_permalink( $this->id );
}
-
+
static function cmp( $a, $b ) {
if ( $a->total == $b->total )
return $a->id < $b->id;
@@ -375,16 +390,41 @@ class Sharing_Post_Total {
}
}
+function sharing_register_post_for_share_counts( $post_id ) {
+ global $jetpack_sharing_counts;
+
+ if ( ! isset( $jetpack_sharing_counts ) || ! is_array( $jetpack_sharing_counts ) )
+ $jetpack_sharing_counts = array();
+
+ $jetpack_sharing_counts[ (int) $post_id ] = get_permalink( $post_id );
+}
+
function sharing_add_footer() {
- if ( apply_filters( 'sharing_js', true ) )
+ global $jetpack_sharing_counts;
+
+ if ( apply_filters( 'sharing_js', true ) ) {
+
+ if ( is_array( $jetpack_sharing_counts ) && count( $jetpack_sharing_counts ) ) :
+ $sharing_post_urls = array_filter( $jetpack_sharing_counts );
+ if ( $sharing_post_urls ) :
+?>
+
+ <script type="text/javascript">
+ WPCOM_sharing_counts = <?php echo json_encode( array_flip( $sharing_post_urls ) ); ?>
+ </script>
+<?php
+ endif;
+ endif;
+
wp_print_scripts( 'sharing-js' );
-
+ }
+
$sharer = new Sharing_Service();
$enabled = $sharer->get_blog_services();
foreach ( array_merge( $enabled['visible'], $enabled['hidden'] ) AS $service ) {
$service->display_footer();
}
-}
+}
function sharing_add_header() {
$sharer = new Sharing_Service();
@@ -393,9 +433,9 @@ function sharing_add_header() {
foreach ( array_merge( $enabled['visible'], $enabled['hidden'] ) AS $service ) {
$service->display_header();
}
-
+
if ( count( $enabled['all'] ) > 0 )
- wp_enqueue_style( 'sharedaddy', plugin_dir_url( __FILE__ ) .'sharing.css', array(), WP_SHARING_PLUGIN_VERSION );
+ wp_enqueue_style( 'sharedaddy', plugin_dir_url( __FILE__ ) .'sharing.css', array(), JETPACK__VERSION );
}
add_action( 'wp_head', 'sharing_add_header', 1 );
@@ -409,7 +449,7 @@ function sharing_process_requests() {
$service = $sharer->get_service( $_GET['share'] );
if ( $service ) {
$service->process_request( $post, $_POST );
- }
+ }
}
}
add_action( 'template_redirect', 'sharing_process_requests' );
@@ -421,10 +461,35 @@ function sharing_display( $text = '' ) {
return $text;
}
+ // Don't output flair on excerpts
if ( in_array( 'get_the_excerpt', (array) $wp_current_filter ) ) {
return $text;
}
+ // Don't allow flair to be added to the_content more than once (prevent infinite loops)
+ $done = false;
+ foreach ( $wp_current_filter as $filter ) {
+ if ( 'the_content' == $filter ) {
+ if ( $done )
+ return $text;
+ else
+ $done = true;
+ }
+ }
+
+ // check whether we are viewing the front page and whether the front page option is checked
+ $options = get_option( 'sharing-options' );
+ $display_options = $options['global']['show'];
+
+ if ( is_front_page() && ( is_array( $display_options ) && ! in_array( 'index', $display_options ) ) )
+ return $text;
+
+ if ( is_attachment() && in_array( 'the_excerpt', (array) $wp_current_filter ) ) {
+ // Many themes run the_excerpt() conditionally on an attachment page, then run the_content().
+ // We only want to output the sharing buttons once. Let's stick with the_content().
+ return $text;
+ }
+
$sharer = new Sharing_Service();
$global = $sharer->get_global_options();
@@ -439,25 +504,25 @@ function sharing_display( $text = '' ) {
// Pass through a filter for final say so
$show = apply_filters( 'sharing_show', $show, $post );
-
+
// Disabled for this post?
$switched_status = get_post_meta( $post->ID, 'sharing_disabled', false );
if ( !empty( $switched_status ) )
$show = false;
-
+
// Allow to be used on P2 ajax requests for latest posts.
if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && 'get_latest_posts' == $_REQUEST['action'] )
$show = true;
-
+
$sharing_content = '';
-
+
if ( $show ) {
$enabled = $sharer->get_blog_services();
if ( count( $enabled['all'] ) > 0 ) {
global $post;
-
+
$dir = get_option( 'text_direction' );
// Wrapper
@@ -465,7 +530,7 @@ function sharing_display( $text = '' ) {
if ( $global['sharing_label'] != '' )
$sharing_content .= '<h3 class="sd-title">' . $global['sharing_label'] . '</h3>';
$sharing_content .= '<div class="sd-content"><ul>';
-
+
// Visible items
$visible = '';
foreach ( $enabled['visible'] as $id => $service ) {
@@ -486,47 +551,47 @@ function sharing_display( $text = '' ) {
if ( $dir == 'rtl' )
$parts = array_reverse( $parts );
- $sharing_content .= implode( '', $parts );
+ $sharing_content .= implode( '', $parts );
$sharing_content .= '<li class="share-end"></li></ul>';
-
+
if ( count( $enabled['hidden'] ) > 0 ) {
$sharing_content .= '<div class="sharing-hidden"><div class="inner" style="display: none;';
if ( count( $enabled['hidden'] ) == 1 )
$sharing_content .= 'width:150px;';
-
+
$sharing_content .= '">';
-
+
if ( count( $enabled['hidden'] ) == 1 )
$sharing_content .= '<ul style="background-image:none;">';
else
$sharing_content .= '<ul>';
-
+
$count = 1;
foreach ( $enabled['hidden'] as $id => $service ) {
// Individual HTML for sharing service
$sharing_content .= '<li class="share-'.$service->get_class().'">';
$sharing_content .= $service->get_display( $post );
$sharing_content .= '</li>';
-
+
if ( ( $count % 2 ) == 0 )
$sharing_content .= '<li class="share-end"></li>';
$count ++;
}
-
+
// End of wrapper
$sharing_content .= '<li class="share-end"></li></ul></div></div>';
}
$sharing_content .= '<div class="sharing-clear"></div></div></div></div>';
-
+
// Register our JS
- wp_register_script( 'sharing-js', plugin_dir_url( __FILE__ ).'sharing.js', array( 'jquery' ), '20120131' );
+ wp_register_script( 'sharing-js', plugin_dir_url( __FILE__ ).'sharing.js', array( 'jquery' ), '20121205' );
add_action( 'wp_footer', 'sharing_add_footer' );
}
}
-
+
return $text.$sharing_content;
}
diff --git a/plugins/jetpack/modules/sharedaddy/sharing-sources.php b/plugins/jetpack/modules/sharedaddy/sharing-sources.php
index bd8b2eb9..256513cb 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing-sources.php
+++ b/plugins/jetpack/modules/sharedaddy/sharing-sources.php
@@ -5,7 +5,7 @@ abstract class Sharing_Source {
public $smart;
protected $open_links;
protected $id;
-
+
public function __construct( $id, array $settings ) {
$this->id = $id;
@@ -14,41 +14,49 @@ abstract class Sharing_Source {
if ( isset( $settings['open_links'] ) )
$this->open_links = $settings['open_links'];
-
+
if ( isset( $settings['smart'] ) )
$this->smart = $settings['smart'];
}
-
+
+ public function http() {
+ return is_ssl() ? 'https' : 'http';
+ }
+
public function get_id() {
return $this->id;
}
-
+
public function get_class() {
return $this->id;
}
-
+
+ public function get_share_url( $post_id ) {
+ return apply_filters( 'sharing_permalink', get_permalink( $post_id ), $post_id, $this->id );
+ }
+
public function has_custom_button_style() {
return false;
}
-
+
public function get_link( $url, $text, $title, $query = '', $id = false ) {
$klasses = array( 'share-'.$this->get_class(), 'sd-button' );
-
+
if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' )
$klasses[] = 'share-icon';
-
+
if ( $this->button_style == 'icon' ) {
$text = '';
$klasses[] = 'no-text';
}
-
+
if ( !empty( $query ) ) {
if ( stripos( $url, '?' ) === false )
$url .= '?'.$query;
else
$url .= '&amp;'.$query;
}
-
+
if ( $this->button_style == 'text' )
$klasses[] = 'no-icon';
@@ -67,29 +75,29 @@ abstract class Sharing_Source {
abstract public function get_display( $post );
public function display_header() {
- }
-
+ }
+
public function display_footer() {
}
-
+
public function has_advanced_options() {
return false;
}
-
+
public function display_preview() {
$text = '&nbsp;';
if ( !$this->smart )
if ( $this->button_style != 'icon' )
$text = $this->get_name();
-
+
$klasses = array( 'share-'.$this->get_class(), 'sd-button' );
-
+
if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' )
$klasses[] = 'share-icon';
-
+
if ( $this->button_style == 'icon' )
$klasses[] = 'no-text';
-
+
if ( $this->button_style == 'text' )
$klasses[] = 'no-icon';
@@ -107,39 +115,39 @@ abstract class Sharing_Source {
public function get_total( $post = false ) {
global $wpdb, $blog_id;
-
- $name = strtolower( $this->get_id() );
-
+
+ $name = strtolower( $this->get_id() );
+
if ( $post == false ) {
// get total number of shares for service
return (int) $wpdb->get_var( $wpdb->prepare( "SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s", $blog_id, $name ) );
}
-
+
// get total shares for a post
return (int) $wpdb->get_var( $wpdb->prepare( "SELECT count FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s", $blog_id, $post->ID, $name ) );
- }
-
+ }
+
public function get_posts_total() {
global $wpdb, $blog_id;
-
+
$totals = array();
- $name = strtolower( $this->get_id() );
-
+ $name = strtolower( $this->get_id() );
+
$my_data = $wpdb->get_results( $wpdb->prepare( "SELECT post_id as id, SUM( count ) as total FROM sharing_stats WHERE blog_id = %d AND share_service = %s GROUP BY post_id ORDER BY count DESC ", $blog_id, $name ) );
-
+
if ( !empty( $my_data ) )
foreach( $my_data as $row )
$totals[] = new Sharing_Post_Total( $row->id, $row->total );
-
+
usort( $totals, array( 'Sharing_Post_Total', 'cmp' ) );
-
+
return $totals;
}
-
+
public function process_request( $post, array $post_data ) {
do_action( 'sharing_bump_stats', array( 'service' => $this, 'post' => $post ) );
}
-
+
public function js_dialog( $name, $params = array() ) {
$defaults = array(
'menubar' => 1,
@@ -154,9 +162,9 @@ abstract class Sharing_Source {
}
$opts = implode( ',', $opts );
?>
- <script type="text/javascript" charset="utf-8">
- jQuery(document).ready(function(){
- jQuery( '.share-<?php echo $name; ?>' ).click(function(){
+ <script type="text/javascript">
+ jQuery(document).on( 'ready post-load', function(){
+ jQuery( 'a.share-<?php echo $name; ?>' ).on( 'click', function() {
window.open( jQuery(this).attr( 'href' ), 'wpcom<?php echo $name; ?>', '<?php echo $opts; ?>' );
return false;
});
@@ -170,7 +178,7 @@ abstract class Sharing_Advanced_Source extends Sharing_Source {
public function has_advanced_options() {
return true;
}
-
+
abstract public function display_options();
abstract public function update_options( array $data );
abstract public function get_options();
@@ -187,12 +195,12 @@ class Share_Email extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'Email', 'jetpack' );
}
- // Default does nothing
+ // Default does nothing
public function process_request( $post, array $post_data ) {
$ajax = false;
if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' )
@@ -205,10 +213,10 @@ class Share_Email extends Sharing_Source {
if ( isset( $post_data['target_email'] ) && is_email( $post_data['target_email'] ) )
$target_email = $post_data['target_email'];
-
+
if ( isset( $post_data['source_name'] ) )
$source_name = $post_data['source_name'];
-
+
// Test email
$error = 1; // Failure in data
if ( $source_email && $target_email && $source_name ) {
@@ -219,21 +227,21 @@ class Share_Email extends Sharing_Source {
'target' => $target_email,
'name' => $source_name
);
-
+
if ( ( $data = apply_filters( 'sharing_email_can_send', $data ) ) !== false ) {
// Record stats
parent::process_request( $data['post'], $post_data );
do_action( 'sharing_email_send_post', $data );
}
-
+
// Return a positive regardless of whether the user is subscribed or not
if ( $ajax ) {
?>
<div class="response">
- <div class="response-title"><?php _e( 'This post has been shared!', 'jetpack' ); ?></div>
- <div class="response-sub"><?php printf( __( 'You have shared this post with %s', 'jetpack' ), esc_html( $target_email ) ); ?></div>
- <div class="response-close"><a href="#" class="sharing_cancel"><?php _e( 'Close', 'jetpack' ); ?></a></div>
+ <div class="response-title"><?php _e( 'This post has been shared!', 'jetpack' ); ?></div>
+ <div class="response-sub"><?php printf( __( 'You have shared this post with %s', 'jetpack' ), esc_html( $target_email ) ); ?></div>
+ <div class="response-close"><a href="#" class="sharing_cancel"><?php _e( 'Close', 'jetpack' ); ?></a></div>
</div>
<?php
}
@@ -245,7 +253,7 @@ class Share_Email extends Sharing_Source {
else
$error = 2; // Email check failed
}
-
+
if ( $ajax )
echo $error;
else
@@ -253,24 +261,24 @@ class Share_Email extends Sharing_Source {
die();
}
-
+
public function get_display( $post ) {
return $this->get_link( get_permalink( $post->ID ), _x( 'Email', 'share to', 'jetpack' ), __( 'Click to email this to a friend', 'jetpack' ), 'share=email' );
}
-
+
/**
* Outputs the hidden email dialog
*/
public function display_footer() {
global $current_user;
-
+
$visible = $status = false;
?>
<div id="sharing_email" style="display: none;">
- <form action="" method="post">
+ <form action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" method="post">
<label for="target_email"><?php _e( 'Send to Email Address', 'jetpack' ) ?></label>
<input type="text" name="target_email" id="target_email" value="" />
-
+
<?php if ( is_user_logged_in() ) : ?>
<input type="hidden" name="source_name" value="<?php echo esc_attr( $current_user->display_name ); ?>" />
<input type="hidden" name="source_email" value="<?php echo esc_attr( $current_user->user_email ); ?>" />
@@ -278,18 +286,18 @@ class Share_Email extends Sharing_Source {
<label for="source_name"><?php _e( 'Your Name', 'jetpack' ) ?></label>
<input type="text" name="source_name" id="source_name" value="" />
-
+
<label for="source_email"><?php _e( 'Your Email Address', 'jetpack' ) ?></label>
<input type="text" name="source_email" id="source_email" value="" />
<?php endif; ?>
-
+
<?php do_action( 'sharing_email_dialog', 'jetpack' ); ?>
- <img style="float: right; display: none" class="loading" src="<?php echo plugin_dir_url( __FILE__ ) . 'images/loading.gif'; ?>" alt="loading" width="16" height="16" />
+ <img style="float: right; display: none" class="loading" src="<?php echo apply_filters( 'jetpack_static_url', plugin_dir_url( __FILE__ ) . 'images/loading.gif' ); ?>" alt="loading" width="16" height="16" />
<input type="submit" value="<?php _e( 'Send Email', 'jetpack' ); ?>" class="sharing_send" />
<a href="#cancel" class="sharing_cancel"><?php _e( 'Cancel', 'jetpack' ); ?></a>
-
+
<div class="errors errors-1" style="display: none;">
<?php _e( 'Post was not sent - check your email addresses!', 'jetpack' ); ?>
</div>
@@ -297,7 +305,7 @@ class Share_Email extends Sharing_Source {
<div class="errors errors-2" style="display: none;">
<?php _e( 'Email check failed, please try again', 'jetpack' ); ?>
</div>
-
+
<div class="errors errors-3" style="display: none;">
<?php _e( 'Sorry, your blog cannot share posts by email.', 'jetpack' ); ?>
</div>
@@ -317,41 +325,61 @@ class Share_Twitter extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'Twitter', 'jetpack' );
}
function sharing_twitter_via( $post ) {
- return '';
+ // Allow themes to customize the via
+ return apply_filters( 'jetpack_sharing_twitter_via', '', $post->ID );
+ }
- // Default 'via' is always us.
- $via = preg_replace( '/(https?:\/\/)|(\.)|(\/)/i', '', home_url() );
+ public function get_related_accounts( $post ) {
+ // Format is 'username' => 'Optional description'
+ $related_accounts = apply_filters( 'jetpack_sharing_twitter_related', array(), $post->ID );
- // Allow themes to customize the via
- return apply_filters( 'sharing_twitter_via', $via, $post->ID );
+ // Example related string: account1,account2:Account 2 description,account3
+ $related = array();
+
+ foreach ( $related_accounts as $related_account_username => $related_account_description ) {
+ // Join the description onto the end of the username
+ if ( $related_account_description )
+ $related_account_username .= ':' . $related_account_description;
+
+ $related[] = $related_account_username;
+ }
+
+ return implode( ',', $related );
}
public function get_display( $post ) {
$via = $this->sharing_twitter_via( $post );
if ( $via ) {
- $via = sprintf( '&via=%1$s', rawurlencode( $via ) );
+ $via = '&via=' . rawurlencode( $via );
+
+ $related = $this->get_related_accounts( $post );
+ if ( ! empty( $related ) && $related !== $via )
+ $via .= '&related=' . rawurlencode( $related );
} else {
$via = '';
}
+
+ $share_url = $this->get_share_url( $post->ID );
+
if ( $this->smart ) {
- return '<div class="twitter_button"><iframe allowtransparency="true" frameborder="0" scrolling="no" src="' . esc_url( 'http://platform.twitter.com/widgets/tweet_button.html?url=' . rawurlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ) . '&counturl=' . rawurlencode( str_replace( 'https://', 'http://', get_permalink( $post->ID ) ) ) . '&count=horizontal&text=' . rawurlencode( $post->post_title . ':' ) . $via ) . '" style="width:101px; height:20px;"></iframe></div>';
+ return '<div class="twitter_button"><iframe allowtransparency="true" frameborder="0" scrolling="no" src="' . esc_url( $this->http() . '://platform.twitter.com/widgets/tweet_button.html?url=' . rawurlencode( $share_url ) . '&counturl=' . rawurlencode( str_replace( 'https://', 'http://', get_permalink( $post->ID ) ) ) . '&count=horizontal&text=' . rawurlencode( $post->post_title . ':' ) . $via ) . '" style="width:101px; height:20px;"></iframe></div>';
} else {
if ( 'icon-text' == $this->button_style || 'text' == $this->button_style )
sharing_register_post_for_share_counts( $post->ID );
return $this->get_link( get_permalink( $post->ID ), _x( 'Twitter', 'share to', 'jetpack' ), __( 'Click to share on Twitter', 'jetpack' ), 'share=twitter', 'sharing-twitter-' . $post->ID );
}
}
-
+
public function process_request( $post, array $post_data ) {
$post_title = $post->post_title;
- $post_link = apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id );
+ $post_link = $this->get_share_url( $post->ID );
if ( function_exists( 'mb_stripos' ) ) {
$strlen = 'mb_strlen';
@@ -360,10 +388,13 @@ class Share_Twitter extends Sharing_Source {
$strlen = 'strlen';
$substr = 'substr';
}
-
+
$via = $this->sharing_twitter_via( $post );
if ( $via ) {
- $related = false;
+ $related = $this->get_related_accounts( $post );
+ if ( $related === $via )
+ $related = false;
+
$sig = " via @$via";
} else {
$via = false;
@@ -384,22 +415,22 @@ class Share_Twitter extends Sharing_Source {
// Record stats
parent::process_request( $post, $post_data );
-
+
$url = $post_link;
$twitter_url = add_query_arg(
- urlencode_deep( compact( 'via', 'related', 'text', 'url' ) ),
- sprintf( '%s://twitter.com/intent/tweet', ( is_ssl() ? 'https' : 'http' ) )
+ urlencode_deep( array_filter( compact( 'via', 'related', 'text', 'url' ) ) ),
+ sprintf( '%s://twitter.com/intent/tweet', $this->http() )
);
// Redirect to Twitter
wp_redirect( $twitter_url );
die();
}
-
+
public function has_custom_button_style() {
return $this->smart;
}
-
+
public function display_footer() {
$this->js_dialog( $this->shortname, array( 'height' => 350 ) );
}
@@ -415,7 +446,7 @@ class Share_Stumbleupon extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'StumbleUpon', 'jetpack' );
}
@@ -426,17 +457,17 @@ class Share_Stumbleupon extends Sharing_Source {
public function get_display( $post ) {
if ( $this->smart )
- return '<div class="stumbleupon_button"><iframe src="http://www.stumbleupon.com/badge/embed/1/?url=' . urlencode( get_permalink( $post->ID ) ) . '&amp;title=' . urlencode( $post->post_title ) . '" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:74px; height: 18px;" allowTransparency="true"></iframe></div>';
+ return '<div class="stumbleupon_button"><iframe src="http://www.stumbleupon.com/badge/embed/1/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&amp;title=' . rawurlencode( $post->post_title ) . '" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:74px; height: 18px;" allowTransparency="true"></iframe></div>';
else
return $this->get_link( get_permalink( $post->ID ), _x( 'StumbleUpon', 'share to', 'jetpack' ), __( 'Click to share on StumbleUpon', 'jetpack' ), 'share=stumbleupon' );
}
-
+
public function process_request( $post, array $post_data ) {
- $stumbleupon_url = 'http://www.stumbleupon.com/submit?url=' . urlencode( get_permalink( $post->ID ) ) . '&title=' . urlencode( $post->post_title );
-
+ $stumbleupon_url = $this->http() . '://www.stumbleupon.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $post->post_title );
+
// Record stats
parent::process_request( $post, $post_data );
-
+
// Redirect to Stumbleupon
wp_redirect( $stumbleupon_url );
die();
@@ -460,17 +491,17 @@ class Share_Reddit extends Sharing_Source {
public function get_display( $post ) {
if ( $this->smart )
- return '<div class="reddit_button"><iframe src="http://www.reddit.com/static/button/button1.html?width=120&amp;url=' . urlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ) . '&amp;title=' . rawurlencode( $post->post_title ) . '" height="22" width="120" scrolling="no" frameborder="0"></iframe></div>';
+ return '<div class="reddit_button"><iframe src="http://www.reddit.com/static/button/button1.html?width=120&amp;url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&amp;title=' . rawurlencode( $post->post_title ) . '" height="22" width="120" scrolling="no" frameborder="0"></iframe></div>';
else
return $this->get_link( get_permalink( $post->ID ), __( 'Reddit', 'share to', 'jetpack' ), __( 'Click to share on Reddit', 'jetpack' ), 'share=reddit' );
- }
-
+ }
+
public function process_request( $post, array $post_data ) {
- $reddit_url = 'http://reddit.com/submit?url=' . urlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ) . '&title=' . urlencode( $post->post_title );
-
+ $reddit_url = 'http://reddit.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $post->post_title );
+
// Record stats
parent::process_request( $post, $post_data );
-
+
// Redirect to Reddit
wp_redirect( $reddit_url );
die();
@@ -487,7 +518,7 @@ class Share_Digg extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'Digg', 'jetpack' );
}
@@ -498,24 +529,24 @@ class Share_Digg extends Sharing_Source {
public function get_display( $post ) {
if ( $this->smart ) {
- $url = $this->get_link( 'http://digg.com/submit?url='. urlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ) . '&amp;title=' . urlencode( $post->post_title ), 'Digg', __( 'Click to Digg this post' ) );
+ $url = $this->get_link( 'http://digg.com/submit?url='. rawurlencode( $this->get_share_url( $post->ID ) ) . '&amp;title=' . rawurlencode( $post->post_title ), 'Digg', __( 'Click to Digg this post', 'jetpack' ) );
return '<div class="digg_button">' . str_replace( 'class="', 'class="DiggThisButton DiggCompact ', $url ) . '</div>';
} else {
- return $this->get_link( get_permalink( $post->ID ), _x( 'Digg', 'share to', 'jetpack' ), __( 'Click to Digg this post' ), 'share=digg' );
+ return $this->get_link( get_permalink( $post->ID ), _x( 'Digg', 'share to', 'jetpack' ), __( 'Click to Digg this post', 'jetpack' ), 'share=digg' );
}
- }
-
+ }
+
public function process_request( $post, array $post_data ) {
- $digg_url = 'http://digg.com/submit?url=' . urlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ) . '&title=' . urlencode( $post->post_title );
-
+ $digg_url = 'http://digg.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $post->post_title );
+
// Record stats
parent::process_request( $post, $post_data );
-
+
// Redirect to Digg
wp_redirect( $digg_url );
die();
}
-
+
public function display_header() {
if ( $this->smart ) {
?>
@@ -553,25 +584,25 @@ class Share_LinkedIn extends Sharing_Source {
}
public function get_display( $post ) {
- $permalink = get_permalink( $post->ID );
+ $share_url = $this->get_share_url( $post->ID );
$display = '';
-
+
if ( $this->smart )
- $display .= sprintf( '<div class="linkedin_button"><script type="in/share" data-url="%s" data-counter="right"></script></div>', esc_url( $permalink ) );
+ $display .= sprintf( '<div class="linkedin_button"><script type="in/share" data-url="%s" data-counter="right"></script></div>', esc_url( $share_url ) );
else
- $display = $this->get_link( $permalink, _x( 'LinkedIn', 'share to', 'jetpack' ), __( 'Click to share on LinkedIn', 'jetpack' ), 'share=linkedin', 'sharing-linkedin-' . $post->ID );
+ $display = $this->get_link( get_permalink( $post->ID ), _x( 'LinkedIn', 'share to', 'jetpack' ), __( 'Click to share on LinkedIn', 'jetpack' ), 'share=linkedin', 'sharing-linkedin-' . $post->ID );
if ( 'icon-text' == $this->button_style || 'text' == $this->button_style )
sharing_register_post_for_share_counts( $post->ID );
return $display;
}
-
+
public function process_request( $post, array $post_data ) {
setup_postdata( $post );
- $post_link = apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id );
+ $post_link = $this->get_share_url( $post->ID );
// http://www.linkedin.com/shareArticle?mini=true&url={articleUrl}&title={articleTitle}&summary={articleSummary}&source={articleSource}
@@ -582,18 +613,16 @@ class Share_LinkedIn extends Sharing_Source {
$encoded_summary = rawurlencode( strip_tags( get_the_excerpt() ) );
if( strlen( $encoded_summary ) > 256 )
$encoded_summary = substr( $encoded_summary, 0, 253 ) . '...';
-
+
$source = get_bloginfo( 'name' );
- $query = add_query_arg( array(
+ $linkedin_url = add_query_arg( array(
'title' => $encoded_title,
'url' => rawurlencode( $post_link ),
'source' => rawurlencode( $source ),
'summary' => $encoded_summary,
- ) );
+ ), 'http://www.linkedin.com/shareArticle?mini=true' );
- $linkedin_url = 'http://www.linkedin.com/shareArticle?mini=true' . $query;
-
// Record stats
parent::process_request( $post, $post_data );
@@ -601,25 +630,36 @@ class Share_LinkedIn extends Sharing_Source {
wp_redirect( $linkedin_url );
die();
}
-
+
public function display_footer() {
- if ( !$this->smart )
+ if ( !$this->smart ) {
$this->js_dialog( $this->shortname, array( 'width' => 580, 'height' => 450 ) );
- else
- echo '<script type="text/javascript" src="//platform.linkedin.com/in.js"></script>';
+ } else {
+ ?><script type="text/javascript">
+ jQuery( document ).ready( function() {
+ jQuery.getScript( 'http://platform.linkedin.com/in.js?async=true', function success() {
+ IN.init();
+ });
+ });
+ jQuery( document.body ).on( 'post-load', function() {
+ if ( typeof IN != 'undefined' )
+ IN.parse();
+ });
+ </script><?php
+ }
}
}
class Share_Facebook extends Sharing_Source {
var $shortname = 'facebook';
private $share_type = 'default';
-
+
public function __construct( $id, array $settings ) {
parent::__construct( $id, $settings );
if ( isset( $settings['share_type'] ) )
$this->share_type = $settings['share_type'];
-
+
if ( 'official' == $this->button_style )
$this->smart = true;
else
@@ -629,21 +669,30 @@ class Share_Facebook extends Sharing_Source {
public function get_name() {
return __( 'Facebook', 'jetpack' );
}
-
+
public function display_header() {
}
-
+
function guess_locale_from_lang( $lang ) {
if ( 'en' == $lang || 'en_US' == $lang || !$lang ) {
return 'en_US';
}
if ( !class_exists( 'GP_Locales' ) ) {
- require JETPACK__PLUGIN_DIR . 'locales.php';
+ if ( !defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) || !file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
+ return false;
+ }
+
+ require JETPACK__GLOTPRESS_LOCALES_PATH;
}
- // Jetpack: get_locale() returns 'it_IT';
- $locale = GP_Locales::by_field( 'wp_locale', $lang );
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ // WP.com: get_locale() returns 'it'
+ $locale = GP_Locales::by_slug( $lang );
+ } else {
+ // Jetpack: get_locale() returns 'it_IT';
+ $locale = GP_Locales::by_field( 'wp_locale', $lang );
+ }
if ( !$locale || empty( $locale->facebook_locale ) ) {
return false;
@@ -653,22 +702,25 @@ class Share_Facebook extends Sharing_Source {
}
public function get_display( $post ) {
+ $share_url = $this->get_share_url( $post->ID );
if ( $this->smart ) {
- $url = 'http://www.facebook.com/plugins/like.php?href=' . rawurlencode( get_permalink( $post->ID ) ) . '&amp;layout=button_count&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;height=21';
-
+ $url = $this->http() . '://www.facebook.com/plugins/like.php?href=' . rawurlencode( $share_url ) . '&amp;layout=button_count&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;height=21';
+
// Default widths to suit English
$inner_w = 90;
-
+
// Locale-specific widths/overrides
$widths = array(
'bg_BG' => 120,
- 'de_DE' => 100,
+ 'cs_CZ' => 135,
+ 'de_DE' => 120,
'da_DK' => 120,
- 'es_ES' => 100,
- 'es_LA' => 100,
+ 'es_ES' => 122,
+ 'es_LA' => 110,
'fi_FI' => 100,
'it_IT' => 100,
'ja_JP' => 100,
+ 'nl_NL' => 130,
'ru_RU' => 128,
);
@@ -676,9 +728,7 @@ class Share_Facebook extends Sharing_Source {
$locale = $this->guess_locale_from_lang( get_locale() );
if ( $locale ) {
- if ( 'en_US' != $locale ) {
- $url .= '&amp;locale=' . $locale;
- }
+ $url .= '&amp;locale=' . $locale;
if ( isset( $widths[$locale] ) ) {
$inner_w = $widths[$locale];
@@ -688,23 +738,23 @@ class Share_Facebook extends Sharing_Source {
$url .= '&amp;width='.$inner_w;
return '<div class="like_button"><iframe src="'.$url.'" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:'.( $inner_w + 6 ).'px; height:21px;" allowTransparency="true"></iframe></div>';
}
-
+
if ( 'icon-text' == $this->button_style || 'text' == $this->button_style )
sharing_register_post_for_share_counts( $post->ID );
return $this->get_link( get_permalink( $post->ID ), _x( 'Facebook', 'share to', 'jetpack' ), __( 'Share on Facebook', 'jetpack' ), 'share=facebook', 'sharing-facebook-' . $post->ID );
}
-
+
public function process_request( $post, array $post_data ) {
- $fb_url = 'http://www.facebook.com/sharer.php?u=' . urlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ) . '&t=' . urlencode( $post->post_title );
-
+ $fb_url = $this->http() . '://www.facebook.com/sharer.php?u=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&t=' . rawurlencode( $post->post_title );
+
// Record stats
parent::process_request( $post, $post_data );
-
+
// Redirect to Facebook
wp_redirect( $fb_url );
die();
}
-
+
public function display_footer() {
$this->js_dialog( $this->shortname );
}
@@ -720,13 +770,13 @@ class Share_Print extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'Print', 'jetpack' );
}
public function get_display( $post ) {
- return $this->get_link( get_permalink( $post->ID ). ( ( is_single() || is_page() ) ? '#print': '' ), _x( 'Print', 'share to', 'jetpack' ), __( 'Click to print', 'jetpack' ) );
+ return $this->get_link( get_permalink( $post->ID ) . ( ( is_single() || is_page() ) ? '#print': '' ), _x( 'Print', 'share to', 'jetpack' ), __( 'Click to print', 'jetpack' ) );
}
}
@@ -740,30 +790,30 @@ class Share_PressThis extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'Press This', 'jetpack' );
}
public function process_request( $post, array $post_data ) {
global $current_user;
-
+
$blogs = get_blogs_of_user( $current_user->ID );
if ( empty( $blogs ) ) {
wp_safe_redirect( get_permalink( $post->ID ) );
die();
}
-
+
$blog = current( $blogs );
- $url = $blog->siteurl.'/wp-admin/press-this.php?u='.urlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ).'&t='.urlencode( $post->post_title ).'&v=4';
+ $url = $blog->siteurl.'/wp-admin/press-this.php?u='.rawurlencode( $this->get_share_url( $post->ID ) ).'&t='.rawurlencode( $post->post_title ).'&v=4';
if ( isset( $_GET['sel'] ) )
- $url .= '&s='.urlencode( $_GET['sel'] );
+ $url .= '&s='.rawurlencode( $_GET['sel'] );
// Record stats
parent::process_request( $post, $post_data );
-
+
// Redirect to Press This
wp_safe_redirect( $url );
die();
@@ -786,65 +836,77 @@ class Share_GooglePlus1 extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'Google +1', 'jetpack' );
}
- public function get_display( $post ) {
- // Smart or not, return the G+ button
- return '<div class="googleplus1_button"><g:plusone size="medium" callback="sharing_plusone" href="' . esc_attr( get_permalink( $post->ID ) ) . '"></g:plusone></div>';
+ public function has_custom_button_style() {
+ return $this->smart;
}
-
- public function display_preview() {
- ?>
- <div class="option option-smart-on">
- <a href="javascript:void(0);return false;" class="share-<?php echo $this->shortname; ?>">
- <span></span>
- </a>
- </div><?php
+
+ public function get_display( $post ) {
+ $share_url = $this->get_share_url( $post->ID );
+
+ if ( $this->smart ) {
+ return '<div class="googleplus1_button"><div class="g-plusone" data-size="medium" data-callback="sharing_plusone" data-href="' . esc_url( $share_url ) . '"></div></div>';
+ } else {
+ //if ( 'icon-text' == $this->button_style || 'text' == $this->button_style )
+ //sharing_register_post_for_share_counts( $post->ID );
+ return $this->get_link( get_permalink( $post->ID ), _x( 'Google +1', 'share to', 'jetpack' ), __( 'Click to share on Google+', 'jetpack' ), 'share=google-plus-1', 'sharing-google-' . $post->ID );
+ }
}
-
+
public function get_state() {
return $this->state;
}
-
+
public function process_request( $post, array $post_data ) {
-
+
if ( isset( $post_data['state'] ) ) {
$this->state = $post_data['state'];
}
// Record stats
parent::process_request( $post, $post_data );
+
+ // Redirect to Google +'s sharing endpoint
+ $url = 'https://plus.google.com/share?url=' . rawurlencode( $this->get_share_url( $post->ID ) );
+ wp_redirect( $url );
die();
}
-
+
public function display_footer() {
global $post;
-?>
- <script type="text/javascript" charset="utf-8">
- function sharing_plusone( obj ) {
- jQuery.ajax( {
- url: '<?php echo get_permalink( $post->ID ) . '?share=google-plus-1'; ?>',
- type: 'POST',
- data: obj
- } );
- }
- </script>
- <script type="text/javascript" src="http://apis.google.com/js/plusone.js"></script>
-<?php
- }
+
+ if ( $this->smart ) { ?>
+ <script type="text/javascript">
+ function sharing_plusone( obj ) {
+ jQuery.ajax( {
+ url: '<?php echo get_permalink( $post->ID ) . '?share=google-plus-1'; ?>',
+ type: 'POST',
+ data: obj
+ } );
+ }
+ jQuery( document.body ).on( 'post-load', function() {
+ gapi.plusone.go();
+ });
+ </script>
+ <script type="text/javascript" src="//apis.google.com/js/plusone.js"></script> <?php
+ } else {
+ $this->js_dialog( 'google-plus-1', array( 'width' => 600, 'height' => 600 ) );
+ }
+ }
public function get_total( $post = false ) {
global $wpdb, $blog_id;
-
- $name = strtolower( $this->get_id() );
-
+
+ $name = strtolower( $this->get_id() );
+
if ( $post == false ) {
// get total number of shares for service
return $wpdb->get_var( $wpdb->prepare( "SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s", $blog_id, $name ) );
}
-
+
//get total shares for a post
return $wpdb->get_var( $wpdb->prepare( "SELECT count FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s", $blog_id, $post->ID, $name ) );
}
@@ -856,14 +918,14 @@ class Share_Custom extends Sharing_Advanced_Source {
private $url;
public $smart = true;
var $shortname;
-
+
public function get_class() {
return 'custom';
}
public function __construct( $id, array $settings ) {
parent::__construct( $id, $settings );
-
+
$opts = $this->get_options();
if ( isset( $settings['name'] ) ) {
@@ -877,46 +939,46 @@ class Share_Custom extends Sharing_Advanced_Source {
if ( isset( $settings['url'] ) )
$this->url = $settings['url'];
}
-
+
public function get_name() {
return $this->name;
}
-
+
public function get_display( $post ) {
$str = $this->get_link( get_permalink( $post->ID ), esc_html( $this->name ), __( 'Click to share', 'jetpack' ), 'share='.$this->id );
- return str_replace( '<span>', '<span style="background-image:url(' . esc_url( $this->icon ) . ');">', $str );
+ return str_replace( '<span>', '<span style="' . esc_attr( 'background-image:url("' . addcslashes( esc_url_raw( $this->icon ), '"' ) . '");' ) . '">', $str );
}
public function process_request( $post, array $post_data ) {
$url = str_replace( '&amp;', '&', $this->url );
- $url = str_replace( '%post_url%', urlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ), $url );
- $url = str_replace( '%post_full_url%', urlencode( get_permalink( $post->ID ) ), $url );
- $url = str_replace( '%post_title%', urlencode( $post->post_title ), $url );
+ $url = str_replace( '%post_url%', rawurlencode( $this->get_share_url( $post->ID ) ), $url );
+ $url = str_replace( '%post_full_url%', rawurlencode( get_permalink( $post->ID ) ), $url );
+ $url = str_replace( '%post_title%', rawurlencode( $post->post_title ), $url );
if ( strpos( $url, '%post_tags%' ) !== false ) {
$tags = get_the_tags( $post->ID );
$tagged = '';
-
+
if ( $tags ) {
foreach ( $tags AS $tag ) {
- $tagged[] = urlencode( $tag->name );
+ $tagged[] = rawurlencode( $tag->name );
}
-
+
$tagged = implode( ',', $tagged );
}
$url = str_replace( '%post_tags%', $tagged, $url );
}
-
+
if ( strpos( $url, '%post_excerpt%' ) !== false ) {
$url_excerpt = $post->post_excerpt;
if ( empty( $url_excerpt ) )
$url_excerpt = $post->post_content;
-
+
$url_excerpt = strip_tags( strip_shortcodes( $url_excerpt ) );
$url_excerpt = wp_html_excerpt( $url_excerpt, 100 );
$url_excerpt = rtrim( preg_replace( '/[^ .]*$/', '', $url_excerpt ) );
- $url = str_replace( '%post_excerpt%', urlencode( $url_excerpt ), $url );
+ $url = str_replace( '%post_excerpt%', rawurlencode( $url_excerpt ), $url );
}
// Record stats
@@ -926,7 +988,7 @@ class Share_Custom extends Sharing_Advanced_Source {
wp_redirect( $url );
die();
}
-
+
public function display_options() {
?>
<div class="input">
@@ -964,13 +1026,13 @@ class Share_Custom extends Sharing_Advanced_Source {
$name = trim( wp_html_excerpt( wp_kses( stripslashes( $data['name'] ), array() ), 30 ) );
$url = trim( esc_url_raw( $data['url'] ) );
$icon = trim( esc_url_raw( $data['icon'] ) );
-
+
if ( $name )
$this->name = $name;
if ( $url )
$this->url = $url;
-
+
if ( $icon )
$this->icon = $icon;
}
@@ -982,25 +1044,25 @@ class Share_Custom extends Sharing_Advanced_Source {
'url' => $this->url,
);
}
-
+
public function display_preview() {
$opts = $this->get_options();
-
+
$text = '&nbsp;';
if ( !$this->smart )
if ( $this->button_style != 'icon' )
$text = $this->get_name();
-
+
$klasses = array( 'share-'.$this->shortname );
-
+
if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' )
$klasses[] = 'share-icon';
-
+
if ( $this->button_style == 'icon' ) {
$text = '';
$klasses[] = 'no-text';
}
-
+
if ( $this->button_style == 'text' )
$klasses[] = 'no-icon';
@@ -1028,24 +1090,29 @@ class Share_Tumblr extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'Tumblr', 'jetpack' );
}
public function get_display( $post ) {
- if ( $this->smart )
- return '<a href="http://www.tumblr.com/share" title="Share on Tumblr" style="display:inline-block; text-indent:-9999px; overflow:hidden; width:62px; height:20px; background:url(\'http://platform.tumblr.com/v1/share_2.png\') top left no-repeat transparent;">Share on Tumblr</a>';
- else
+ if ( $this->smart ) {
+ $target = '';
+ if ( 'new' == $this->open_links )
+ $target = '_blank';
+
+ return '<a target="' . $target . '" href="http://www.tumblr.com/share/link/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&name=' . rawurlencode( $post->post_title ) . '" title="Share on Tumblr" style="display:inline-block; text-indent:-9999px; overflow:hidden; width:62px; height:20px; background:url(\'http://platform.tumblr.com/v1/share_2.png\') top left no-repeat transparent;">Share on Tumblr</a>';
+ } else {
return $this->get_link( get_permalink( $post->ID ), _x( 'Tumblr', 'share to', 'jetpack' ), __( 'Click to share on Tumblr', 'jetpack' ), 'share=tumblr' );
+ }
}
-
+
public function process_request( $post, array $post_data ) {
// Record stats
parent::process_request( $post, $post_data );
-
+
// Redirect to Tumblr's sharing endpoint (a la their bookmarklet)
- $url = 'http://www.tumblr.com/share?v=3&u=' . rawurlencode( get_permalink( $post->ID ) ) . '&t=' . rawurlencode( $post->post_title ) . '&s=';
+ $url = 'http://www.tumblr.com/share?v=3&u=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&t=' . rawurlencode( $post->post_title ) . '&s=';
wp_redirect( $url );
die();
}
@@ -1070,7 +1137,7 @@ class Share_Pinterest extends Sharing_Source {
else
$this->smart = false;
}
-
+
public function get_name() {
return __( 'Pinterest', 'jetpack' );
}
@@ -1078,10 +1145,24 @@ class Share_Pinterest extends Sharing_Source {
public function get_post_image( $content ) {
$image = '';
+ if ( class_exists( 'Jetpack_PostImages' ) ) {
+ // Use the full stack of methods to find an image, except for HTML, which can cause loops
+ $img = Jetpack_PostImages::get_image( $content->ID );
+ if ( !empty( $img['src'] ) )
+ return $img['src'];
+ }
+
+ // If we have to fall back to the following, we only do a few basic image checks
+ $content = $content->post_content;
if ( function_exists('has_post_thumbnail') && has_post_thumbnail() ) {
$thumb_id = get_post_thumbnail_id();
- $thumb = wp_get_attachment_image_src( $thumb_id );
- $image = remove_query_arg( array('w', 'h'), $thumb[0] );
+ $thumb = wp_get_attachment_image_src( $thumb_id, 'full' );
+
+ // This shouldn't be necessary, since has_post_thumbnail() is true,
+ // but... see http://wordpress.org/support/topic/jetpack-youtube-embeds
+ if ( ! $thumb ) return '';
+
+ $image = remove_query_arg( array('w', 'h'), $thumb[0] );
} else if ( preg_match_all('/<img (.+?)>/', $content, $matches) ) {
foreach ( $matches[1] as $attrs ) {
$media = $img = array();
@@ -1091,7 +1172,7 @@ class Share_Pinterest extends Sharing_Source {
continue;
}
else {
- $image = $img['src'];
+ $image = htmlspecialchars_decode( $img['src'] );
break;
}
}
@@ -1102,43 +1183,60 @@ class Share_Pinterest extends Sharing_Source {
public function get_display( $post ) {
if ( $this->smart )
- return '<div class="pinterest_button"><a href="http://pinterest.com/pin/create/button/?url='. rawurlencode( apply_filters( 'sharing_permalink', get_permalink( $post->ID ), $post->ID, $this->id ) ) . '&description=' . rawurlencode( esc_attr( $post->post_title ) ) . '&media=' . rawurlencode( esc_url( $this->get_post_image( $post->post_content ) ) ) . '" class="pin-it-button" count-layout="horizontal"> '. __( 'Pin It', 'sharedaddy') .'</a></div>';
+ return '<div class="pinterest_button"><a href="' . esc_url( 'http://pinterest.com/pin/create/button/?url='. rawurlencode( $this->get_share_url( $post->ID ) ) . '&description=' . rawurlencode( $post->post_title ) . '&media=' . rawurlencode( esc_url_raw( $this->get_post_image( $post ) ) ) ) . '" class="pin-it-button" count-layout="horizontal"> '. __( 'Pin It', 'jetpack') .'</a></div>';
else
return $this->get_link( get_permalink( $post->ID ), _x( 'Pinterest', 'share to', 'jetpack' ), __( 'Click to share on Pinterest', 'jetpack' ), 'share=pinterest' );
}
-
+
public function process_request( $post, array $post_data ) {
- $pinterest_url = 'http://pinterest.com/pin/create/button/?url=' . rawurlencode( get_permalink( $post->ID ) ) . '&description=' . rawurlencode( esc_attr( $post->post_title ) ) . '&media=' . rawurlencode( esc_url( $this->get_post_image( $post->post_content ) ) );
-
// Record stats
parent::process_request( $post, $post_data );
-
- // Redirect to Pinterest
- wp_redirect( $pinterest_url );
- die();
- }
- public function display_footer() {
- if ( !$this->smart ) {
- $this->js_dialog( $this->shortname, array( 'width' => 650, 'height' => 280 ) );
+ // If we're triggering the multi-select panel, then we don't need to redirect to Pinterest
+ if ( !isset( $_GET['js_only'] ) ) {
+ $pinterest_url = esc_url_raw( 'http://pinterest.com/pin/create/button/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&description=' . rawurlencode( $post->post_title ) . '&media=' . rawurlencode( esc_url_raw( $this->get_post_image( $post ) ) ) );
+ wp_redirect( $pinterest_url );
} else {
-?>
- <script type="text/javascript">
- function pinterest_async_load() {
- var s = document.createElement("script");
- s.type = "text/javascript";
- s.async = true;
- s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
- var x = document.getElementsByTagName("script")[0];
- x.parentNode.insertBefore(s, x);
- }
- jQuery(document).on('ready post-load', function() {
- pinterest_async_load();
- });
- </script>
-<?php
+ echo '// share count bumped';
}
- }
+ die();
+ }
+ public function display_footer() {
+ ?>
+ <?php if ( $this->smart ) : ?>
+ <script type="text/javascript">
+ // Pinterest shared resources
+ var s = document.createElement("script");
+ s.type = "text/javascript";
+ s.async = true;
+ s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
+ var x = document.getElementsByTagName("script")[0];
+ x.parentNode.insertBefore(s, x);
+ </script>
+ <?php else : ?>
+ <script type="text/javascript">
+ jQuery(document).on('ready', function(){
+ jQuery('body').on('click', 'a.share-pinterest', function(e){
+ e.preventDefault();
+
+ // Load Pinterest Bookmarklet code
+ var s = document.createElement("script");
+ s.type = "text/javascript";
+ s.src = window.location.protocol + "//assets.pinterest.com/js/pinmarklet.js?r=" + ( Math.random() * 99999999 );
+ var x = document.getElementsByTagName("script")[0];
+ x.parentNode.insertBefore(s, x);
+
+ // Trigger Stats
+ var s = document.createElement("script");
+ s.type = "text/javascript";
+ s.src = this + ( this.toString().indexOf( '?' ) ? '&' : '?' ) + 'js_only=1';
+ var x = document.getElementsByTagName("script")[0];
+ x.parentNode.insertBefore(s, x);
+ });
+ });
+ </script>
+ <?php endif;
+ }
}
diff --git a/plugins/jetpack/modules/sharedaddy/sharing.css b/plugins/jetpack/modules/sharedaddy/sharing.css
index fb45c924..95a09d0e 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing.css
+++ b/plugins/jetpack/modules/sharedaddy/sharing.css
@@ -40,6 +40,7 @@ div.sharedaddy h3,
border: none;
}
+/* @noflip */
.rtl div.sharedaddy h3,
.rtl #content div.sharedaddy h3,
.rtl #main div.sharedaddy h3,
@@ -121,7 +122,7 @@ div.sharedaddy.sharedaddy-dark .sd-block {
div.sharedaddy .sd-content {
width: 82.125%; /* 530px / 640px */
float: right;
- margin: 0;
+ margin: -2px 0 0 0;
}
div.sharedaddy .sd-content ul {
@@ -134,10 +135,12 @@ div.sharedaddy .sd-content li {
display: block;
}
+/* @noflip */
.rtl div.sharedaddy .sd-content {
float: right;
}
+/* @noflip */
.rtl div.sharedaddy .sd-content li {
float: right;
margin: 0 0 5px 5px !important;
@@ -190,7 +193,7 @@ a.sd-button > span {
padding: 4px 8px;
display: block;
opacity: .8;
- line-height: 1;
+ line-height: 1.5em;
text-shadow: none;
}
@@ -202,8 +205,10 @@ a.sd-button:hover span {
font-size: 90%;
color: #666;
margin-left: 5px;
+ line-height: 1;
}
+/* @noflip */
.rtl .sd-button span.share-count {
margin-right: 5px;
}
@@ -212,7 +217,7 @@ a.sd-button:hover span {
.sd-social-icon-text a.sd-button > span,
a.sd-button > span {
- padding: 3px 5px 3px 23px;
+ padding: 1px 5px 1px 23px;
background-position: 2px center;
background-repeat: no-repeat;
}
@@ -249,17 +254,20 @@ div.sharedaddy .no-icon a span, div.sharedaddy li.no-icon div a span {
background-image: none;
}
+/* @noflip */
.rtl .sd-social-icon-text a.sd-button > span,
.rtl a.sd-button > span {
padding: 3px 23px 3px 5px;
background-position: 98% center;
}
+/* @noflip */
.rtl .sd-social-text a.sd-button > span {
padding-left: 0;
padding-right: 5px
}
+/* @noflip */
.rtl div.sharedaddy .no-icon a span, .rtl div.sharedaddy li.no-icon div a span {
padding-left: 0;
padding-right: 5px
@@ -279,6 +287,10 @@ li.share-twitter a.sd-button > span {
background-image: url('images/twitter.png?1');
}
+li.share-google-plus-1 a.sd-button > span {
+ background-image: url('images/googleplus1.png?1');
+}
+
li.share-linkedin a.sd-button > span {
background-image: url('images/linkedin.png');
}
@@ -332,6 +344,11 @@ a.sd-button.share-more span {
background-size: 16px 16px;
}
+ li.share-google-plus-1 a.sd-button > span {
+ background-image: url('images/googleplus1@2x.png');
+ background-size: 16px 16px;
+ }
+
li.share-linkedin a.sd-button > span {
background-image: url('images/linkedin@2x.png');
background-size: 16px 16px;
@@ -379,19 +396,6 @@ a.sd-button.share-more span {
}
-
-/* Special case for non-smart implementations of Google+ button */
-
-div.sharedaddy .sd-content ul li.share-google-plus-1 {
- line-height: 90%;
- margin-bottom: 2px !important;
- min-height: 20px;
-}
-
-div.sharedaddy .sd-social-official .sd-content ul li.share-google-plus-1 {
- padding-top: 0;
-}
-
/* More pannel */
div.sharedaddy .sharing-hidden .inner {
@@ -413,6 +417,7 @@ div.sharedaddy .sharing-hidden .inner {
box-shadow: 0px 2px 8px rgba(0, 0, 0, .2);
}
+/* @noflip */
.rtl div.sharedaddy .sharing-hidden .inner {
margin-left: 0;
margin-right: -100px;
@@ -422,82 +427,97 @@ div.sharedaddy.sharedaddy-dark .sharing-hidden .inner {
border-color: #222;
}
-div.sd-content a.sd-button > span {
- line-height: 1.5em;
-}
+/* =Sharing: Email Dialog
+-------------------------------------------------------------- */
#sharing_email {
- background-color: #FFFFFF;
- border: 1px solid #CCCCCC;
- border-radius: 3px 3px 3px 3px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
- margin-left: -120px;
- padding: 15px;
- position: absolute;
- text-align: left;
- width: 312px;
- z-index: 1001;
+ width: 312px;
+ padding: 15px;
+ position: absolute;
+ margin-left: -120px;
+ z-index: 1001;
+ background-color: #fff;
+ border: 1px solid #ccc;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ -moz-box-shadow: 0px 2px 8px #ccc;
+ -webkit-box-shadow: 0px 2px 8px #ccc;
+ box-shadow: 0px 2px 8px #ccc;
+ -webkit-box-shadow: 0px 2px 8px rgba(0, 0, 0, .2);
+ -moz-box-shadow: 0px 2px 8px rgba(0, 0, 0, .2);
+ box-shadow: 0px 2px 8px rgba(0, 0, 0, .2);
+ text-align: left;
}
div.sharedaddy.sharedaddy-dark #sharing_email {
- border-color: #FFFFFF;
+ border-color: #fff;
}
#sharing_email .errors {
- background-color: #771A09;
- color: #FFFFFF;
- font-size: 11px;
- line-height: 11px;
- margin: 10px 0 0;
- padding: 5px 8px;
+ color: #fff;
+ background-color: #771a09;
+ font-size: 11px;
+ padding: 5px 8px;
+ line-height: 11px;
+ margin: 10px 0 0 0;
}
#sharing_email label {
- color: #333333;
- display: block;
- font-size: 11px;
- font-weight: bold;
- padding: 0 0 4px;
- text-align: left;
- text-shadow: none;
+ font-size: 11px;
+ color: #333;
+ font-weight: bold;
+ display: block;
+ padding: 0 0 4px 0;
+ text-align: left;
+ text-shadow: none;
}
#sharing_email input[type="text"] {
- background: none repeat scroll 0 0 #FFFFFF;
- border: 1px solid #CCCCCC;
- color: #333333;
- margin-bottom: 12px;
- width: 98.5%;
+ width: 98.5%;
+ margin-bottom: 12px;
+ border: 1px solid #ccc;
+ background: #fff;
+ color: #333;
}
#sharing_email .sharing_cancel {
- font-size: 11px;
- padding: 0 0 0 10px;
- text-shadow: none;
+ padding: 0 0 0 10px;
+ font-size: 11px;
+ text-shadow: none;
}
#sharing_email .recaptcha {
- height: 123px;
- margin: 10px 0 14px;
- width: 312px;
+ width: 312px;
+ height: 123px;
+ margin: 10px 0 14px 0;
}
/* =RTL
-------------------------------------------------------------- */
+/* @noflip */
body.rtl .sharing ul {
float: right;
}
+
+/* @noflip */
body.rtl .sharing li {
margin: 0 0 0 10px !important;
}
+
+/* @noflip */
.rtl #sharing_email {
- margin-left: 0;
- margin-right: -120px;
- text-align: right;
+ margin-left: -0px;
+ margin-right: -120px;
+ text-align: right
}
+
+/* @noflip */
+.rtl #sharing_email label {
+ text-align: right
+}
+
+/* @noflip */
.rtl #sharing_email .sharing_cancel {
- padding: 0 10px 0 0;
+ padding: 0 10px 0 0;
}
-.rtl #sharing_email label {
- text-align: right;
-} \ No newline at end of file
diff --git a/plugins/jetpack/modules/sharedaddy/sharing.js b/plugins/jetpack/modules/sharedaddy/sharing.js
index a6c29494..68482c60 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing.js
+++ b/plugins/jetpack/modules/sharedaddy/sharing.js
@@ -1,15 +1,21 @@
var WPCOMSharing = {
+ done_urls : [],
get_counts : function( url ) {
+ if ( 'undefined' != typeof WPCOMSharing.done_urls[ WPCOM_sharing_counts[ url ] ] )
+ return;
+
if ( jQuery( '#sharing-facebook-' + WPCOM_sharing_counts[ url ] ).length )
- jQuery.getScript( 'https://graph.facebook.com/' + encodeURIComponent( url ) + '?callback=WPCOMSharing.update_facebook_count' );
+ jQuery.getScript( 'https://api.facebook.com/method/fql.query?query=' + encodeURIComponent( "SELECT total_count, url FROM link_stat WHERE url='" + url + "'" ) + '&format=json&callback=WPCOMSharing.update_facebook_count' );
if ( jQuery( '#sharing-twitter-' + WPCOM_sharing_counts[ url ] ).length )
- jQuery.getScript( 'http://urls.api.twitter.com/1/urls/count.json?callback=WPCOMSharing.update_twitter_count&url=' + encodeURIComponent( url ) );
+ jQuery.getScript( window.location.protocol + '//cdn.api.twitter.com/1/urls/count.json?callback=WPCOMSharing.update_twitter_count&url=' + encodeURIComponent( url ) );
if ( jQuery( '#sharing-linkedin-' + WPCOM_sharing_counts[ url ] ).length )
- jQuery.getScript( 'http://www.linkedin.com/countserv/count/share?format=jsonp&callback=WPCOMSharing.update_linkedin_count&url=' + encodeURIComponent( url ) );
+ jQuery.getScript( window.location.protocol + '//www.linkedin.com/countserv/count/share?format=jsonp&callback=WPCOMSharing.update_linkedin_count&url=' + encodeURIComponent( url ) );
+
+ WPCOMSharing.done_urls[ WPCOM_sharing_counts[ url ] ] = true;
},
update_facebook_count : function( data ) {
- if ( 'undefined' != typeof data.shares && ( data.shares * 1 ) > 0 ) {
- WPCOMSharing.inject_share_count( 'sharing-facebook-' + WPCOM_sharing_counts[ data.id ], data.shares );
+ if ( 'undefined' != typeof data[0].total_count && ( data[0].total_count * 1 ) > 0 ) {
+ WPCOMSharing.inject_share_count( 'sharing-facebook-' + WPCOM_sharing_counts[ data[0].url ], data[0].total_count );
}
},
update_twitter_count : function( data ) {
@@ -40,14 +46,16 @@ var WPCOMSharing = {
return /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test( this.val() );
}
} );
-
- if ( 'undefined' != typeof WPCOM_sharing_counts ) {
- for ( var url in WPCOM_sharing_counts ) {
- WPCOMSharing.get_counts( url );
- }
- }
- $( document ).on( 'ready post-load', function() {
+ $( document ).on( 'ready', WPCOMSharing_do );
+ $( document.body ).on( 'post-load', WPCOMSharing_do );
+
+ function WPCOMSharing_do() {
+ if ( 'undefined' != typeof WPCOM_sharing_counts ) {
+ for ( var url in WPCOM_sharing_counts ) {
+ WPCOMSharing.get_counts( url );
+ }
+ }
var $more_sharing_buttons = $( '.sharedaddy a.sharing-anchor' );
$more_sharing_buttons.click( function() {
@@ -58,7 +66,7 @@ var WPCOMSharing = {
if ( $( this ).attr( 'href' ) && $( this ).attr( 'href' ).indexOf( 'share=' ) != -1 )
$( this ).attr( 'href', $( this ).attr( 'href' ) + '&nb=1' );
} );
-
+
// Show hidden buttons
// Touchscreen device: use click.
@@ -71,14 +79,14 @@ var WPCOMSharing = {
// We're in the middle of some other event's animation
return;
}
-
+
if ( true === $more_sharing_pane.data( 'justSlid' ) ) {
// We just finished some other event's animation - don't process click event so that slow-to-react-clickers don't get confused
return;
}
-
+
$( '#sharing_email' ).slideUp( 200 );
-
+
$more_sharing_pane.css( {
left: $more_sharing_button.position().left + 'px',
top: $more_sharing_button.position().top + $more_sharing_button.height() + 3 + 'px'
@@ -95,7 +103,7 @@ var WPCOMSharing = {
// Create a timer to make the area appear if the mouse hovers for a period
var timer = setTimeout( function() {
$( '#sharing_email' ).slideUp( 200 );
-
+
$more_sharing_pane.data( 'justSlid', true );
$more_sharing_pane.css( {
left: $more_sharing_button.position().left + 'px',
@@ -103,44 +111,49 @@ var WPCOMSharing = {
} ).slideDown( 200, function() {
// Mark the item as have being appeared by the hover
$more_sharing_button.data( 'hasoriginal', true ).data( 'hasitem', false );
-
- // Remove all special handlers
- $more_sharing_pane.mouseleave( handler_item_leave ).mouseenter( handler_item_enter );
- $more_sharing_button.mouseleave( handler_original_leave ).mouseenter( handler_original_enter );
+
setTimeout( function() {
$more_sharing_pane.data( 'justSlid', false );
}, 300 );
+
+ if ( $more_sharing_pane.find( '.share-google-plus-1' ).size() ) {
+ // The pane needs to stay open for the Google+ Button
+ return;
+ }
+
+ $more_sharing_pane.mouseleave( handler_item_leave ).mouseenter( handler_item_enter );
+ $more_sharing_button.mouseleave( handler_original_leave ).mouseenter( handler_original_enter );
} );
-
+
// The following handlers take care of the mouseenter/mouseleave for the share button and the share area - if both are left then we close the share area
var handler_item_leave = function() {
$more_sharing_button.data( 'hasitem', false );
-
+
if ( $more_sharing_button.data( 'hasoriginal' ) === false ) {
var timer = setTimeout( close_it, 800 );
$more_sharing_button.data( 'timer2', timer );
}
};
-
+
var handler_item_enter = function() {
$more_sharing_button.data( 'hasitem', true );
clearTimeout( $more_sharing_button.data( 'timer2' ) );
- }
-
+ }
+
var handler_original_leave = function() {
$more_sharing_button.data( 'hasoriginal', false );
-
+
if ( $more_sharing_button.data( 'hasitem' ) === false ) {
var timer = setTimeout( close_it, 800 );
$more_sharing_button.data( 'timer2', timer );
}
};
-
+
var handler_original_enter = function() {
$more_sharing_button.data( 'hasoriginal', true );
clearTimeout( $more_sharing_button.data( 'timer2' ) );
};
-
+
var close_it = function() {
$more_sharing_pane.data( 'justSlid', true );
$more_sharing_pane.slideUp( 200, function() {
@@ -148,36 +161,36 @@ var WPCOMSharing = {
$more_sharing_pane.data( 'justSlid', false );
}, 300 );
} );
-
+
// Clear all hooks
$more_sharing_button.unbind( 'mouseleave', handler_original_leave ).unbind( 'mouseenter', handler_original_enter );
$more_sharing_pane.unbind( 'mouseleave', handler_item_leave ).unbind( 'mouseenter', handler_item_leave );
return false;
};
}, 200 );
-
+
// Remember the timer so we can detect it on the mouseout
$more_sharing_button.data( 'timer', timer );
}
}, function() {
// Mouse out - remove any timer
- $more_sharing_buttons.each( function() {
+ $more_sharing_buttons.each( function() {
clearTimeout( $( this ).data( 'timer' ) );
} );
$more_sharing_buttons.data( 'timer', false );
} );
}
-
+
// Add click functionality
$( '.sharedaddy ul' ).each( function( item ) {
printUrl = function ( uniqueId, urlToPrint ) {
$( 'body:first' ).append( '<iframe style="position:fixed;top:100;left:100;height:1px;width:1px;border:none;" id="printFrame-' + uniqueId + '" name="printFrame-' + uniqueId + '" src="' + urlToPrint + '" onload="frames[\'printFrame-' + uniqueId + '\'].focus();frames[\'printFrame-' + uniqueId + '\'].print();"></iframe>' )
};
-
+
// Print button
$( this ).find( 'a.share-print' ).click( function() {
ref = $( this ).attr( 'href' );
-
+
var do_print = function() {
if ( ref.indexOf( '#print' ) == -1 ) {
uid = new Date().getTime();
@@ -186,7 +199,7 @@ var WPCOMSharing = {
else
print();
}
-
+
// Is the button in a dropdown?
if ( $( this ).parents( '.sharing-hidden' ).length > 0 ) {
$( this ).parents( '.inner' ).slideUp( 0, function() {
@@ -198,11 +211,11 @@ var WPCOMSharing = {
return false;
} );
-
+
// Press This button
$( this ).find( 'a.share-press-this' ).click( function() {
var s = '';
-
+
if ( window.getSelection )
s = window.getSelection();
else if( document.getSelection )
@@ -213,7 +226,7 @@ var WPCOMSharing = {
if ( s )
$( this ).attr( 'href', $( this ).attr( 'href' ) + '&sel=' + encodeURI( s ) );
- if ( !window.open( $( this ).attr( 'href' ), 't', 'toolbar=0,resizable=1,scrollbars=1,status=1,width=720,height=570' ) )
+ if ( !window.open( $( this ).attr( 'href' ), 't', 'toolbar=0,resizable=1,scrollbars=1,status=1,width=720,height=570' ) )
document.location.href = $( this ).attr( 'href' );
return false;
@@ -221,8 +234,8 @@ var WPCOMSharing = {
// Email button
$( this ).find( 'a.share-email' ).click( function() {
- var url = $( this ).attr( 'href' );
-
+ var url = $( this ).attr( 'href' ), key;
+
if ( $( '#sharing_email' ).is( ':visible' ) )
$( '#sharing_email' ).slideUp( 200 );
else {
@@ -232,8 +245,8 @@ var WPCOMSharing = {
$( '#sharing_email form' ).show();
$( '#sharing_email form input[type=submit]' ).removeAttr( 'disabled' );
$( '#sharing_email form a.sharing_cancel' ).show();
-
- var key = '';
+
+ key = '';
if ( $( '#recaptcha_public_key' ).length > 0 )
key = $( '#recaptcha_public_key' ).val();
@@ -245,7 +258,7 @@ var WPCOMSharing = {
left: $( this ).offset().left + 'px',
top: $( this ).offset().top + $( this ).height() + 'px'
} ).slideDown( 200 );
-
+
// Hook up other buttons
$( '#sharing_email a.sharing_cancel' ).unbind( 'click' ).click( function() {
$( '#sharing_email .errors' ).hide();
@@ -253,25 +266,25 @@ var WPCOMSharing = {
$( '#sharing_background' ).fadeOut();
return false;
} );
-
+
// Submit validation
$( '#sharing_email input[type=submit]' ).unbind( 'click' ).click( function() {
var form = $( this ).parents( 'form' );
-
+
// Disable buttons + enable loading icon
$( this ).prop( 'disabled', true );
form.find( 'a.sharing_cancel' ).hide();
form.find( 'img.loading' ).show();
-
+
$( '#sharing_email .errors' ).hide();
$( '#sharing_email .error' ).removeClass( 'error' );
-
+
if ( $( '#sharing_email input[name=source_email]' ).share_is_email() == false )
$( '#sharing_email input[name=source_email]' ).addClass( 'error' );
-
+
if ( $( '#sharing_email input[name=target_email]' ).share_is_email() == false )
$( '#sharing_email input[name=target_email]' ).addClass( 'error' );
-
+
if ( $( '#sharing_email .error' ).length == 0 ) {
// AJAX send the form
$.ajax( {
@@ -298,10 +311,10 @@ var WPCOMSharing = {
}
}
} );
-
+
return false;
}
-
+
form.find( 'img.loading' ).hide();
form.find( 'input[type=submit]' ).removeAttr( 'disabled' );
form.find( 'a.sharing_cancel' ).show();
@@ -310,13 +323,13 @@ var WPCOMSharing = {
return false;
} );
}
-
+
return false;
} );
} );
-
+
$( 'li.share-email, li.share-custom a.sharing-anchor' ).addClass( 'share-service-visible' );
- } );
+ }
})( jQuery );
// Recaptcha code
diff --git a/plugins/jetpack/modules/sharedaddy/sharing.php b/plugins/jetpack/modules/sharedaddy/sharing.php
index 3dd6f8d4..118f851c 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing.php
+++ b/plugins/jetpack/modules/sharedaddy/sharing.php
@@ -6,7 +6,7 @@ class Sharing_Admin {
define( 'WP_SHARING_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'WP_SHARING_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
}
-
+
require_once WP_SHARING_PLUGIN_DIR.'sharing-service.php';
add_action( 'admin_init', array( &$this, 'admin_init' ) );
@@ -21,16 +21,16 @@ class Sharing_Admin {
add_action( 'wp_ajax_sharing_new_service', array( &$this, 'ajax_new_service' ) );
add_action( 'wp_ajax_sharing_delete_service', array( &$this, 'ajax_delete_service' ) );
}
-
+
public function sharing_head() {
wp_enqueue_script( 'sharing-js', WP_SHARING_PLUGIN_URL.'admin-sharing.js', array( 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-sortable', 'jquery-form' ), 2 );
- wp_enqueue_style( 'sharing-admin', WP_SHARING_PLUGIN_URL.'admin-sharing.css', false, WP_SHARING_PLUGIN_VERSION );
- wp_enqueue_style( 'sharing', WP_SHARING_PLUGIN_URL.'sharing.css', false, WP_SHARING_PLUGIN_VERSION );
- wp_enqueue_script( 'sharing-js-fe', WP_SHARING_PLUGIN_URL . 'sharing.js', array( ), 2 );
+ wp_enqueue_style( 'sharing-admin', WP_SHARING_PLUGIN_URL.'admin-sharing.css', false, JETPACK__VERSION );
+ wp_enqueue_style( 'sharing', WP_SHARING_PLUGIN_URL.'sharing.css', false, JETPACK__VERSION );
+ wp_enqueue_script( 'sharing-js-fe', WP_SHARING_PLUGIN_URL . 'sharing.js', array( ), 3 );
add_thickbox();
}
-
+
public function admin_init() {
if ( isset( $_GET['page'] ) && ( $_GET['page'] == 'sharing.php' || $_GET['page'] == 'sharing' ) )
$this->process_requests();
@@ -41,29 +41,35 @@ class Sharing_Admin {
$sharer = new Sharing_Service();
$sharer->set_global_options( $_POST );
do_action( 'sharing_admin_update' );
-
+
wp_safe_redirect( admin_url( 'options-general.php?page=sharing&update=saved' ) );
die();
}
}
-
+
public function subscription_menu( $user ) {
+ if ( !defined( 'IS_WPCOM' ) || !IS_WPCOM ) {
+ $active = Jetpack::get_active_modules();
+ if ( !in_array( 'publicize', $active ) && !current_user_can( 'manage_options' ) )
+ return;
+ }
+
add_submenu_page( 'options-general.php', __( 'Sharing Settings', 'jetpack' ), __( 'Sharing', 'jetpack' ), 'publish_posts', 'sharing', array( &$this, 'management_page' ) );
}
-
+
public function ajax_save_services() {
if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'sharing-options' ) && isset( $_POST['hidden'] ) && isset( $_POST['visible'] ) ) {
$sharer = new Sharing_Service();
-
+
$sharer->set_blog_services( explode( ',', $_POST['visible'] ), explode( ',', $_POST['hidden'] ) );
die();
}
}
-
+
public function ajax_new_service() {
if ( isset( $_POST['_wpnonce'] ) && isset( $_POST['sharing_name'] ) && isset( $_POST['sharing_url'] ) && isset( $_POST['sharing_icon'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'sharing-new_service' ) ) {
$sharer = new Sharing_Service();
- if ( $service = $sharer->new_service( $_POST['sharing_name'], $_POST['sharing_url'], $_POST['sharing_icon'] ) ) {
+ if ( $service = $sharer->new_service( stripslashes( $_POST['sharing_name'] ), stripslashes( $_POST['sharing_url'] ), stripslashes( $_POST['sharing_icon'] ) ) ) {
$this->output_service( $service->get_id(), $service );
echo '<!--->';
$service->button_style = 'icon-text';
@@ -76,14 +82,14 @@ class Sharing_Admin {
// Fail
die( '1' );
}
-
+
public function ajax_delete_service() {
if ( isset( $_POST['_wpnonce'] ) && isset( $_POST['service'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'sharing-options_'.$_POST['service'] ) ) {
$sharer = new Sharing_Service();
$sharer->delete_service( $_POST['service'] );
}
}
-
+
public function ajax_save_options() {
if ( isset( $_POST['_wpnonce'] ) && isset( $_POST['service'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'sharing-options_'.$_POST['service'] ) ) {
$sharer = new Sharing_Service();
@@ -102,29 +108,23 @@ class Sharing_Admin {
die();
}
}
-
+
public function output_preview( $service ) {
$klasses = array( 'advanced', 'preview-item' );
-
- if (
- 'googleplus1' == $service->shortname
- ||
- $service->button_style != 'text'
- ||
- $service->has_custom_button_style()
- ) {
+
+ if ( $service->button_style != 'text' || $service->has_custom_button_style() ) {
$klasses[] = 'preview-'.$service->get_class();
$klasses[] = 'share-'.$service->get_class();
-
+
if ( $service->get_class() != $service->get_id() )
$klasses[] = 'preview-'.$service->get_id();
}
-
+
echo '<li class="'.implode( ' ', $klasses ).'">';
echo $service->display_preview();
echo '</li>';
}
-
+
public function output_service( $id, $service, $show_dropdown = false ) {
?>
<li class="service advanced share-<?php echo $service->get_class(); ?>" id="<?php echo $service->get_id(); ?>">
@@ -161,21 +161,21 @@ class Sharing_Admin {
<div class="wrap">
<div class="icon32" id="icon-options-general"><br /></div>
<h2><?php _e( 'Sharing Settings', 'jetpack' ); ?></h2>
-
+
<?php do_action( 'pre_admin_screen_sharing' ) ?>
-
+
<?php if ( current_user_can( 'manage_options' ) ) : ?>
-
- <h3><?php _e( 'Sharing Buttons' ) ?></h3>
- <p><?php _e( 'Add sharing buttons to your blog and allow your visitors to share posts with their friends.' ) ?></p>
-
+
+ <h3><?php _e( 'Sharing Buttons', 'jetpack' ) ?></h3>
+ <p><?php _e( 'Add sharing buttons to your blog and allow your visitors to share posts with their friends.', 'jetpack' ) ?></p>
+
<div id="services-config">
<table id="available-services">
<tr>
<td class="description">
<h3><?php _e( 'Available Services', 'jetpack' ); ?></h3>
<p><?php _e( "Drag and drop the services you'd like to enable into the box below.", 'jetpack' ); ?></p>
- <p><a href="#TB_inline?height=395&amp;width=600&amp;inlineId=new-service" title="<?php echo esc_attr( __( 'Add a new service', 'jetpack' ) ); ?>" class="thickbox"><?php _e( 'Add a new service', 'jetpack' ); ?></a></p>
+ <p><a href="#TB_inline?height=395&amp;width=600&amp;inlineId=new-service" title="<?php echo esc_attr( __( 'Add a new service', 'jetpack' ) ); ?>" class="thickbox" id="add-a-new-service"><?php _e( 'Add a new service', 'jetpack' ); ?></a></p>
</td>
<td class="services">
<ul class="services-available" style="height: 100px;">
@@ -186,11 +186,15 @@ class Sharing_Admin {
?>
<?php endforeach; ?>
</ul>
+ <?php
+ if ( -1 == get_option( 'blog_public' ) )
+ echo '<p><strong>'.__( 'Please note that your services have been restricted because your site is private.', 'jetpack' ).'</strong></p>';
+ ?>
<br class="clearing" />
</td>
</tr>
</table>
-
+
<table id="enabled-services">
<tr>
<td class="description">
@@ -201,19 +205,19 @@ class Sharing_Admin {
<p><?php _e( 'Services dragged here will appear individually.', 'jetpack' ); ?></p>
</td>
<td class="services" id="share-drop-target">
- <h2 id="drag-instructions" <?php if ( count( $enabled['visible'] ) > 0 ) echo ' style="display: none"'; ?>><?php _e( 'Drag and drop available services here', 'jetpack' ); ?></h2>
-
+ <h2 id="drag-instructions" <?php if ( count( $enabled['visible'] ) > 0 ) echo ' style="display: none"'; ?>><?php _e( 'Drag and drop available services here.', 'jetpack' ); ?></h2>
+
<ul class="services-enabled">
<?php foreach ( $enabled['visible'] as $id => $service ) : ?>
<?php $this->output_service( $id, $service, true ); ?>
<?php endforeach; ?>
-
+
<li class="end-fix"></li>
</ul>
- </td>
+ </td>
<td id="hidden-drop-target" class="services">
<p><?php _e( 'Services dragged here will be hidden behind a share button.', 'jetpack' ); ?></p>
-
+
<ul class="services-hidden">
<?php foreach ( $enabled['hidden'] as $id => $service ) : ?>
<?php $this->output_service( $id, $service, true ); ?>
@@ -222,8 +226,8 @@ class Sharing_Admin {
</ul>
</td>
</tr>
- </table>
-
+ </table>
+
<table id="live-preview">
<tr>
<td class="description">
@@ -240,12 +244,12 @@ class Sharing_Admin {
<?php foreach ( $enabled['visible'] as $id => $service ) : ?>
<?php $this->output_preview( $service ); ?>
<?php endforeach; ?>
-
+
<?php if ( count( $enabled['hidden'] ) > 0 ) : ?>
<li class="advanced"><a href="#" class="sharing-anchor sd-button share-more"><span><?php _e( 'More', 'jetpack' ); ?></span></a></li>
<?php endif; ?>
</ul>
-
+
<?php if ( count( $enabled['hidden'] ) > 0 ) : ?>
<div class="sharing-hidden">
<div class="inner" style="display: none; <?php echo count( $enabled['hidden'] ) == 1 ? 'width:150px;' : ''; ?>">
@@ -254,18 +258,18 @@ class Sharing_Admin {
<?php else: ?>
<ul>
<?php endif; ?>
-
+
<?php foreach ( $enabled['hidden'] as $id => $service ) {
$this->output_preview( $service );
}?>
- </ul>
+ </ul>
</div>
</div>
<?php endif; ?>
<ul class="archive" style="display:none;">
- <?php
- foreach ( $sharer->get_all_services_blog() as $id => $service ) :
+ <?php
+ foreach ( $sharer->get_all_services_blog() as $id => $service ) :
if ( isset( $enabled['visible'][$id] ) )
$service = $enabled['visible'][$id];
elseif ( isset( $enabled['hidden'][$id] ) )
@@ -284,7 +288,7 @@ class Sharing_Admin {
</td>
</tr>
</table>
-
+
<form method="post" action="<?php echo admin_url( 'admin-ajax.php' ); ?>" id="save-enabled-shares">
<input type="hidden" name="action" value="sharing_save_services" />
<input type="hidden" name="visible" value="<?php echo implode( ',', array_keys( $enabled['visible'] ) ); ?>" />
@@ -322,7 +326,7 @@ class Sharing_Admin {
</select>
</td>
</tr>
- <tr valign="top">
+ <?php echo apply_filters( 'sharing_show_buttons_on_row_start', '<tr valign="top">' ); ?>
<th scope="row"><label><?php _e( 'Show buttons on', 'jetpack' ); ?></label></th>
<td>
<?php
@@ -338,19 +342,19 @@ class Sharing_Admin {
<?php if ( $br ) echo '<br />'; ?><label><input type="checkbox"<?php checked( in_array( $show, $global['show'] ) ); ?> name="show[]" value="<?php echo esc_attr( $show ); ?>" /> <?php echo esc_html( $label ); ?></label>
<?php $br = true; endforeach; ?>
</td>
- </tr>
-
+ <?php echo apply_filters( 'sharing_show_buttons_on_row_end', '</tr>' ); ?>
+
<?php do_action( 'sharing_global_options' ); ?>
</tbody>
</table>
-
+
<p class="submit">
<input type="submit" name="submit" class="button-primary" value="<?php _e( 'Save Changes', 'jetpack' ); ?>" />
</p>
-
+
<input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce( 'sharing-options' );?>" />
</form>
-
+
<div id="new-service" style="display: none">
<form method="post" action="<?php echo admin_url( 'admin-ajax.php' ); ?>" id="new-service-form">
<table class="form-table">
@@ -365,9 +369,9 @@ class Sharing_Admin {
<th scope="row" width="100"><label><?php _e( 'Sharing URL', 'jetpack' ); ?></label></th>
<td>
<input type="text" name="sharing_url" id="new_sharing_url" size="40" />
-
+
<p><?php _e( 'You can add the following variables to your service sharing URL:', 'jetpack' ); ?><br/>
- <code>%post_title%</code>, <code>%post_url%</code>, <code>%post_full_url%</code>, <code>%post_excerpt%</code>, <code>%post_full_url%</code>, <code>%post_tags%</code></p>
+ <code>%post_title%</code>, <code>%post_url%</code>, <code>%post_full_url%</code>, <code>%post_excerpt%</code>, <code>%post_tags%</code></p>
</td>
</tr>
<tr valign="top">
@@ -384,7 +388,7 @@ class Sharing_Admin {
<img src="<?php echo admin_url( 'images/loading.gif' ); ?>" width="16" height="16" alt="loading" style="vertical-align: middle; display: none" />
</td>
</tr>
-
+
<?php do_action( 'sharing_new_service_form' ); ?>
</tbody>
</table>
@@ -394,18 +398,18 @@ class Sharing_Admin {
<div class="inerror" style="display: none; margin-top: 15px">
<p><?php _e( 'An error occurred creating your new sharing service - please check you gave valid details.', 'jetpack' ); ?></p>
</div>
-
+
<input type="hidden" name="action" value="sharing_new_service" />
- <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce( 'sharing-new_service' );?>" />
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce( 'sharing-new_service' );?>" />
</form>
</div>
-
-
+
+
<?php endif; ?>
</div>
-
+
<script type="text/javascript">
var sharing_loading_icon = '<?php echo esc_js( admin_url( "/images/loading.gif" ) ); ?>';
<?php if ( isset( $_GET['create_new_service'] ) && 'true' == $_GET['create_new_service'] ) : ?>
diff --git a/plugins/jetpack/modules/shortcodes/audio.php b/plugins/jetpack/modules/shortcodes/audio.php
index 7b507a5f..9c6b49eb 100644
--- a/plugins/jetpack/modules/shortcodes/audio.php
+++ b/plugins/jetpack/modules/shortcodes/audio.php
@@ -6,7 +6,7 @@
class AudioShortcode {
static $add_script = false;
-
+
/**
* Add all the actions & resgister the shortcode
*/
@@ -161,8 +161,8 @@ class AudioShortcode {
// generate default titles
$file_titles = array();
- for ( $i = 0; $i < $num_files; $i++ ) {
- $file_titles[] = 'Track #' . ($i+1);
+ for ( $i = 0; $i < $num_files; $i++ ) {
+ $file_titles[] = 'Track #' . ($i+1);
}
// replace with real titles if they exist
@@ -190,7 +190,7 @@ class AudioShortcode {
$to_remove = array();
foreach ( $sound_files as $i => $sfile ) {
$file_extension = pathinfo( $sfile, PATHINFO_EXTENSION );
- if ( ! preg_match( '/^(mp3|wav|ogg|oga|m4a|aac|webm)$/', $file_extension ) ) {
+ if ( ! preg_match( '/^(mp3|wav|ogg|oga|m4a|aac|webm)$/i', $file_extension ) ) {
$html5_audio .= '<!-- Audio shortcode unsupported audio format -->';
if ( 1 == $num_files ) {
$html5_audio .= $not_supported;
@@ -199,7 +199,7 @@ class AudioShortcode {
$to_remove[] = $i; // make a note of the bad files
$all_mp3 = false;
continue;
- } elseif ( ! preg_match( '/^mp3$/', $file_extension ) ) {
+ } elseif ( ! preg_match( '/^mp3$/i', $file_extension ) ) {
$all_mp3 = false;
}
@@ -240,9 +240,9 @@ CONTROLS;
// override html5 audio code w/ just not supported code
if ( is_feed() ) {
$html5_audio = $not_supported;
- }
+ }
- if ( $all_mp3 ) {
+ if ( $all_mp3 ) {
// process regular flash player, inserting HTML5 tags into object as fallback
$audio_tags = <<<FLASH
<object id='wp-as-{$post->ID}_{$ap_playerID}-flash' type='application/x-shockwave-flash' data='$swfurl' width='$width' height='24'>
@@ -268,7 +268,7 @@ FLASH;
// mashup the artist/titles for the script
$script_titles = array();
- for ( $i = 0; $i < $num_files; $i++ ) {
+ for ( $i = 0; $i < $num_files; $i++ ) {
$script_titles[] = $file_artists[$i] . $file_titles[$i];
}
@@ -279,16 +279,27 @@ FLASH;
$script = <<<SCRIPT
<script type='text/javascript'>
//<![CDATA[
- jQuery(document).on( 'ready as-script-load', function($) {
- if ( typeof window.audioshortcode != 'undefined' ) {
+ (function() {
+ var prep = function() {
+ if ( 'undefined' === typeof window.audioshortcode ) { return; }
audioshortcode.prep(
'{$post->ID}_{$ap_playerID}',
$script_files,
$script_titles,
$volume,
- $script_loop );
+ $script_loop
+ );
+ };
+ if ( 'undefined' === typeof jQuery ) {
+ if ( document.addEventListener ) {
+ window.addEventListener( 'load', prep, false );
+ } else if ( document.attachEvent ) {
+ window.attachEvent( 'onload', prep );
+ }
+ } else {
+ jQuery(document).on( 'ready as-script-load', prep );
}
- } );
+ })();
//]]>
</script>
SCRIPT;
@@ -297,7 +308,7 @@ SCRIPT;
if ( 0 < $num_good && ! is_feed() ) {
$audio_tags .= $script;
}
-
+
return "<span style='text-align:left;display:block;'><p>$audio_tags</p></span>";
}
@@ -305,11 +316,11 @@ SCRIPT;
* If the theme uses infinite scroll, include jquery at the start
*/
function check_infinite() {
- if ( current_theme_supports( 'infinite-scroll' ) ) {
+ if ( current_theme_supports( 'infinite-scroll' ) && class_exists( 'The_Neverending_Home_Page' ) && The_Neverending_Home_Page::archive_supports_infinity() )
wp_enqueue_script( 'jquery' );
- }
}
+
/**
* Dynamically load the .js, if needed
*
@@ -331,8 +342,8 @@ SCRIPT;
wp_as_js.type = 'text/javascript';
wp_as_js.src = $script_url;
wp_as_js.async = true;
- wp_as_js.onload = function() {
- jQuery( document.body ).trigger( 'as-script-load' );
+ wp_as_js.onload = function() {
+ jQuery( document.body ).trigger( 'as-script-load' );
};
document.getElementsByTagName( 'head' )[0].appendChild( wp_as_js );
} else {
diff --git a/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css b/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css
new file mode 100644
index 00000000..167ec706
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css
@@ -0,0 +1,131 @@
+/* This file was automatically generated on Jan 06 2013 05:39:50 */
+
+.slideshow-window {
+ background-color: #222;
+ border: 20px solid #222;
+ border-radius: 11px;
+ -moz-border-radius: 11px;
+ -webkit-border-radius: 11px;
+ -khtml-border-radius: 11px;
+ margin-bottom: 20px;
+}
+
+.slideshow-window, .slideshow-window * {
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ box-sizing: content-box;
+}
+
+.slideshow-loading {
+ height: 100%;
+ text-align: center;
+ margin: auto;
+}
+
+body div.slideshow-window * img {
+ /* Override any styles that might be present in the page stylesheet */
+ border-width: 0 !important;
+ padding: 0 !important;
+ background-color: transparent !important;
+ background-image: none !important;
+ max-width: 100%;
+}
+
+.slideshow-loading img {
+ vertical-align: middle;
+}
+
+.slideshow-slide {
+ height: 100%;
+ width: 100%;
+ text-align: center;
+ margin: auto;
+ display: none;
+}
+
+.slideshow-slide img {
+ vertical-align: middle;
+}
+
+.slideshow-line-height-hack {
+ overflow: hide;
+ width: 0px;
+ font-size: 0px;
+}
+
+.slideshow-slide-caption {
+ font-size: 13px;
+ font-family: "Helvetica Neue", sans-serif;
+ color: #f7f7f7;
+ text-shadow: #222 2px 1px 1px;
+ line-height: 25px;
+ height: 25px;
+ position: absolute;
+ bottom: 5px;
+ right: 0;
+ z-index: 100;
+ width: 100%;
+ text-align: center;
+}
+
+/* @noflip */
+.slideshow-controls {
+ z-index: 1000;
+ position: absolute;
+ bottom: 30px;
+ margin: auto;
+ text-align: center;
+ width: 100%;
+ display: none;
+ direction:ltr;
+}
+
+body div div.slideshow-controls a,
+body div div.slideshow-controls a:hover {
+ border:2px solid rgba(255,255,255,0.1) !important;
+ background-color: #000 !important;
+ background-color: rgba(0,0,0,0.6) !important;
+ background-image: url('../../img/slideshow-controls.png') !important;
+ background-repeat: no-repeat;
+ background-size: 142px 16px !important;
+ background-position: -34px 8px !important;
+ color: #222 !important;
+ margin: 0 5px !important;
+ padding: 0 !important;
+ display: inline-block !important;
+ *display: inline;
+ zoom: 1;
+ height: 32px !important;
+ width: 32px !important;
+ line-height: 32px !important;
+ text-align: center !important;
+ -khtml-border-radius: 10em !important;
+ -webkit-border-radius: 10em !important;
+ -moz-border-radius: 10em !important;
+ border-radius: 10em !important;
+ -webkit-transition: 300ms border-color ease-out;
+ -moz-transition: 300ms border-color ease-out;
+ -o-transition: 300ms border-color ease-out;
+ transition: 300ms border-color ease-out;
+}
+
+@media only screen and (-webkit-min-device-pixel-ratio: 1.5) {
+ body div div.slideshow-controls a,
+ body div div.slideshow-controls a:hover {
+ background-image: url('../../img/slideshow-controls-2x.png') !important;
+ }
+}
+
+body div div.slideshow-controls a:hover {
+ border-color: rgba(255,255,255,1) !important;
+}
+
+body div div.slideshow-controls a:first-child { background-position: -76px 8px !important;}
+body div div.slideshow-controls a:last-child { background-position: -117px 8px !important;}
+body div div.slideshow-controls a:nth-child(2) { background-position: -34px 8px !important;}
+body div div.slideshow-controls a.running { background-position: -34px 8px !important;}
+body div div.slideshow-controls a.paused { background-position: 9px 8px !important;}
+
+.slideshow-controls a img {
+ border: 50px dotted fuchsia;
+}
diff --git a/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css b/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css
new file mode 100644
index 00000000..e6d05b23
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css
@@ -0,0 +1,129 @@
+.slideshow-window {
+ background-color: #222;
+ border: 20px solid #222;
+ border-radius: 11px;
+ -moz-border-radius: 11px;
+ -webkit-border-radius: 11px;
+ -khtml-border-radius: 11px;
+ margin-bottom: 20px;
+}
+
+.slideshow-window, .slideshow-window * {
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ box-sizing: content-box;
+}
+
+.slideshow-loading {
+ height: 100%;
+ text-align: center;
+ margin: auto;
+}
+
+body div.slideshow-window * img {
+ /* Override any styles that might be present in the page stylesheet */
+ border-width: 0 !important;
+ padding: 0 !important;
+ background-color: transparent !important;
+ background-image: none !important;
+ max-width: 100%;
+}
+
+.slideshow-loading img {
+ vertical-align: middle;
+}
+
+.slideshow-slide {
+ height: 100%;
+ width: 100%;
+ text-align: center;
+ margin: auto;
+ display: none;
+}
+
+.slideshow-slide img {
+ vertical-align: middle;
+}
+
+.slideshow-line-height-hack {
+ overflow: hide;
+ width: 0px;
+ font-size: 0px;
+}
+
+.slideshow-slide-caption {
+ font-size: 13px;
+ font-family: "Helvetica Neue", sans-serif;
+ color: #f7f7f7;
+ text-shadow: #222 1px 1px 2px;
+ line-height: 25px;
+ height: 25px;
+ position: absolute;
+ bottom: 5px;
+ left: 0;
+ z-index: 100;
+ width: 100%;
+ text-align: center;
+}
+
+/* @noflip */
+.slideshow-controls {
+ z-index: 1000;
+ position: absolute;
+ bottom: 30px;
+ margin: auto;
+ text-align: center;
+ width: 100%;
+ display: none;
+ direction:ltr;
+}
+
+body div div.slideshow-controls a,
+body div div.slideshow-controls a:hover {
+ border:2px solid rgba(255,255,255,0.1) !important;
+ background-color: #000 !important;
+ background-color: rgba(0,0,0,0.6) !important;
+ background-image: url('../img/slideshow-controls.png') !important;
+ background-repeat: no-repeat;
+ background-size: 142px 16px !important;
+ background-position: -34px 8px !important;
+ color: #222 !important;
+ margin: 0 5px !important;
+ padding: 0 !important;
+ display: inline-block !important;
+ *display: inline;
+ zoom: 1;
+ height: 32px !important;
+ width: 32px !important;
+ line-height: 32px !important;
+ text-align: center !important;
+ -khtml-border-radius: 10em !important;
+ -webkit-border-radius: 10em !important;
+ -moz-border-radius: 10em !important;
+ border-radius: 10em !important;
+ -webkit-transition: 300ms border-color ease-out;
+ -moz-transition: 300ms border-color ease-out;
+ -o-transition: 300ms border-color ease-out;
+ transition: 300ms border-color ease-out;
+}
+
+@media only screen and (-webkit-min-device-pixel-ratio: 1.5) {
+ body div div.slideshow-controls a,
+ body div div.slideshow-controls a:hover {
+ background-image: url('../img/slideshow-controls-2x.png') !important;
+ }
+}
+
+body div div.slideshow-controls a:hover {
+ border-color: rgba(255,255,255,1) !important;
+}
+
+body div div.slideshow-controls a:first-child { background-position: -76px 8px !important;}
+body div div.slideshow-controls a:last-child { background-position: -117px 8px !important;}
+body div div.slideshow-controls a:nth-child(2) { background-position: -34px 8px !important;}
+body div div.slideshow-controls a.running { background-position: -34px 8px !important;}
+body div div.slideshow-controls a.paused { background-position: 9px 8px !important;}
+
+.slideshow-controls a img {
+ border: 50px dotted fuchsia;
+}
diff --git a/plugins/jetpack/modules/shortcodes/googlemaps.php b/plugins/jetpack/modules/shortcodes/googlemaps.php
index 8ced50ea..fe79a9e6 100644
--- a/plugins/jetpack/modules/shortcodes/googlemaps.php
+++ b/plugins/jetpack/modules/shortcodes/googlemaps.php
@@ -77,7 +77,7 @@ function jetpack_googlemaps_shortcode( $atts ) {
$url = substr( $url, 0, -5 );
$link_url = preg_replace( '!output=embed!', 'source=embed', $url );
- return '<iframe width="' . $width . '" height="' . $height . '" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="' . $url . '"></iframe><br /><small><a href="' . $link_url . '" style="text-align:left">View Larger Map</a></small>';
+ return '<div class="googlemaps"><iframe width="' . $width . '" height="' . $height . '" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="' . $url . '"></iframe><br /><small><a href="' . $link_url . '" style="text-align:left">View Larger Map</a></small></div>';
}
}
add_shortcode( 'googlemaps', 'jetpack_googlemaps_shortcode' );
diff --git a/plugins/jetpack/modules/shortcodes/img/slideshow-controls-2x.png b/plugins/jetpack/modules/shortcodes/img/slideshow-controls-2x.png
new file mode 100644
index 00000000..2c76ac05
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/img/slideshow-controls-2x.png
Binary files differ
diff --git a/plugins/jetpack/modules/shortcodes/img/slideshow-controls.png b/plugins/jetpack/modules/shortcodes/img/slideshow-controls.png
new file mode 100644
index 00000000..09ca4871
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/img/slideshow-controls.png
Binary files differ
diff --git a/plugins/jetpack/modules/shortcodes/img/slideshow-loader.gif b/plugins/jetpack/modules/shortcodes/img/slideshow-loader.gif
new file mode 100644
index 00000000..ce1c594e
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/img/slideshow-loader.gif
Binary files differ
diff --git a/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js b/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js
new file mode 100644
index 00000000..7697258e
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js
@@ -0,0 +1,154 @@
+(function($) {
+
+window.audioshortcode = {
+
+ /**
+ * Prep the audio player once the page is ready, add listeners, etc
+ */
+ prep: function( player_id, files, titles, volume, loop ) {
+ // check if the player has already been prepped, no-op if it has
+ var container = $( '#wp-as-' + player_id + '-container' );
+ if ( container.hasClass( 'wp-as-prepped' ) ) {
+ return;
+ }
+ container.addClass( 'wp-as-prepped' );
+
+ // browser doesn't support HTML5 audio, no-op
+ if ( ! document.createElement('audio').canPlayType ) {
+ return;
+ }
+
+ // if the browser removed the script, no-op
+ player = $( '#wp-as-' + player_id ).get(0);
+ if ( typeof player === 'undefined' ) {
+ return;
+ }
+
+ this[player_id] = [];
+ this[player_id].i = 0;
+ this[player_id].files = files;
+ this[player_id].titles = titles;
+ player.volume = volume;
+
+ var type_map = {
+ 'mp3': 'mpeg',
+ 'wav': 'wav',
+ 'ogg': 'ogg',
+ 'oga': 'ogg',
+ 'm4a': 'mp4',
+ 'aac': 'mp4',
+ 'webm': 'webm'
+ };
+
+ // strip out all the files that can't be played
+ for ( var i = this[player_id].files.length-1; i >= 0; i-- ) {
+ var extension = this[player_id].files[i].split( '.' ).pop();
+ var type = 'audio/' + type_map[extension];
+ if ( ! player.canPlayType( type ) ) {
+ this.remove_track( player_id, i );
+ }
+ }
+
+ // bail if there are no more good files
+ if ( 0 == this[player_id].files.length ) {
+ return;
+ }
+ player.src = this[player_id].files[0];
+
+ // show the controls if there are still 2+ files remaining
+ if ( 1 < this[player_id].files.length ) {
+ $( '#wp-as-' + player_id + '-controls' ).show();
+ }
+
+ player.addEventListener( 'error', function() {
+ audioshortcode.remove_track( player_id, audioshortcode[player_id].i );
+ if ( 0 < audioshortcode[player_id].files.length ) {
+ audioshortcode[player_id].i--;
+ audioshortcode.next_track( player_id, false, loop );
+ }
+ }, false );
+
+ player.addEventListener( 'ended', function() {
+ audioshortcode.next_track( player_id, false, loop );
+ }, false );
+
+ player.addEventListener( 'play', function() {
+ var i = audioshortcode[player_id].i;
+ var titles = audioshortcode[player_id].titles;
+ $( '#wp-as-' + player_id + '-playing' ).text( ' ' + titles[i] );
+ }, false );
+
+ player.addEventListener( 'pause', function() {
+ $( '#wp-as-' + player_id + '-playing' ).text( '' );
+ }, false );
+ },
+
+ /**
+ * Remove the track and update the player/controls if needed
+ */
+ remove_track: function( player_id, index ) {
+ this[player_id].files.splice( index, 1 );
+ this[player_id].titles.splice( index, 1 );
+
+ // get rid of player/controls if they can't be played
+ if ( 0 == this[player_id].files.length ) {
+ $( '#wp-as-' + player_id + '-container' ).html( $( '#wp-as-' + player_id + '-nope' ).html() );
+ $( '#wp-as-' + player_id + '-controls' ).html( '' );
+ } else if ( 1 == this[player_id].files.length ) {
+ $( '#wp-as-' + player_id + '-controls' ).html( '' );
+ }
+ },
+
+ /**
+ * Change the src of the player, load the file, then play it
+ */
+ start_track: function( player_id, file ) {
+ var player = $( '#wp-as-' + player_id ).get(0);
+ player.src = file;
+ player.load();
+ player.play();
+ },
+
+ /**
+ * Play the previous track
+ */
+ prev_track: function( player_id ) {
+ var player = $( '#wp-as-' + player_id ).get(0);
+ var files = this[player_id].files;
+ if ( player.paused || 0 == this[player_id].i ) {
+ return
+ };
+
+ player.pause();
+ if ( 0 < this[player_id].i ) {
+ this[player_id].i--;
+ this.start_track( player_id, files[this[player_id].i] );
+ }
+ },
+
+ /**
+ * Play the next track
+ */
+ next_track: function( player_id, fromClick, loop ) {
+ var player = $( '#wp-as-' + player_id ).get(0);
+ var files = this[player_id].files;
+ if ( fromClick && ( player.paused || files.length-1 == this[player_id].i ) ) {
+ return;
+ }
+
+ player.pause();
+ if ( files.length-1 > this[player_id].i ) {
+ this[player_id].i++;
+ this.start_track( player_id, files[this[player_id].i] );
+ } else if ( loop ) {
+ this[player_id].i = 0;
+ this.start_track( player_id, 0 );
+ } else {
+ this[player_id].i = 0;
+ player.src = files[0];
+ $( '#wp-as-' + player_id + '-playing' ).text( '' );
+ }
+ }
+};
+
+})(jQuery);
diff --git a/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js b/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js
new file mode 100644
index 00000000..89d583eb
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js
@@ -0,0 +1,1551 @@
+/*!
+ * jQuery Cycle Plugin (with Transition Definitions)
+ * Examples and documentation at: http://jquery.malsup.com/cycle/
+ * Copyright (c) 2007-2010 M. Alsup
+ * Version: 2.9999.8 (26-OCT-2012)
+ * Dual licensed under the MIT and GPL licenses.
+ * http://jquery.malsup.com/license.html
+ * Requires: jQuery v1.3.2 or later
+ */
+;(function($, undefined) {
+"use strict";
+
+var ver = '2.9999.8';
+
+// if $.support is not defined (pre jQuery 1.3) add what I need
+if ($.support === undefined) {
+ $.support = {
+ opacity: !($.browser.msie)
+ };
+}
+
+function debug(s) {
+ if ($.fn.cycle.debug)
+ log(s);
+}
+function log() {
+ if (window.console && console.log)
+ console.log('[cycle] ' + Array.prototype.join.call(arguments,' '));
+}
+$.expr[':'].paused = function(el) {
+ return el.cyclePause;
+};
+
+
+// the options arg can be...
+// a number - indicates an immediate transition should occur to the given slide index
+// a string - 'pause', 'resume', 'toggle', 'next', 'prev', 'stop', 'destroy' or the name of a transition effect (ie, 'fade', 'zoom', etc)
+// an object - properties to control the slideshow
+//
+// the arg2 arg can be...
+// the name of an fx (only used in conjunction with a numeric value for 'options')
+// the value true (only used in first arg == 'resume') and indicates
+// that the resume should occur immediately (not wait for next timeout)
+
+$.fn.cycle = function(options, arg2) {
+ var o = { s: this.selector, c: this.context };
+
+ // in 1.3+ we can fix mistakes with the ready state
+ if (this.length === 0 && options != 'stop') {
+ if (!$.isReady && o.s) {
+ log('DOM not ready, queuing slideshow');
+ $(function() {
+ $(o.s,o.c).cycle(options,arg2);
+ });
+ return this;
+ }
+ // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+ log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+ return this;
+ }
+
+ // iterate the matched nodeset
+ return this.each(function() {
+ var opts = handleArguments(this, options, arg2);
+ if (opts === false)
+ return;
+
+ opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink;
+
+ // stop existing slideshow for this container (if there is one)
+ if (this.cycleTimeout)
+ clearTimeout(this.cycleTimeout);
+ this.cycleTimeout = this.cyclePause = 0;
+ this.cycleStop = 0; // issue #108
+
+ var $cont = $(this);
+ var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children();
+ var els = $slides.get();
+
+ if (els.length < 2) {
+ log('terminating; too few slides: ' + els.length);
+ return;
+ }
+
+ var opts2 = buildOptions($cont, $slides, els, opts, o);
+ if (opts2 === false)
+ return;
+
+ var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.backwards);
+
+ // if it's an auto slideshow, kick it off
+ if (startTime) {
+ startTime += (opts2.delay || 0);
+ if (startTime < 10)
+ startTime = 10;
+ debug('first timeout: ' + startTime);
+ this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts.backwards);}, startTime);
+ }
+ });
+};
+
+function triggerPause(cont, byHover, onPager) {
+ var opts = $(cont).data('cycle.opts');
+ if (!opts)
+ return;
+ var paused = !!cont.cyclePause;
+ if (paused && opts.paused)
+ opts.paused(cont, opts, byHover, onPager);
+ else if (!paused && opts.resumed)
+ opts.resumed(cont, opts, byHover, onPager);
+}
+
+// process the args that were passed to the plugin fn
+function handleArguments(cont, options, arg2) {
+ if (cont.cycleStop === undefined)
+ cont.cycleStop = 0;
+ if (options === undefined || options === null)
+ options = {};
+ if (options.constructor == String) {
+ switch(options) {
+ case 'destroy':
+ case 'stop':
+ var opts = $(cont).data('cycle.opts');
+ if (!opts)
+ return false;
+ cont.cycleStop++; // callbacks look for change
+ if (cont.cycleTimeout)
+ clearTimeout(cont.cycleTimeout);
+ cont.cycleTimeout = 0;
+ if (opts.elements)
+ $(opts.elements).stop();
+ $(cont).removeData('cycle.opts');
+ if (options == 'destroy')
+ destroy(cont, opts);
+ return false;
+ case 'toggle':
+ cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1;
+ checkInstantResume(cont.cyclePause, arg2, cont);
+ triggerPause(cont);
+ return false;
+ case 'pause':
+ cont.cyclePause = 1;
+ triggerPause(cont);
+ return false;
+ case 'resume':
+ cont.cyclePause = 0;
+ checkInstantResume(false, arg2, cont);
+ triggerPause(cont);
+ return false;
+ case 'prev':
+ case 'next':
+ opts = $(cont).data('cycle.opts');
+ if (!opts) {
+ log('options not found, "prev/next" ignored');
+ return false;
+ }
+ $.fn.cycle[options](opts);
+ return false;
+ default:
+ options = { fx: options };
+ }
+ return options;
+ }
+ else if (options.constructor == Number) {
+ // go to the requested slide
+ var num = options;
+ options = $(cont).data('cycle.opts');
+ if (!options) {
+ log('options not found, can not advance slide');
+ return false;
+ }
+ if (num < 0 || num >= options.elements.length) {
+ log('invalid slide index: ' + num);
+ return false;
+ }
+ options.nextSlide = num;
+ if (cont.cycleTimeout) {
+ clearTimeout(cont.cycleTimeout);
+ cont.cycleTimeout = 0;
+ }
+ if (typeof arg2 == 'string')
+ options.oneTimeFx = arg2;
+ go(options.elements, options, 1, num >= options.currSlide);
+ return false;
+ }
+ return options;
+
+ function checkInstantResume(isPaused, arg2, cont) {
+ if (!isPaused && arg2 === true) { // resume now!
+ var options = $(cont).data('cycle.opts');
+ if (!options) {
+ log('options not found, can not resume');
+ return false;
+ }
+ if (cont.cycleTimeout) {
+ clearTimeout(cont.cycleTimeout);
+ cont.cycleTimeout = 0;
+ }
+ go(options.elements, options, 1, !options.backwards);
+ }
+ }
+}
+
+function removeFilter(el, opts) {
+ if (!$.support.opacity && opts.cleartype && el.style.filter) {
+ try { el.style.removeAttribute('filter'); }
+ catch(smother) {} // handle old opera versions
+ }
+}
+
+// unbind event handlers
+function destroy(cont, opts) {
+ if (opts.next)
+ $(opts.next).unbind(opts.prevNextEvent);
+ if (opts.prev)
+ $(opts.prev).unbind(opts.prevNextEvent);
+
+ if (opts.pager || opts.pagerAnchorBuilder)
+ $.each(opts.pagerAnchors || [], function() {
+ this.unbind().remove();
+ });
+ opts.pagerAnchors = null;
+ $(cont).unbind('mouseenter.cycle mouseleave.cycle');
+ if (opts.destroy) // callback
+ opts.destroy(opts);
+}
+
+// one-time initialization
+function buildOptions($cont, $slides, els, options, o) {
+ var startingSlideSpecified;
+ // support metadata plugin (v1.0 and v2.0)
+ var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});
+ var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null;
+ if (meta)
+ opts = $.extend(opts, meta);
+ if (opts.autostop)
+ opts.countdown = opts.autostopCount || els.length;
+
+ var cont = $cont[0];
+ $cont.data('cycle.opts', opts);
+ opts.$cont = $cont;
+ opts.stopCount = cont.cycleStop;
+ opts.elements = els;
+ opts.before = opts.before ? [opts.before] : [];
+ opts.after = opts.after ? [opts.after] : [];
+
+ // push some after callbacks
+ if (!$.support.opacity && opts.cleartype)
+ opts.after.push(function() { removeFilter(this, opts); });
+ if (opts.continuous)
+ opts.after.push(function() { go(els,opts,0,!opts.backwards); });
+
+ saveOriginalOpts(opts);
+
+ // clearType corrections
+ if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
+ clearTypeFix($slides);
+
+ // container requires non-static position so that slides can be position within
+ if ($cont.css('position') == 'static')
+ $cont.css('position', 'relative');
+ if (opts.width)
+ $cont.width(opts.width);
+ if (opts.height && opts.height != 'auto')
+ $cont.height(opts.height);
+
+ if (opts.startingSlide !== undefined) {
+ opts.startingSlide = parseInt(opts.startingSlide,10);
+ if (opts.startingSlide >= els.length || opts.startSlide < 0)
+ opts.startingSlide = 0; // catch bogus input
+ else
+ startingSlideSpecified = true;
+ }
+ else if (opts.backwards)
+ opts.startingSlide = els.length - 1;
+ else
+ opts.startingSlide = 0;
+
+ // if random, mix up the slide array
+ if (opts.random) {
+ opts.randomMap = [];
+ for (var i = 0; i < els.length; i++)
+ opts.randomMap.push(i);
+ opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+ if (startingSlideSpecified) {
+ // try to find the specified starting slide and if found set start slide index in the map accordingly
+ for ( var cnt = 0; cnt < els.length; cnt++ ) {
+ if ( opts.startingSlide == opts.randomMap[cnt] ) {
+ opts.randomIndex = cnt;
+ }
+ }
+ }
+ else {
+ opts.randomIndex = 1;
+ opts.startingSlide = opts.randomMap[1];
+ }
+ }
+ else if (opts.startingSlide >= els.length)
+ opts.startingSlide = 0; // catch bogus input
+ opts.currSlide = opts.startingSlide || 0;
+ var first = opts.startingSlide;
+
+ // set position and zIndex on all the slides
+ $slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) {
+ var z;
+ if (opts.backwards)
+ z = first ? i <= first ? els.length + (i-first) : first-i : els.length-i;
+ else
+ z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i;
+ $(this).css('z-index', z);
+ });
+
+ // make sure first slide is visible
+ $(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case
+ removeFilter(els[first], opts);
+
+ // stretch slides
+ if (opts.fit) {
+ if (!opts.aspect) {
+ if (opts.width)
+ $slides.width(opts.width);
+ if (opts.height && opts.height != 'auto')
+ $slides.height(opts.height);
+ } else {
+ $slides.each(function(){
+ var $slide = $(this);
+ var ratio = (opts.aspect === true) ? $slide.width()/$slide.height() : opts.aspect;
+ if( opts.width && $slide.width() != opts.width ) {
+ $slide.width( opts.width );
+ $slide.height( opts.width / ratio );
+ }
+
+ if( opts.height && $slide.height() < opts.height ) {
+ $slide.height( opts.height );
+ $slide.width( opts.height * ratio );
+ }
+ });
+ }
+ }
+
+ if (opts.center && ((!opts.fit) || opts.aspect)) {
+ $slides.each(function(){
+ var $slide = $(this);
+ $slide.css({
+ "margin-left": opts.width ?
+ ((opts.width - $slide.width()) / 2) + "px" :
+ 0,
+ "margin-top": opts.height ?
+ ((opts.height - $slide.height()) / 2) + "px" :
+ 0
+ });
+ });
+ }
+
+ if (opts.center && !opts.fit && !opts.slideResize) {
+ $slides.each(function(){
+ var $slide = $(this);
+ $slide.css({
+ "margin-left": opts.width ? ((opts.width - $slide.width()) / 2) + "px" : 0,
+ "margin-top": opts.height ? ((opts.height - $slide.height()) / 2) + "px" : 0
+ });
+ });
+ }
+
+ // stretch container
+ var reshape = (opts.containerResize || opts.containerResizeHeight) && !$cont.innerHeight();
+ if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9
+ var maxw = 0, maxh = 0;
+ for(var j=0; j < els.length; j++) {
+ var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight();
+ if (!w) w = e.offsetWidth || e.width || $e.attr('width');
+ if (!h) h = e.offsetHeight || e.height || $e.attr('height');
+ maxw = w > maxw ? w : maxw;
+ maxh = h > maxh ? h : maxh;
+ }
+ if (opts.containerResize && maxw > 0 && maxh > 0)
+ $cont.css({width:maxw+'px',height:maxh+'px'});
+ if (opts.containerResizeHeight && maxh > 0)
+ $cont.css({height:maxh+'px'});
+ }
+
+ var pauseFlag = false; // https://github.com/malsup/cycle/issues/44
+ if (opts.pause)
+ $cont.bind('mouseenter.cycle', function(){
+ pauseFlag = true;
+ this.cyclePause++;
+ triggerPause(cont, true);
+ }).bind('mouseleave.cycle', function(){
+ if (pauseFlag)
+ this.cyclePause--;
+ triggerPause(cont, true);
+ });
+
+ if (supportMultiTransitions(opts) === false)
+ return false;
+
+ // apparently a lot of people use image slideshows without height/width attributes on the images.
+ // Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that.
+ var requeue = false;
+ options.requeueAttempts = options.requeueAttempts || 0;
+ $slides.each(function() {
+ // try to get height/width of each slide
+ var $el = $(this);
+ this.cycleH = (opts.fit && opts.height) ? opts.height : ($el.height() || this.offsetHeight || this.height || $el.attr('height') || 0);
+ this.cycleW = (opts.fit && opts.width) ? opts.width : ($el.width() || this.offsetWidth || this.width || $el.attr('width') || 0);
+
+ if ( $el.is('img') ) {
+ // sigh.. sniffing, hacking, shrugging... this crappy hack tries to account for what browsers do when
+ // an image is being downloaded and the markup did not include sizing info (height/width attributes);
+ // there seems to be some "default" sizes used in this situation
+ var loadingIE = ($.browser.msie && this.cycleW == 28 && this.cycleH == 30 && !this.complete);
+ var loadingFF = ($.browser.mozilla && this.cycleW == 34 && this.cycleH == 19 && !this.complete);
+ var loadingOp = ($.browser.opera && ((this.cycleW == 42 && this.cycleH == 19) || (this.cycleW == 37 && this.cycleH == 17)) && !this.complete);
+ var loadingOther = (this.cycleH === 0 && this.cycleW === 0 && !this.complete);
+ // don't requeue for images that are still loading but have a valid size
+ if (loadingIE || loadingFF || loadingOp || loadingOther) {
+ if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever
+ log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH);
+ setTimeout(function() {$(o.s,o.c).cycle(options);}, opts.requeueTimeout);
+ requeue = true;
+ return false; // break each loop
+ }
+ else {
+ log('could not determine size of image: '+this.src, this.cycleW, this.cycleH);
+ }
+ }
+ }
+ return true;
+ });
+
+ if (requeue)
+ return false;
+
+ opts.cssBefore = opts.cssBefore || {};
+ opts.cssAfter = opts.cssAfter || {};
+ opts.cssFirst = opts.cssFirst || {};
+ opts.animIn = opts.animIn || {};
+ opts.animOut = opts.animOut || {};
+
+ $slides.not(':eq('+first+')').css(opts.cssBefore);
+ $($slides[first]).css(opts.cssFirst);
+
+ if (opts.timeout) {
+ opts.timeout = parseInt(opts.timeout,10);
+ // ensure that timeout and speed settings are sane
+ if (opts.speed.constructor == String)
+ opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed,10);
+ if (!opts.sync)
+ opts.speed = opts.speed / 2;
+
+ var buffer = opts.fx == 'none' ? 0 : opts.fx == 'shuffle' ? 500 : 250;
+ while((opts.timeout - opts.speed) < buffer) // sanitize timeout
+ opts.timeout += opts.speed;
+ }
+ if (opts.easing)
+ opts.easeIn = opts.easeOut = opts.easing;
+ if (!opts.speedIn)
+ opts.speedIn = opts.speed;
+ if (!opts.speedOut)
+ opts.speedOut = opts.speed;
+
+ opts.slideCount = els.length;
+ opts.currSlide = opts.lastSlide = first;
+ if (opts.random) {
+ if (++opts.randomIndex == els.length)
+ opts.randomIndex = 0;
+ opts.nextSlide = opts.randomMap[opts.randomIndex];
+ }
+ else if (opts.backwards)
+ opts.nextSlide = opts.startingSlide === 0 ? (els.length-1) : opts.startingSlide-1;
+ else
+ opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1;
+
+ // run transition init fn
+ if (!opts.multiFx) {
+ var init = $.fn.cycle.transitions[opts.fx];
+ if ($.isFunction(init))
+ init($cont, $slides, opts);
+ else if (opts.fx != 'custom' && !opts.multiFx) {
+ log('unknown transition: ' + opts.fx,'; slideshow terminating');
+ return false;
+ }
+ }
+
+ // fire artificial events
+ var e0 = $slides[first];
+ if (!opts.skipInitializationCallbacks) {
+ if (opts.before.length)
+ opts.before[0].apply(e0, [e0, e0, opts, true]);
+ if (opts.after.length)
+ opts.after[0].apply(e0, [e0, e0, opts, true]);
+ }
+ if (opts.next)
+ $(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,1);});
+ if (opts.prev)
+ $(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,0);});
+ if (opts.pager || opts.pagerAnchorBuilder)
+ buildPager(els,opts);
+
+ exposeAddSlide(opts, els);
+
+ return opts;
+}
+
+// save off original opts so we can restore after clearing state
+function saveOriginalOpts(opts) {
+ opts.original = { before: [], after: [] };
+ opts.original.cssBefore = $.extend({}, opts.cssBefore);
+ opts.original.cssAfter = $.extend({}, opts.cssAfter);
+ opts.original.animIn = $.extend({}, opts.animIn);
+ opts.original.animOut = $.extend({}, opts.animOut);
+ $.each(opts.before, function() { opts.original.before.push(this); });
+ $.each(opts.after, function() { opts.original.after.push(this); });
+}
+
+function supportMultiTransitions(opts) {
+ var i, tx, txs = $.fn.cycle.transitions;
+ // look for multiple effects
+ if (opts.fx.indexOf(',') > 0) {
+ opts.multiFx = true;
+ opts.fxs = opts.fx.replace(/\s*/g,'').split(',');
+ // discard any bogus effect names
+ for (i=0; i < opts.fxs.length; i++) {
+ var fx = opts.fxs[i];
+ tx = txs[fx];
+ if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) {
+ log('discarding unknown transition: ',fx);
+ opts.fxs.splice(i,1);
+ i--;
+ }
+ }
+ // if we have an empty list then we threw everything away!
+ if (!opts.fxs.length) {
+ log('No valid transitions named; slideshow terminating.');
+ return false;
+ }
+ }
+ else if (opts.fx == 'all') { // auto-gen the list of transitions
+ opts.multiFx = true;
+ opts.fxs = [];
+ for (var p in txs) {
+ if (txs.hasOwnProperty(p)) {
+ tx = txs[p];
+ if (txs.hasOwnProperty(p) && $.isFunction(tx))
+ opts.fxs.push(p);
+ }
+ }
+ }
+ if (opts.multiFx && opts.randomizeEffects) {
+ // munge the fxs array to make effect selection random
+ var r1 = Math.floor(Math.random() * 20) + 30;
+ for (i = 0; i < r1; i++) {
+ var r2 = Math.floor(Math.random() * opts.fxs.length);
+ opts.fxs.push(opts.fxs.splice(r2,1)[0]);
+ }
+ debug('randomized fx sequence: ',opts.fxs);
+ }
+ return true;
+}
+
+// provide a mechanism for adding slides after the slideshow has started
+function exposeAddSlide(opts, els) {
+ opts.addSlide = function(newSlide, prepend) {
+ var $s = $(newSlide), s = $s[0];
+ if (!opts.autostopCount)
+ opts.countdown++;
+ els[prepend?'unshift':'push'](s);
+ if (opts.els)
+ opts.els[prepend?'unshift':'push'](s); // shuffle needs this
+ opts.slideCount = els.length;
+
+ // add the slide to the random map and resort
+ if (opts.random) {
+ opts.randomMap.push(opts.slideCount-1);
+ opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+ }
+
+ $s.css('position','absolute');
+ $s[prepend?'prependTo':'appendTo'](opts.$cont);
+
+ if (prepend) {
+ opts.currSlide++;
+ opts.nextSlide++;
+ }
+
+ if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg)
+ clearTypeFix($s);
+
+ if (opts.fit && opts.width)
+ $s.width(opts.width);
+ if (opts.fit && opts.height && opts.height != 'auto')
+ $s.height(opts.height);
+ s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height();
+ s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width();
+
+ $s.css(opts.cssBefore);
+
+ if (opts.pager || opts.pagerAnchorBuilder)
+ $.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts);
+
+ if ($.isFunction(opts.onAddSlide))
+ opts.onAddSlide($s);
+ else
+ $s.hide(); // default behavior
+ };
+}
+
+// reset internal state; we do this on every pass in order to support multiple effects
+$.fn.cycle.resetState = function(opts, fx) {
+ fx = fx || opts.fx;
+ opts.before = []; opts.after = [];
+ opts.cssBefore = $.extend({}, opts.original.cssBefore);
+ opts.cssAfter = $.extend({}, opts.original.cssAfter);
+ opts.animIn = $.extend({}, opts.original.animIn);
+ opts.animOut = $.extend({}, opts.original.animOut);
+ opts.fxFn = null;
+ $.each(opts.original.before, function() { opts.before.push(this); });
+ $.each(opts.original.after, function() { opts.after.push(this); });
+
+ // re-init
+ var init = $.fn.cycle.transitions[fx];
+ if ($.isFunction(init))
+ init(opts.$cont, $(opts.elements), opts);
+};
+
+// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt
+function go(els, opts, manual, fwd) {
+ var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide];
+
+ // opts.busy is true if we're in the middle of an animation
+ if (manual && opts.busy && opts.manualTrump) {
+ // let manual transitions requests trump active ones
+ debug('manualTrump in go(), stopping active transition');
+ $(els).stop(true,true);
+ opts.busy = 0;
+ clearTimeout(p.cycleTimeout);
+ }
+
+ // don't begin another timeout-based transition if there is one active
+ if (opts.busy) {
+ debug('transition active, ignoring new tx request');
+ return;
+ }
+
+
+ // stop cycling if we have an outstanding stop request
+ if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual)
+ return;
+
+ // check to see if we should stop cycling based on autostop options
+ if (!manual && !p.cyclePause && !opts.bounce &&
+ ((opts.autostop && (--opts.countdown <= 0)) ||
+ (opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) {
+ if (opts.end)
+ opts.end(opts);
+ return;
+ }
+
+ // if slideshow is paused, only transition on a manual trigger
+ var changed = false;
+ if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) {
+ changed = true;
+ var fx = opts.fx;
+ // keep trying to get the slide size if we don't have it yet
+ curr.cycleH = curr.cycleH || $(curr).height();
+ curr.cycleW = curr.cycleW || $(curr).width();
+ next.cycleH = next.cycleH || $(next).height();
+ next.cycleW = next.cycleW || $(next).width();
+
+ // support multiple transition types
+ if (opts.multiFx) {
+ if (fwd && (opts.lastFx === undefined || ++opts.lastFx >= opts.fxs.length))
+ opts.lastFx = 0;
+ else if (!fwd && (opts.lastFx === undefined || --opts.lastFx < 0))
+ opts.lastFx = opts.fxs.length - 1;
+ fx = opts.fxs[opts.lastFx];
+ }
+
+ // one-time fx overrides apply to: $('div').cycle(3,'zoom');
+ if (opts.oneTimeFx) {
+ fx = opts.oneTimeFx;
+ opts.oneTimeFx = null;
+ }
+
+ $.fn.cycle.resetState(opts, fx);
+
+ // run the before callbacks
+ if (opts.before.length)
+ $.each(opts.before, function(i,o) {
+ if (p.cycleStop != opts.stopCount) return;
+ o.apply(next, [curr, next, opts, fwd]);
+ });
+
+ // stage the after callacks
+ var after = function() {
+ opts.busy = 0;
+ $.each(opts.after, function(i,o) {
+ if (p.cycleStop != opts.stopCount) return;
+ o.apply(next, [curr, next, opts, fwd]);
+ });
+ if (!p.cycleStop) {
+ // queue next transition
+ queueNext();
+ }
+ };
+
+ debug('tx firing('+fx+'); currSlide: ' + opts.currSlide + '; nextSlide: ' + opts.nextSlide);
+
+ // get ready to perform the transition
+ opts.busy = 1;
+ if (opts.fxFn) // fx function provided?
+ opts.fxFn(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+ else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ?
+ $.fn.cycle[opts.fx](curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+ else
+ $.fn.cycle.custom(curr, next, opts, after, fwd, manual && opts.fastOnEvent);
+ }
+ else {
+ queueNext();
+ }
+
+ if (changed || opts.nextSlide == opts.currSlide) {
+ // calculate the next slide
+ var roll;
+ opts.lastSlide = opts.currSlide;
+ if (opts.random) {
+ opts.currSlide = opts.nextSlide;
+ if (++opts.randomIndex == els.length) {
+ opts.randomIndex = 0;
+ opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;});
+ }
+ opts.nextSlide = opts.randomMap[opts.randomIndex];
+ if (opts.nextSlide == opts.currSlide)
+ opts.nextSlide = (opts.currSlide == opts.slideCount - 1) ? 0 : opts.currSlide + 1;
+ }
+ else if (opts.backwards) {
+ roll = (opts.nextSlide - 1) < 0;
+ if (roll && opts.bounce) {
+ opts.backwards = !opts.backwards;
+ opts.nextSlide = 1;
+ opts.currSlide = 0;
+ }
+ else {
+ opts.nextSlide = roll ? (els.length-1) : opts.nextSlide-1;
+ opts.currSlide = roll ? 0 : opts.nextSlide+1;
+ }
+ }
+ else { // sequence
+ roll = (opts.nextSlide + 1) == els.length;
+ if (roll && opts.bounce) {
+ opts.backwards = !opts.backwards;
+ opts.nextSlide = els.length-2;
+ opts.currSlide = els.length-1;
+ }
+ else {
+ opts.nextSlide = roll ? 0 : opts.nextSlide+1;
+ opts.currSlide = roll ? els.length-1 : opts.nextSlide-1;
+ }
+ }
+ }
+ if (changed && opts.pager)
+ opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass);
+
+ function queueNext() {
+ // stage the next transition
+ var ms = 0, timeout = opts.timeout;
+ if (opts.timeout && !opts.continuous) {
+ ms = getTimeout(els[opts.currSlide], els[opts.nextSlide], opts, fwd);
+ if (opts.fx == 'shuffle')
+ ms -= opts.speedOut;
+ }
+ else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic
+ ms = 10;
+ if (ms > 0)
+ p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.backwards); }, ms);
+ }
+}
+
+// invoked after transition
+$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) {
+ $(pager).each(function() {
+ $(this).children().removeClass(clsName).eq(currSlide).addClass(clsName);
+ });
+};
+
+// calculate timeout value for current transition
+function getTimeout(curr, next, opts, fwd) {
+ if (opts.timeoutFn) {
+ // call user provided calc fn
+ var t = opts.timeoutFn.call(curr,curr,next,opts,fwd);
+ while (opts.fx != 'none' && (t - opts.speed) < 250) // sanitize timeout
+ t += opts.speed;
+ debug('calculated timeout: ' + t + '; speed: ' + opts.speed);
+ if (t !== false)
+ return t;
+ }
+ return opts.timeout;
+}
+
+// expose next/prev function, caller must pass in state
+$.fn.cycle.next = function(opts) { advance(opts,1); };
+$.fn.cycle.prev = function(opts) { advance(opts,0);};
+
+// advance slide forward or back
+function advance(opts, moveForward) {
+ var val = moveForward ? 1 : -1;
+ var els = opts.elements;
+ var p = opts.$cont[0], timeout = p.cycleTimeout;
+ if (timeout) {
+ clearTimeout(timeout);
+ p.cycleTimeout = 0;
+ }
+ if (opts.random && val < 0) {
+ // move back to the previously display slide
+ opts.randomIndex--;
+ if (--opts.randomIndex == -2)
+ opts.randomIndex = els.length-2;
+ else if (opts.randomIndex == -1)
+ opts.randomIndex = els.length-1;
+ opts.nextSlide = opts.randomMap[opts.randomIndex];
+ }
+ else if (opts.random) {
+ opts.nextSlide = opts.randomMap[opts.randomIndex];
+ }
+ else {
+ opts.nextSlide = opts.currSlide + val;
+ if (opts.nextSlide < 0) {
+ if (opts.nowrap) return false;
+ opts.nextSlide = els.length - 1;
+ }
+ else if (opts.nextSlide >= els.length) {
+ if (opts.nowrap) return false;
+ opts.nextSlide = 0;
+ }
+ }
+
+ var cb = opts.onPrevNextEvent || opts.prevNextClick; // prevNextClick is deprecated
+ if ($.isFunction(cb))
+ cb(val > 0, opts.nextSlide, els[opts.nextSlide]);
+ go(els, opts, 1, moveForward);
+ return false;
+}
+
+function buildPager(els, opts) {
+ var $p = $(opts.pager);
+ $.each(els, function(i,o) {
+ $.fn.cycle.createPagerAnchor(i,o,$p,els,opts);
+ });
+ opts.updateActivePagerLink(opts.pager, opts.startingSlide, opts.activePagerClass);
+}
+
+$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
+ var a;
+ if ($.isFunction(opts.pagerAnchorBuilder)) {
+ a = opts.pagerAnchorBuilder(i,el);
+ debug('pagerAnchorBuilder('+i+', el) returned: ' + a);
+ }
+ else
+ a = '<a href="#">'+(i+1)+'</a>';
+
+ if (!a)
+ return;
+ var $a = $(a);
+ // don't reparent if anchor is in the dom
+ if ($a.parents('body').length === 0) {
+ var arr = [];
+ if ($p.length > 1) {
+ $p.each(function() {
+ var $clone = $a.clone(true);
+ $(this).append($clone);
+ arr.push($clone[0]);
+ });
+ $a = $(arr);
+ }
+ else {
+ $a.appendTo($p);
+ }
+ }
+
+ opts.pagerAnchors = opts.pagerAnchors || [];
+ opts.pagerAnchors.push($a);
+
+ var pagerFn = function(e) {
+ e.preventDefault();
+ opts.nextSlide = i;
+ var p = opts.$cont[0], timeout = p.cycleTimeout;
+ if (timeout) {
+ clearTimeout(timeout);
+ p.cycleTimeout = 0;
+ }
+ var cb = opts.onPagerEvent || opts.pagerClick; // pagerClick is deprecated
+ if ($.isFunction(cb))
+ cb(opts.nextSlide, els[opts.nextSlide]);
+ go(els,opts,1,opts.currSlide < i); // trigger the trans
+// return false; // <== allow bubble
+ };
+
+ if ( /mouseenter|mouseover/i.test(opts.pagerEvent) ) {
+ $a.hover(pagerFn, function(){/* no-op */} );
+ }
+ else {
+ $a.bind(opts.pagerEvent, pagerFn);
+ }
+
+ if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble)
+ $a.bind('click.cycle', function(){return false;}); // suppress click
+
+ var cont = opts.$cont[0];
+ var pauseFlag = false; // https://github.com/malsup/cycle/issues/44
+ if (opts.pauseOnPagerHover) {
+ $a.hover(
+ function() {
+ pauseFlag = true;
+ cont.cyclePause++;
+ triggerPause(cont,true,true);
+ }, function() {
+ if (pauseFlag)
+ cont.cyclePause--;
+ triggerPause(cont,true,true);
+ }
+ );
+ }
+};
+
+// helper fn to calculate the number of slides between the current and the next
+$.fn.cycle.hopsFromLast = function(opts, fwd) {
+ var hops, l = opts.lastSlide, c = opts.currSlide;
+ if (fwd)
+ hops = c > l ? c - l : opts.slideCount - l;
+ else
+ hops = c < l ? l - c : l + opts.slideCount - c;
+ return hops;
+};
+
+// fix clearType problems in ie6 by setting an explicit bg color
+// (otherwise text slides look horrible during a fade transition)
+function clearTypeFix($slides) {
+ debug('applying clearType background-color hack');
+ function hex(s) {
+ s = parseInt(s,10).toString(16);
+ return s.length < 2 ? '0'+s : s;
+ }
+ function getBg(e) {
+ for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) {
+ var v = $.css(e,'background-color');
+ if (v && v.indexOf('rgb') >= 0 ) {
+ var rgb = v.match(/\d+/g);
+ return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]);
+ }
+ if (v && v != 'transparent')
+ return v;
+ }
+ return '#ffffff';
+ }
+ $slides.each(function() { $(this).css('background-color', getBg(this)); });
+}
+
+// reset common props before the next transition
+$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) {
+ $(opts.elements).not(curr).hide();
+ if (typeof opts.cssBefore.opacity == 'undefined')
+ opts.cssBefore.opacity = 1;
+ opts.cssBefore.display = 'block';
+ if (opts.slideResize && w !== false && next.cycleW > 0)
+ opts.cssBefore.width = next.cycleW;
+ if (opts.slideResize && h !== false && next.cycleH > 0)
+ opts.cssBefore.height = next.cycleH;
+ opts.cssAfter = opts.cssAfter || {};
+ opts.cssAfter.display = 'none';
+ $(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0));
+ $(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1));
+};
+
+// the actual fn for effecting a transition
+$.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) {
+ var $l = $(curr), $n = $(next);
+ var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut;
+ $n.css(opts.cssBefore);
+ if (speedOverride) {
+ if (typeof speedOverride == 'number')
+ speedIn = speedOut = speedOverride;
+ else
+ speedIn = speedOut = 1;
+ easeIn = easeOut = null;
+ }
+ var fn = function() {
+ $n.animate(opts.animIn, speedIn, easeIn, function() {
+ cb();
+ });
+ };
+ $l.animate(opts.animOut, speedOut, easeOut, function() {
+ $l.css(opts.cssAfter);
+ if (!opts.sync)
+ fn();
+ });
+ if (opts.sync) fn();
+};
+
+// transition definitions - only fade is defined here, transition pack defines the rest
+$.fn.cycle.transitions = {
+ fade: function($cont, $slides, opts) {
+ $slides.not(':eq('+opts.currSlide+')').css('opacity',0);
+ opts.before.push(function(curr,next,opts) {
+ $.fn.cycle.commonReset(curr,next,opts);
+ opts.cssBefore.opacity = 0;
+ });
+ opts.animIn = { opacity: 1 };
+ opts.animOut = { opacity: 0 };
+ opts.cssBefore = { top: 0, left: 0 };
+ }
+};
+
+$.fn.cycle.ver = function() { return ver; };
+
+// override these globally if you like (they are all optional)
+$.fn.cycle.defaults = {
+ activePagerClass: 'activeSlide', // class name used for the active pager link
+ after: null, // transition callback (scope set to element that was shown): function(currSlideElement, nextSlideElement, options, forwardFlag)
+ allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling
+ animIn: null, // properties that define how the slide animates in
+ animOut: null, // properties that define how the slide animates out
+ aspect: false, // preserve aspect ratio during fit resizing, cropping if necessary (must be used with fit option)
+ autostop: 0, // true to end slideshow after X transitions (where X == slide count)
+ autostopCount: 0, // number of transitions (optionally used with autostop to define X)
+ backwards: false, // true to start slideshow at last slide and move backwards through the stack
+ before: null, // transition callback (scope set to element to be shown): function(currSlideElement, nextSlideElement, options, forwardFlag)
+ center: null, // set to true to have cycle add top/left margin to each slide (use with width and height options)
+ cleartype: !$.support.opacity, // true if clearType corrections should be applied (for IE)
+ cleartypeNoBg: false, // set to true to disable extra cleartype fixing (leave false to force background color setting on slides)
+ containerResize: 1, // resize container to fit largest slide
+ containerResizeHeight: 0, // resize containers height to fit the largest slide but leave the width dynamic
+ continuous: 0, // true to start next transition immediately after current one completes
+ cssAfter: null, // properties that defined the state of the slide after transitioning out
+ cssBefore: null, // properties that define the initial state of the slide before transitioning in
+ delay: 0, // additional delay (in ms) for first transition (hint: can be negative)
+ easeIn: null, // easing for "in" transition
+ easeOut: null, // easing for "out" transition
+ easing: null, // easing method for both in and out transitions
+ end: null, // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options)
+ fastOnEvent: 0, // force fast transitions when triggered manually (via pager or prev/next); value == time in ms
+ fit: 0, // force slides to fit container
+ fx: 'fade', // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle')
+ fxFn: null, // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag)
+ height: 'auto', // container height (if the 'fit' option is true, the slides will be set to this height as well)
+ manualTrump: true, // causes manual transition to stop an active transition instead of being ignored
+ metaAttr: 'cycle', // data- attribute that holds the option data for the slideshow
+ next: null, // element, jQuery object, or jQuery selector string for the element to use as event trigger for next slide
+ nowrap: 0, // true to prevent slideshow from wrapping
+ onPagerEvent: null, // callback fn for pager events: function(zeroBasedSlideIndex, slideElement)
+ onPrevNextEvent: null, // callback fn for prev/next events: function(isNext, zeroBasedSlideIndex, slideElement)
+ pager: null, // element, jQuery object, or jQuery selector string for the element to use as pager container
+ pagerAnchorBuilder: null, // callback fn for building anchor links: function(index, DOMelement)
+ pagerEvent: 'click.cycle', // name of event which drives the pager navigation
+ pause: 0, // true to enable "pause on hover"
+ pauseOnPagerHover: 0, // true to pause when hovering over pager link
+ prev: null, // element, jQuery object, or jQuery selector string for the element to use as event trigger for previous slide
+ prevNextEvent: 'click.cycle',// event which drives the manual transition to the previous or next slide
+ random: 0, // true for random, false for sequence (not applicable to shuffle fx)
+ randomizeEffects: 1, // valid when multiple effects are used; true to make the effect sequence random
+ requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded
+ requeueTimeout: 250, // ms delay for requeue
+ rev: 0, // causes animations to transition in reverse (for effects that support it such as scrollHorz/scrollVert/shuffle)
+ shuffle: null, // coords for shuffle animation, ex: { top:15, left: 200 }
+ skipInitializationCallbacks: false, // set to true to disable the first before/after callback that occurs prior to any transition
+ slideExpr: null, // expression for selecting slides (if something other than all children is required)
+ slideResize: 1, // force slide width/height to fixed size before every transition
+ speed: 1000, // speed of the transition (any valid fx speed value)
+ speedIn: null, // speed of the 'in' transition
+ speedOut: null, // speed of the 'out' transition
+ startingSlide: undefined,// zero-based index of the first slide to be displayed
+ sync: 1, // true if in/out transitions should occur simultaneously
+ timeout: 4000, // milliseconds between slide transitions (0 to disable auto advance)
+ timeoutFn: null, // callback for determining per-slide timeout value: function(currSlideElement, nextSlideElement, options, forwardFlag)
+ updateActivePagerLink: null,// callback fn invoked to update the active pager link (adds/removes activePagerClass style)
+ width: null // container width (if the 'fit' option is true, the slides will be set to this width as well)
+};
+
+})(jQuery);
+
+
+/*!
+ * jQuery Cycle Plugin Transition Definitions
+ * This script is a plugin for the jQuery Cycle Plugin
+ * Examples and documentation at: http://malsup.com/jquery/cycle/
+ * Copyright (c) 2007-2010 M. Alsup
+ * Version: 2.73
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ */
+(function($) {
+"use strict";
+
+//
+// These functions define slide initialization and properties for the named
+// transitions. To save file size feel free to remove any of these that you
+// don't need.
+//
+$.fn.cycle.transitions.none = function($cont, $slides, opts) {
+ opts.fxFn = function(curr,next,opts,after){
+ $(next).show();
+ $(curr).hide();
+ after();
+ };
+};
+
+// not a cross-fade, fadeout only fades out the top slide
+$.fn.cycle.transitions.fadeout = function($cont, $slides, opts) {
+ $slides.not(':eq('+opts.currSlide+')').css({ display: 'block', 'opacity': 1 });
+ opts.before.push(function(curr,next,opts,w,h,rev) {
+ $(curr).css('zIndex',opts.slideCount + (rev !== true ? 1 : 0));
+ $(next).css('zIndex',opts.slideCount + (rev !== true ? 0 : 1));
+ });
+ opts.animIn.opacity = 1;
+ opts.animOut.opacity = 0;
+ opts.cssBefore.opacity = 1;
+ opts.cssBefore.display = 'block';
+ opts.cssAfter.zIndex = 0;
+};
+
+// scrollUp/Down/Left/Right
+$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) {
+ $cont.css('overflow','hidden');
+ opts.before.push($.fn.cycle.commonReset);
+ var h = $cont.height();
+ opts.cssBefore.top = h;
+ opts.cssBefore.left = 0;
+ opts.cssFirst.top = 0;
+ opts.animIn.top = 0;
+ opts.animOut.top = -h;
+};
+$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) {
+ $cont.css('overflow','hidden');
+ opts.before.push($.fn.cycle.commonReset);
+ var h = $cont.height();
+ opts.cssFirst.top = 0;
+ opts.cssBefore.top = -h;
+ opts.cssBefore.left = 0;
+ opts.animIn.top = 0;
+ opts.animOut.top = h;
+};
+$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) {
+ $cont.css('overflow','hidden');
+ opts.before.push($.fn.cycle.commonReset);
+ var w = $cont.width();
+ opts.cssFirst.left = 0;
+ opts.cssBefore.left = w;
+ opts.cssBefore.top = 0;
+ opts.animIn.left = 0;
+ opts.animOut.left = 0-w;
+};
+$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) {
+ $cont.css('overflow','hidden');
+ opts.before.push($.fn.cycle.commonReset);
+ var w = $cont.width();
+ opts.cssFirst.left = 0;
+ opts.cssBefore.left = -w;
+ opts.cssBefore.top = 0;
+ opts.animIn.left = 0;
+ opts.animOut.left = w;
+};
+$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) {
+ $cont.css('overflow','hidden').width();
+ opts.before.push(function(curr, next, opts, fwd) {
+ if (opts.rev)
+ fwd = !fwd;
+ $.fn.cycle.commonReset(curr,next,opts);
+ opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW);
+ opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW;
+ });
+ opts.cssFirst.left = 0;
+ opts.cssBefore.top = 0;
+ opts.animIn.left = 0;
+ opts.animOut.top = 0;
+};
+$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) {
+ $cont.css('overflow','hidden');
+ opts.before.push(function(curr, next, opts, fwd) {
+ if (opts.rev)
+ fwd = !fwd;
+ $.fn.cycle.commonReset(curr,next,opts);
+ opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1);
+ opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH;
+ });
+ opts.cssFirst.top = 0;
+ opts.cssBefore.left = 0;
+ opts.animIn.top = 0;
+ opts.animOut.left = 0;
+};
+
+// slideX/slideY
+$.fn.cycle.transitions.slideX = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $(opts.elements).not(curr).hide();
+ $.fn.cycle.commonReset(curr,next,opts,false,true);
+ opts.animIn.width = next.cycleW;
+ });
+ opts.cssBefore.left = 0;
+ opts.cssBefore.top = 0;
+ opts.cssBefore.width = 0;
+ opts.animIn.width = 'show';
+ opts.animOut.width = 0;
+};
+$.fn.cycle.transitions.slideY = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $(opts.elements).not(curr).hide();
+ $.fn.cycle.commonReset(curr,next,opts,true,false);
+ opts.animIn.height = next.cycleH;
+ });
+ opts.cssBefore.left = 0;
+ opts.cssBefore.top = 0;
+ opts.cssBefore.height = 0;
+ opts.animIn.height = 'show';
+ opts.animOut.height = 0;
+};
+
+// shuffle
+$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) {
+ var i, w = $cont.css('overflow', 'visible').width();
+ $slides.css({left: 0, top: 0});
+ opts.before.push(function(curr,next,opts) {
+ $.fn.cycle.commonReset(curr,next,opts,true,true,true);
+ });
+ // only adjust speed once!
+ if (!opts.speedAdjusted) {
+ opts.speed = opts.speed / 2; // shuffle has 2 transitions
+ opts.speedAdjusted = true;
+ }
+ opts.random = 0;
+ opts.shuffle = opts.shuffle || {left:-w, top:15};
+ opts.els = [];
+ for (i=0; i < $slides.length; i++)
+ opts.els.push($slides[i]);
+
+ for (i=0; i < opts.currSlide; i++)
+ opts.els.push(opts.els.shift());
+
+ // custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!)
+ opts.fxFn = function(curr, next, opts, cb, fwd) {
+ if (opts.rev)
+ fwd = !fwd;
+ var $el = fwd ? $(curr) : $(next);
+ $(next).css(opts.cssBefore);
+ var count = opts.slideCount;
+ $el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() {
+ var hops = $.fn.cycle.hopsFromLast(opts, fwd);
+ for (var k=0; k < hops; k++) {
+ if (fwd)
+ opts.els.push(opts.els.shift());
+ else
+ opts.els.unshift(opts.els.pop());
+ }
+ if (fwd) {
+ for (var i=0, len=opts.els.length; i < len; i++)
+ $(opts.els[i]).css('z-index', len-i+count);
+ }
+ else {
+ var z = $(curr).css('z-index');
+ $el.css('z-index', parseInt(z,10)+1+count);
+ }
+ $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() {
+ $(fwd ? this : curr).hide();
+ if (cb) cb();
+ });
+ });
+ };
+ $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
+};
+
+// turnUp/Down/Left/Right
+$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,true,false);
+ opts.cssBefore.top = next.cycleH;
+ opts.animIn.height = next.cycleH;
+ opts.animOut.width = next.cycleW;
+ });
+ opts.cssFirst.top = 0;
+ opts.cssBefore.left = 0;
+ opts.cssBefore.height = 0;
+ opts.animIn.top = 0;
+ opts.animOut.height = 0;
+};
+$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,true,false);
+ opts.animIn.height = next.cycleH;
+ opts.animOut.top = curr.cycleH;
+ });
+ opts.cssFirst.top = 0;
+ opts.cssBefore.left = 0;
+ opts.cssBefore.top = 0;
+ opts.cssBefore.height = 0;
+ opts.animOut.height = 0;
+};
+$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,false,true);
+ opts.cssBefore.left = next.cycleW;
+ opts.animIn.width = next.cycleW;
+ });
+ opts.cssBefore.top = 0;
+ opts.cssBefore.width = 0;
+ opts.animIn.left = 0;
+ opts.animOut.width = 0;
+};
+$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,false,true);
+ opts.animIn.width = next.cycleW;
+ opts.animOut.left = curr.cycleW;
+ });
+ $.extend(opts.cssBefore, { top: 0, left: 0, width: 0 });
+ opts.animIn.left = 0;
+ opts.animOut.width = 0;
+};
+
+// zoom
+$.fn.cycle.transitions.zoom = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,false,false,true);
+ opts.cssBefore.top = next.cycleH/2;
+ opts.cssBefore.left = next.cycleW/2;
+ $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
+ $.extend(opts.animOut, { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 });
+ });
+ opts.cssFirst.top = 0;
+ opts.cssFirst.left = 0;
+ opts.cssBefore.width = 0;
+ opts.cssBefore.height = 0;
+};
+
+// fadeZoom
+$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,false,false);
+ opts.cssBefore.left = next.cycleW/2;
+ opts.cssBefore.top = next.cycleH/2;
+ $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH });
+ });
+ opts.cssBefore.width = 0;
+ opts.cssBefore.height = 0;
+ opts.animOut.opacity = 0;
+};
+
+// blindX
+$.fn.cycle.transitions.blindX = function($cont, $slides, opts) {
+ var w = $cont.css('overflow','hidden').width();
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts);
+ opts.animIn.width = next.cycleW;
+ opts.animOut.left = curr.cycleW;
+ });
+ opts.cssBefore.left = w;
+ opts.cssBefore.top = 0;
+ opts.animIn.left = 0;
+ opts.animOut.left = w;
+};
+// blindY
+$.fn.cycle.transitions.blindY = function($cont, $slides, opts) {
+ var h = $cont.css('overflow','hidden').height();
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts);
+ opts.animIn.height = next.cycleH;
+ opts.animOut.top = curr.cycleH;
+ });
+ opts.cssBefore.top = h;
+ opts.cssBefore.left = 0;
+ opts.animIn.top = 0;
+ opts.animOut.top = h;
+};
+// blindZ
+$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) {
+ var h = $cont.css('overflow','hidden').height();
+ var w = $cont.width();
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts);
+ opts.animIn.height = next.cycleH;
+ opts.animOut.top = curr.cycleH;
+ });
+ opts.cssBefore.top = h;
+ opts.cssBefore.left = w;
+ opts.animIn.top = 0;
+ opts.animIn.left = 0;
+ opts.animOut.top = h;
+ opts.animOut.left = w;
+};
+
+// growX - grow horizontally from centered 0 width
+$.fn.cycle.transitions.growX = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,false,true);
+ opts.cssBefore.left = this.cycleW/2;
+ opts.animIn.left = 0;
+ opts.animIn.width = this.cycleW;
+ opts.animOut.left = 0;
+ });
+ opts.cssBefore.top = 0;
+ opts.cssBefore.width = 0;
+};
+// growY - grow vertically from centered 0 height
+$.fn.cycle.transitions.growY = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,true,false);
+ opts.cssBefore.top = this.cycleH/2;
+ opts.animIn.top = 0;
+ opts.animIn.height = this.cycleH;
+ opts.animOut.top = 0;
+ });
+ opts.cssBefore.height = 0;
+ opts.cssBefore.left = 0;
+};
+
+// curtainX - squeeze in both edges horizontally
+$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,false,true,true);
+ opts.cssBefore.left = next.cycleW/2;
+ opts.animIn.left = 0;
+ opts.animIn.width = this.cycleW;
+ opts.animOut.left = curr.cycleW/2;
+ opts.animOut.width = 0;
+ });
+ opts.cssBefore.top = 0;
+ opts.cssBefore.width = 0;
+};
+// curtainY - squeeze in both edges vertically
+$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) {
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,true,false,true);
+ opts.cssBefore.top = next.cycleH/2;
+ opts.animIn.top = 0;
+ opts.animIn.height = next.cycleH;
+ opts.animOut.top = curr.cycleH/2;
+ opts.animOut.height = 0;
+ });
+ opts.cssBefore.height = 0;
+ opts.cssBefore.left = 0;
+};
+
+// cover - curr slide covered by next slide
+$.fn.cycle.transitions.cover = function($cont, $slides, opts) {
+ var d = opts.direction || 'left';
+ var w = $cont.css('overflow','hidden').width();
+ var h = $cont.height();
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts);
+ opts.cssAfter.display = '';
+ if (d == 'right')
+ opts.cssBefore.left = -w;
+ else if (d == 'up')
+ opts.cssBefore.top = h;
+ else if (d == 'down')
+ opts.cssBefore.top = -h;
+ else
+ opts.cssBefore.left = w;
+ });
+ opts.animIn.left = 0;
+ opts.animIn.top = 0;
+ opts.cssBefore.top = 0;
+ opts.cssBefore.left = 0;
+};
+
+// uncover - curr slide moves off next slide
+$.fn.cycle.transitions.uncover = function($cont, $slides, opts) {
+ var d = opts.direction || 'left';
+ var w = $cont.css('overflow','hidden').width();
+ var h = $cont.height();
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,true,true,true);
+ if (d == 'right')
+ opts.animOut.left = w;
+ else if (d == 'up')
+ opts.animOut.top = -h;
+ else if (d == 'down')
+ opts.animOut.top = h;
+ else
+ opts.animOut.left = -w;
+ });
+ opts.animIn.left = 0;
+ opts.animIn.top = 0;
+ opts.cssBefore.top = 0;
+ opts.cssBefore.left = 0;
+};
+
+// toss - move top slide and fade away
+$.fn.cycle.transitions.toss = function($cont, $slides, opts) {
+ var w = $cont.css('overflow','visible').width();
+ var h = $cont.height();
+ opts.before.push(function(curr, next, opts) {
+ $.fn.cycle.commonReset(curr,next,opts,true,true,true);
+ // provide default toss settings if animOut not provided
+ if (!opts.animOut.left && !opts.animOut.top)
+ $.extend(opts.animOut, { left: w*2, top: -h/2, opacity: 0 });
+ else
+ opts.animOut.opacity = 0;
+ });
+ opts.cssBefore.left = 0;
+ opts.cssBefore.top = 0;
+ opts.animIn.left = 0;
+};
+
+// wipe - clip animation
+$.fn.cycle.transitions.wipe = function($cont, $slides, opts) {
+ var w = $cont.css('overflow','hidden').width();
+ var h = $cont.height();
+ opts.cssBefore = opts.cssBefore || {};
+ var clip;
+ if (opts.clip) {
+ if (/l2r/.test(opts.clip))
+ clip = 'rect(0px 0px '+h+'px 0px)';
+ else if (/r2l/.test(opts.clip))
+ clip = 'rect(0px '+w+'px '+h+'px '+w+'px)';
+ else if (/t2b/.test(opts.clip))
+ clip = 'rect(0px '+w+'px 0px 0px)';
+ else if (/b2t/.test(opts.clip))
+ clip = 'rect('+h+'px '+w+'px '+h+'px 0px)';
+ else if (/zoom/.test(opts.clip)) {
+ var top = parseInt(h/2,10);
+ var left = parseInt(w/2,10);
+ clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)';
+ }
+ }
+
+ opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)';
+
+ var d = opts.cssBefore.clip.match(/(\d+)/g);
+ var t = parseInt(d[0],10), r = parseInt(d[1],10), b = parseInt(d[2],10), l = parseInt(d[3],10);
+
+ opts.before.push(function(curr, next, opts) {
+ if (curr == next) return;
+ var $curr = $(curr), $next = $(next);
+ $.fn.cycle.commonReset(curr,next,opts,true,true,false);
+ opts.cssAfter.display = 'block';
+
+ var step = 1, count = parseInt((opts.speedIn / 13),10) - 1;
+ (function f() {
+ var tt = t ? t - parseInt(step * (t/count),10) : 0;
+ var ll = l ? l - parseInt(step * (l/count),10) : 0;
+ var bb = b < h ? b + parseInt(step * ((h-b)/count || 1),10) : h;
+ var rr = r < w ? r + parseInt(step * ((w-r)/count || 1),10) : w;
+ $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' });
+ (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none');
+ })();
+ });
+ $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 });
+ opts.animIn = { left: 0 };
+ opts.animOut = { left: 0 };
+};
+
+})(jQuery);
diff --git a/plugins/jetpack/modules/shortcodes/js/slideshow-shortcode.js b/plugins/jetpack/modules/shortcodes/js/slideshow-shortcode.js
new file mode 100644
index 00000000..5e132097
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/js/slideshow-shortcode.js
@@ -0,0 +1,187 @@
+function JetpackSlideshow( element, width, height, transition ) {
+ this.element = element;
+ this.images = [];
+ this.controls = {};
+ this.transition = transition || 'fade';
+
+ var currentWidth = this.element.width();
+ if ( !width || width > currentWidth )
+ width = currentWidth;
+
+ this.width = width;
+ this.height = height;
+ this.element.css( {
+ 'height': this.height + 'px'
+ } );
+}
+
+JetpackSlideshow.prototype.showLoadingImage = function( toggle ) {
+ if ( toggle ) {
+ this.loadingImage_ = document.createElement( 'div' );
+ this.loadingImage_.className = 'slideshow-loading';
+ var img = document.createElement( 'img' );
+ img.src = jetpackSlideshowSettings.spinner;
+ this.loadingImage_.appendChild( img );
+ this.loadingImage_.appendChild( this.makeZeroWidthSpan() );
+ this.loadingImage_.style.lineHeight = this.height + 'px';
+ this.element.append( this.loadingImage_ );
+ } else if ( this.loadingImage_ ) {
+ this.loadingImage_.parentNode.removeChild( this.loadingImage_ );
+ this.loadingImage_ = null;
+ }
+};
+
+JetpackSlideshow.prototype.init = function() {
+ this.showLoadingImage(true);
+
+ var self = this;
+ // Set up DOM.
+ for ( var i = 0; i < this.images.length; i++ ) {
+ var imageInfo = this.images[i];
+ var img = document.createElement( 'img' );
+ img.src = imageInfo.src + '?w=' + this.width;
+ img.align = 'middle';
+ var caption = document.createElement( 'div' );
+ caption.className = 'slideshow-slide-caption';
+ caption.innerHTML = imageInfo.caption;
+ var container = document.createElement('div');
+ container.className = 'slideshow-slide';
+ container.style.lineHeight = this.height + 'px';
+
+ // Hide loading image once first image has loaded.
+ if ( i == 0 ) {
+ if ( img.complete ) {
+ // IE, image in cache
+ setTimeout( function() {
+ self.finishInit_();
+ }, 1);
+ } else {
+ jQuery( img ).load(function() {
+ self.finishInit_();
+ });
+ }
+ }
+ container.appendChild( img );
+ // I'm not sure where these were coming from, but IE adds
+ // bad values for width/height for portrait-mode images
+ img.removeAttribute('width');
+ img.removeAttribute('height');
+ container.appendChild( this.makeZeroWidthSpan() );
+ container.appendChild( caption );
+ this.element.append( container );
+ }
+};
+
+JetpackSlideshow.prototype.makeZeroWidthSpan = function() {
+ var emptySpan = document.createElement( 'span' );
+ emptySpan.className = 'slideshow-line-height-hack';
+ // Having a NBSP makes IE act weird during transitions, but other
+ // browsers ignore a text node with a space in it as whitespace.
+ if (jQuery.browser.msie) {
+ emptySpan.appendChild( document.createTextNode(' ') );
+ } else {
+ emptySpan.innerHTML = '&nbsp;';
+ }
+ return emptySpan;
+};
+
+JetpackSlideshow.prototype.finishInit_ = function() {
+ this.showLoadingImage( false );
+ this.renderControls_();
+
+ var self = this;
+ // Initialize Cycle instance.
+ this.element.cycle( {
+ fx: this.transition,
+ prev: this.controls.prev,
+ next: this.controls.next,
+ slideExpr: '.slideshow-slide',
+ onPrevNextEvent: function() {
+ return self.onCyclePrevNextClick_.apply( self, arguments );
+ }
+ } );
+
+ var slideshow = this.element;
+ jQuery( this.controls['stop'] ).click( function() {
+ var button = jQuery(this);
+ if ( ! button.hasClass( 'paused' ) ) {
+ slideshow.cycle( 'pause' );
+ button.removeClass( 'running' );
+ button.addClass( 'paused' );
+ } else {
+ button.addClass( 'running' );
+ button.removeClass( 'paused' );
+ slideshow.cycle( 'resume', true );
+ }
+ return false;
+ } );
+
+ var controls = jQuery( this.controlsDiv_ );
+ slideshow.mouseenter( function() {
+ controls.fadeIn();
+ } );
+ slideshow.mouseleave( function() {
+ controls.fadeOut();
+ } );
+
+ this.initialized_ = true;
+};
+
+JetpackSlideshow.prototype.renderControls_ = function() {
+ if ( this.controlsDiv_ )
+ return;
+
+ var controlsDiv = document.createElement( 'div' );
+ controlsDiv.className = 'slideshow-controls';
+
+ controls = [ 'prev', 'stop', 'next' ];
+ for ( var i = 0; i < controls.length; i++ ) {
+ var controlName = controls[i];
+ var a = document.createElement( 'a' );
+ a.href = '#';
+ controlsDiv.appendChild( a );
+ this.controls[controlName] = a;
+ }
+ this.element.append( controlsDiv );
+ this.controlsDiv_ = controlsDiv;
+};
+
+JetpackSlideshow.prototype.onCyclePrevNextClick_ = function( isNext, i, slideElement ) {
+ // If blog_id not present don't track page views
+ if ( ! jetpackSlideshowSettings.blog_id )
+ return;
+
+ var postid = this.images[i].id;
+ var stats = new Image();
+ stats.src = document.location.protocol +
+ '//stats.wordpress.com/g.gif?host=' +
+ escape( document.location.host ) +
+ '&rand=' + Math.random() +
+ '&blog=' + jetpackSlideshowSettings.blog_id +
+ '&subd=' + jetpackSlideshowSettings.blog_subdomain +
+ '&user_id=' + jetpackSlideshowSettings.user_id +
+ '&post=' + postid +
+ '&ref=' + escape( document.location );
+};
+
+( function ( $ ) {
+ function jetpack_slideshow_init() {
+ $( '.jetpack-slideshow-noscript' ).remove();
+
+ $( '.jetpack-slideshow' ).each( function () {
+ var container = $( this );
+
+ if ( container.data( 'processed' ) )
+ return;
+
+ var slideshow = new JetpackSlideshow( container, container.data( 'width' ), container.data( 'height' ), container.data( 'trans' ) );
+ slideshow.images = container.data( 'gallery' );
+ slideshow.init();
+
+ container.data( 'processed', true );
+ } );
+ }
+
+ $( document ).ready( jetpack_slideshow_init );
+ $( 'body' ).on( 'post-load', jetpack_slideshow_init );
+} )( jQuery ); \ No newline at end of file
diff --git a/plugins/jetpack/modules/shortcodes/polldaddy.php b/plugins/jetpack/modules/shortcodes/polldaddy.php
index bcb30f81..7eb30edf 100644
--- a/plugins/jetpack/modules/shortcodes/polldaddy.php
+++ b/plugins/jetpack/modules/shortcodes/polldaddy.php
@@ -193,7 +193,7 @@ SCRIPT;
$data = esc_attr( json_encode( $data ) );
return <<<CONTAINER
-<a name="pd_a_{$poll}"></a>
+<a id="pd_a_{$poll}"></a>
<div class="PDS_Poll" id="PDI_container{$poll}" data-settings="{$data}" style="display:inline-block;{$float}{$margins}"></div>
<div id="PD_superContainer"></div>
<noscript>{$poll_link}</noscript>
@@ -204,7 +204,7 @@ CONTAINER;
$cb = '';
return <<<CONTAINER
-<a name="pd_a_{$poll}"></a>
+<a id="pd_a_{$poll}"></a>
<div class="PDS_Poll" id="PDI_container{$poll}" style="display:inline-block;{$float}{$margins}"></div>
<div id="PD_superContainer"></div>
<script type="text/javascript" charset="UTF-8" src="{$poll_js}{$cb}"></script>
@@ -395,4 +395,4 @@ if ( !function_exists( 'polldaddy_link' ) ) {
add_filter( 'comment_text', 'polldaddy_link', 1 );
}
-} \ No newline at end of file
+}
diff --git a/plugins/jetpack/modules/shortcodes/slideshow.php b/plugins/jetpack/modules/shortcodes/slideshow.php
new file mode 100644
index 00000000..ab1145d8
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/slideshow.php
@@ -0,0 +1,208 @@
+<?php
+
+/**
+ * Slideshow shortcode usage: [gallery type="slideshow"] or the older [slideshow]
+ */
+class Jetpack_Slideshow_Shortcode {
+ public $instance_count = 0;
+
+ function __construct() {
+ global $shortcode_tags;
+
+ $needs_scripts = false;
+
+ // Only if the slideshow shortcode has not already been defined.
+ if ( ! array_key_exists( 'slideshow', $shortcode_tags ) ) {
+ add_shortcode( 'slideshow', array( $this, 'shortcode_callback' ) );
+ $needs_scripts = true;
+ }
+
+ // Only if the gallery shortcode has not been redefined.
+ if ( isset( $shortcode_tags['gallery'] ) && $shortcode_tags['gallery'] == 'gallery_shortcode' ) {
+ add_filter( 'post_gallery', array( $this, 'post_gallery' ), 1002, 2 );
+ add_filter( 'jetpack_gallery_types', array( $this, 'add_gallery_type' ), 10 );
+ $needs_scripts = true;
+ }
+
+ if ( $needs_scripts )
+ add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ), 1 );
+ }
+
+ /**
+ * Responds to the [gallery] shortcode, but not an actual shortcode callback.
+ *
+ * @param $value An empty string if nothing has modified the gallery output, the output html otherwise
+ * @param $attr The shortcode attributes array
+ *
+ * @return string The (un)modified $value
+ */
+ function post_gallery( $value, $attr ) {
+ // Bail if somebody else has done something
+ if ( ! empty( $value ) )
+ return $value;
+
+ // If [gallery type="slideshow"] have it behave just like [slideshow]
+ if ( ! empty( $attr['type'] ) && 'slideshow' == $attr['type'] )
+ return $this->shortcode_callback( $attr );
+
+ return $value;
+ }
+
+ /**
+ * Add the Slideshow type to gallery settings
+ *
+ * @param $types An array of types where the key is the value, and the value is the caption.
+ * @see Jetpack_Tiled_Gallery::media_ui_print_templates
+ */
+ function add_gallery_type( $types = array() ) {
+ $types['slideshow'] = esc_html__( 'Slideshow', 'jetpack' );
+ return $types;
+ }
+
+ function shortcode_callback( $attr, $content = null ) {
+ global $post, $content_width;
+
+ $attr = shortcode_atts( array(
+ 'trans' => 'fade',
+ 'order' => 'ASC',
+ 'orderby' => 'menu_order ID',
+ 'id' => $post->ID,
+ 'include' => '',
+ 'exclude' => '',
+ ), $attr );
+
+ if ( 'rand' == strtolower( $attr['order'] ) )
+ $attr['orderby'] = 'none';
+
+ $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
+ if ( ! $attr['orderby'] )
+ $attr['orderby'] = 'menu_order ID';
+
+ // Don't restrict to the current post if include
+ $post_parent = ( empty( $attr['include'] ) ) ? intval( $attr['id'] ) : null;
+
+ $attachments = get_posts( array(
+ 'post_status' => 'inherit',
+ 'post_type' => 'attachment',
+ 'post_mime_type' => 'image',
+ 'posts_per_page' => -1,
+ 'post_parent' => $post_parent,
+ 'order' => $attr['order'],
+ 'orderby' => $attr['orderby'],
+ 'include' => $attr['include'],
+ 'exclude' => $attr['exclude'],
+ ) );
+
+ if ( count( $attachments ) < 2 )
+ return;
+
+ $gallery_instance = sprintf( "gallery-%d-%d", $attr['id'], ++$this->instance_count );
+
+ $gallery = array();
+ foreach ( $attachments as $attachment ) {
+ $attachment_image_src = wp_get_attachment_image_src( $attachment->ID, 'full' );
+ $attachment_image_src = $attachment_image_src[0]; // [url, width, height]
+ $caption = wptexturize( strip_tags( $attachment->post_excerpt ) );
+
+ $gallery[] = (object) array(
+ 'src' => (string) esc_url_raw( $attachment_image_src ),
+ 'id' => (string) $attachment->ID,
+ 'caption' => (string) $caption,
+ );
+ }
+
+ $max_width = intval( get_option( 'large_size_w' ) );
+ $max_height = 450;
+ if ( intval( $content_width ) > 0 )
+ $max_width = min( intval( $content_width ), $max_width );
+
+ $js_attr = array(
+ 'gallery' => $gallery,
+ 'selector' => $gallery_instance,
+ 'width' => $max_width,
+ 'height' => $max_height,
+ 'trans' => $attr['trans'] ? $attr['trans'] : 'fade',
+ );
+
+ // Show a link to the gallery in feeds.
+ if ( is_feed() )
+ return sprintf( '<a href="%s">%s</a>',
+ esc_url( get_permalink( $post->ID ) . '#' . $gallery_instance . '-slideshow' ),
+ esc_html__( 'Click to view slideshow.', 'jetpack' )
+ );
+
+ return $this->slideshow_js( $js_attr );
+ }
+
+ /**
+ * Render the slideshow js
+ *
+ * Returns the necessary markup and js to fire a slideshow.
+ *
+ * @uses $this->enqueue_scripts()
+ */
+ function slideshow_js( $attr ) {
+ // Enqueue scripts
+ $this->enqueue_scripts();
+
+ if ( $attr['width'] <= 100 )
+ $attr['width'] = 450;
+
+ if ( $attr['height'] <= 100 )
+ $attr['height'] = 450;
+
+ // 40px padding
+ $attr['width'] -= 40;
+ $attr['height'] -= 40;
+
+ $output = '';
+
+ $output .= '<p class="jetpack-slideshow-noscript robots-nocontent">' . esc_html__( 'This slideshow requires JavaScript.', 'jetpack' ) . '</p>';
+ $output .= '<div id="' . esc_attr( $attr['selector'] . '-slideshow' ) . '" class="slideshow-window jetpack-slideshow" data-width="' . esc_attr( $attr['width'] ) . '" data-height="' . esc_attr( $attr['height'] ) . '" data-trans="' . esc_attr( $attr['trans'] ) . '" data-gallery="' . esc_attr( json_encode( $attr['gallery'] ) ) . '"></div>';
+
+ $output .= "
+ <style>
+ #{$attr['selector']}-slideshow .slideshow-slide img {
+ max-height: " . intval( $attr['height'] ) ."px;
+ /* Emulate max-height in IE 6 */
+ _height: expression(this.scrollHeight >= " . intval( $attr['height'] ) . " ? '" . intval( $attr['height'] ) . "px' : 'auto');
+ }
+ </style>
+ ";
+
+ return $output;
+ }
+
+ /**
+ * Infinite Scroll needs the scripts to be present at all times
+ */
+ function maybe_enqueue_scripts() {
+ if ( is_home() && current_theme_supports( 'infinite-scroll' ) )
+ $this->enqueue_scripts();
+ }
+
+ /**
+ * Actually enqueues the scripts and styles.
+ */
+ function enqueue_scripts() {
+ static $enqueued = false;
+
+ if ( $enqueued )
+ return;
+
+ wp_enqueue_script( 'jquery-cycle', plugins_url( '/js/jquery.cycle.js', __FILE__ ) , array( 'jquery' ), '2.9999.8', true );
+ wp_enqueue_script( 'jetpack-slideshow', plugins_url( '/js/slideshow-shortcode.js', __FILE__ ), array( 'jquery-cycle' ), '20121214.1', true );
+ wp_enqueue_style( 'jetpack-slideshow', plugins_url( '/css/slideshow-shortcode.css', __FILE__ ) );
+
+ wp_localize_script( 'jetpack-slideshow', 'jetpackSlideshowSettings', apply_filters( 'jetpack_js_slideshow_settings', array(
+ 'spinner' => plugins_url( '/img/slideshow-loader.gif', __FILE__ ),
+ ) ) );
+
+ $enqueued = true;
+ }
+
+ public static function init() {
+ $gallery = new Jetpack_Slideshow_Shortcode;
+ }
+}
+add_action( 'init', array( 'Jetpack_Slideshow_Shortcode', 'init' ) );
diff --git a/plugins/jetpack/modules/shortcodes/soundcloud.php b/plugins/jetpack/modules/shortcodes/soundcloud.php
index 8aa35380..a7486115 100644
--- a/plugins/jetpack/modules/shortcodes/soundcloud.php
+++ b/plugins/jetpack/modules/shortcodes/soundcloud.php
@@ -1,60 +1,214 @@
<?php
-
/*
Plugin Name: SoundCloud Shortcode
-Plugin URI: http://www.soundcloud.com
-Description: SoundCloud Shortcode. Usage in your posts: [soundcloud]http://soundcloud.com/TRACK_PERMALINK[/soundcloud] . Works also with set or group instead of track. You can provide optional parameters height/width/params like that [soundcloud height="82" params="auto_play=true"]http....
-Version: 1.1.5
-Author: Johannes Wagener <johannes@soundcloud.com> added to wpcom by tott
-Author URI: http://johannes.wagener.cc
-
-[soundcloud url="http://api.soundcloud.com/tracks/9408008"]
-<object height="81" width="100%"> <param name="movie" value="http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F8781356"></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="81" src="http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F8781356" type="application/x-shockwave-flash" width="100%"></embed> </object> <span><a href="http://soundcloud.com/robokopbeats/robokop-we-move-at-midnight-preview-forthcoming-on-mwm-recordings">Robokop - We move at midnight preview ( FORTHCOMING ON MWM recordings)</a> by <a href="http://soundcloud.com/robokopbeats">Robokop</a></span>
+Plugin URI: http://wordpress.org/extend/plugins/soundcloud-shortcode/
+Description: Converts SoundCloud WordPress shortcodes to a SoundCloud widget. Example: [soundcloud]http://soundcloud.com/forss/flickermood[/soundcloud]
+Version: 2.3
+Author: SoundCloud Inc., simplified for Jetpack by Automattic, Inc.
+Author URI: http://soundcloud.com
+License: GPLv2
+
+Original version: Johannes Wagener <johannes@soundcloud.com>
+Options support: Tiffany Conroy <tiffany@soundcloud.com>
+HTML5 & oEmbed support: Tim Bormans <tim@soundcloud.com>
+*/
+
+/*
+A8C: Taken from http://plugins.svn.wordpress.org/soundcloud-shortcode/trunk/
+at revision 664386.
+
+Commenting out (instead of removing) and replacing code with custom modifs
+so it's eqsy to see what differs from the standard DOTORG version.
+
+All custom modifs are annoted with "A8C" keyword in comment.
*/
-add_filter( "pre_kses", "soundcloud_reverse_shortcode" );
+/* Register oEmbed provider
+ -------------------------------------------------------------------------- */
+
+wp_oembed_add_provider('#https?://(?:api\.)?soundcloud\.com/.*#i', 'http://soundcloud.com/oembed', true);
+
+
+/* Register SoundCloud shortcode
+ -------------------------------------------------------------------------- */
+
+add_shortcode("soundcloud", "soundcloud_shortcode");
+
+
+/**
+ * SoundCloud shortcode handler
+ * @param {string|array} $atts The attributes passed to the shortcode like [soundcloud attr1="value" /].
+ * Is an empty string when no arguments are given.
+ * @param {string} $content The content between non-self closing [soundcloud]…[/soundcloud] tags.
+ * @return {string} Widget embed code HTML
+ */
+function soundcloud_shortcode($atts, $content = null) {
+
+ // Custom shortcode options
+ $shortcode_options = array_merge(array('url' => trim($content)), is_array($atts) ? $atts : array());
+
+ // Turn shortcode option "param" (param=value&param2=value) into array
+ $shortcode_params = array();
+ if (isset($shortcode_options['params'])) {
+ parse_str(html_entity_decode($shortcode_options['params']), $shortcode_params);
+ }
+ $shortcode_options['params'] = $shortcode_params;
+
+ // User preference options
+ $plugin_options = array_filter(array(
+ 'iframe' => soundcloud_get_option('player_iframe', true),
+ 'width' => soundcloud_get_option('player_width'),
+ 'height' => soundcloud_url_has_tracklist($shortcode_options['url']) ? soundcloud_get_option('player_height_multi') : soundcloud_get_option('player_height'),
+ 'params' => array_filter(array(
+ 'auto_play' => soundcloud_get_option('auto_play'),
+ 'show_comments' => soundcloud_get_option('show_comments'),
+ 'color' => soundcloud_get_option('color'),
+ 'theme_color' => soundcloud_get_option('theme_color'),
+ )),
+ ));
+ // Needs to be an array
+ if (!isset($plugin_options['params'])) { $plugin_options['params'] = array(); }
+
+ // plugin options < shortcode options
+ $options = array_merge(
+ $plugin_options,
+ $shortcode_options
+ );
+
+ // plugin params < shortcode params
+ $options['params'] = array_merge(
+ $plugin_options['params'],
+ $shortcode_options['params']
+ );
+
+ // The "url" option is required
+ if (!isset($options['url'])) {
+ return '';
+ } else {
+ $options['url'] = trim($options['url']);
+ }
+
+ // Both "width" and "height" need to be integers
+ if (isset($options['width']) && !preg_match('/^\d+$/', $options['width'])) {
+ // set to 0 so oEmbed will use the default 100% and WordPress themes will leave it alone
+ $options['width'] = 0;
+ }
+ if (isset($options['height']) && !preg_match('/^\d+$/', $options['height'])) { unset($options['height']); }
-function soundcloud_reverse_shortcode_preg_replace_callback( $a ) {
- $pattern = '/([a-zA-Z0-9\-_%=&]*)&?url=([^&]+)&?([a-zA-Z0-9\-_%&=]*)/';
- preg_match( $pattern, str_replace( "&amp;", "&", $a[3] ), $params );
+ // The "iframe" option must be true to load the iframe widget
+ $iframe = soundcloud_booleanize($options['iframe'])
+ // Default to flash widget for permalink urls (e.g. http://soundcloud.com/{username})
+ // because HTML5 widget doesn’t support those yet
+ ? preg_match('/api.soundcloud.com/i', $options['url'])
+ : false;
- return '[soundcloud width="' . esc_attr( $a[2] ) . '" height="' . esc_attr( $a[1] ) . '" params="' . esc_attr( $params[1] . $params[3] ) . '" url="' . urldecode( $params[2] ) . '"]';
+ // Return html embed code
+ if ($iframe) {
+ return soundcloud_iframe_widget($options);
+ } else {
+ return soundcloud_flash_widget($options);
+ }
+
+}
+
+/**
+ * Plugin options getter
+ * @param {string|array} $option Option name
+ * @param {mixed} $default Default value
+ * @return {mixed} Option value
+ */
+function soundcloud_get_option($option, $default = false) {
+ $value = get_option('soundcloud_' . $option);
+ return $value === '' ? $default : $value;
+}
+
+/**
+ * Booleanize a value
+ * @param {boolean|string} $value
+ * @return {boolean}
+ */
+function soundcloud_booleanize($value) {
+ return is_bool($value) ? $value : $value === 'true' ? true : false;
}
-function soundcloud_reverse_shortcode( $content ){
- if ( false === stripos( $content, 'http://player.soundcloud.com/player.swf' ) )
- return $content;
+/**
+ * Decide if a url has a tracklist
+ * @param {string} $url
+ * @return {boolean}
+ */
+function soundcloud_url_has_tracklist($url) {
+ return preg_match('/^(.+?)\/(sets|groups|playlists)\/(.+?)$/', $url);
+}
+
+/**
+ * Parameterize url
+ * @param {array} $match Matched regex
+ * @return {string} Parameterized url
+ */
+function soundcloud_oembed_params_callback($match) {
+ global $soundcloud_oembed_params;
- $pattern = '!<object\s*height="(\d+%?)"\s*width="(\d+%?)".*?src="http://.*?soundcloud\.com/player.swf\?([^"]+)".*?</object>.*?</span>!';
- $pattern_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $pattern, ENT_NOQUOTES ) );
+ // Convert URL to array
+ $url = parse_url(urldecode($match[1]));
+ // Convert URL query to array
+ parse_str($url['query'], $query_array);
+ // Build new query string
+ $query = http_build_query(array_merge($query_array, $soundcloud_oembed_params));
- if ( preg_match( $pattern_ent, $content ) )
- return( preg_replace_callback( $pattern_ent, 'soundcloud_reverse_shortcode_preg_replace_callback', $content ) );
- else
- return( preg_replace_callback( $pattern, 'soundcloud_reverse_shortcode_preg_replace_callback', $content ) );
+ return 'src="' . $url['scheme'] . '://' . $url['host'] . $url['path'] . '?' . $query;
}
-add_shortcode( "soundcloud", "soundcloud_shortcode" );
-
-function soundcloud_shortcode( $atts, $url = '' ) {
- if ( empty( $url ) )
- extract( shortcode_atts( array( 'url' => '', 'params' => '', 'height' => '', 'width' => '100%' ), $atts ) );
- else
- extract( shortcode_atts( array( 'params' => '', 'height' => '', 'width' => '100%' ), $atts ) );
-
- $encoded_url = urlencode( $url );
- if ( $url = parse_url( $url ) ) {
- $splitted_url = split( "/", $url['path'] );
- $media_type = $splitted_url[ count( $splitted_url ) - 2 ];
-
- if ( '' == $height ){
- if ( in_array( $media_type, array( 'groups', 'sets' ) ) )
- $height = 225;
- else
- $height = 81;
- }
- $player_params = "url=$encoded_url&g=1&$params";
-
- return '<object height="' . esc_attr( $height ) . '" width="' . esc_attr( $width ) . '"><param name="movie" value="' . esc_url( "http://player.soundcloud.com/player.swf?$player_params" ) . '"></param><embed height="' . esc_attr( $height ) . '" src="' . esc_url( "http://player.soundcloud.com/player.swf?$player_params" ) . '" type="application/x-shockwave-flash" width="' . esc_attr( $width ) . '"> </embed> </object>';
- }
+/**
+ * Iframe widget embed code
+ * @param {array} $options Parameters
+ * @return {string} Iframe embed code
+ */
+function soundcloud_iframe_widget($options) {
+
+ // Merge in "url" value
+ $options['params'] = array_merge(array(
+ 'url' => $options['url']
+ ), $options['params']);
+
+ // Build URL
+ $url = 'http://w.soundcloud.com/player?' . http_build_query($options['params']);
+ // Set default width if not defined
+ $width = isset($options['width']) && $options['width'] !== 0 ? $options['width'] : '100%';
+ // Set default height if not defined
+ $height = isset($options['height']) && $options['height'] !== 0 ? $options['height'] : (soundcloud_url_has_tracklist($options['url']) ? '450' : '166');
+
+ return sprintf('<iframe width="%s" height="%s" scrolling="no" frameborder="no" src="%s"></iframe>', $width, $height, $url);
}
+
+/**
+ * Legacy Flash widget embed code
+ * @param {array} $options Parameters
+ * @return {string} Flash embed code
+ */
+function soundcloud_flash_widget($options) {
+
+ // Merge in "url" value
+ $options['params'] = array_merge(array(
+ 'url' => $options['url']
+ ), $options['params']);
+
+ // Build URL
+ $url = 'http://player.soundcloud.com/player.swf?' . http_build_query($options['params']);
+ // Set default width if not defined
+ $width = isset($options['width']) && $options['width'] !== 0 ? $options['width'] : '100%';
+ // Set default height if not defined
+ $height = isset($options['height']) && $options['height'] !== 0 ? $options['height'] : (soundcloud_url_has_tracklist($options['url']) ? '255' : '81');
+
+ return preg_replace('/\s\s+/', "", sprintf('<object width="%s" height="%s">
+ <param name="movie" value="%s"></param>
+ <param name="allowscriptaccess" value="always"></param>
+ <embed width="%s" height="%s" src="%s" allowscriptaccess="always" type="application/x-shockwave-flash"></embed>
+ </object>', $width, $height, $url, $width, $height, $url));
+}
+
+
+
+/* Settings
+ -------------------------------------------------------------------------- */
+
+/* A8C: no user-defined options, KISS */
diff --git a/plugins/jetpack/modules/shortcodes/ted.php b/plugins/jetpack/modules/shortcodes/ted.php
new file mode 100644
index 00000000..afd35961
--- /dev/null
+++ b/plugins/jetpack/modules/shortcodes/ted.php
@@ -0,0 +1,68 @@
+<?php
+/*
+ * TED Player embed code
+ * http://www.ted.com
+ *
+ * http://www.ted.com/talks/view/id/210
+ * http://www.ted.com/talks/marc_goodman_a_vision_of_crimes_in_the_future.html
+ * [ted id="210" lang="eng"]
+ * [ted id="http://www.ted.com/talks/view/id/210" lang="eng"]
+ * [ted id=1539 lang=fr width=560 height=315]
+ */
+
+wp_oembed_add_provider( '!https?://(www\.)?ted.com/talks/view/id/.+!i', 'http://www.ted.com/talks/oembed.json', true );
+wp_oembed_add_provider( '!https?://(www\.)?ted.com/talks/[a-zA-Z\-\_]+\.html!i', 'http://www.ted.com/talks/oembed.json', true );
+
+add_shortcode( 'ted', 'shortcode_ted' );
+function shortcode_ted( $atts, $content = '' ) {
+ global $wp_embed;
+
+ $defaults = array(
+ 'id' => '',
+ 'width' => '',
+ 'height' => '',
+ 'lang' => 'eng',
+ );
+ $atts = shortcode_atts( $defaults, $atts );
+
+ if ( empty( $atts['id'] ) )
+ return '<!-- Missing TED ID -->';
+
+ if ( preg_match( "#^[\d]+$#", $atts['id'], $matches ) )
+ $url = 'http://ted.com/talks/view/id/' . $matches[0];
+ elseif ( preg_match( "#^https?://(www\.)?ted\.com/talks/view/id/[0-9]+$#", $atts['id'], $matches ) )
+ $url = $matches[0];
+
+ unset( $atts['id'] );
+
+ $args = array();
+ if ( is_numeric( $atts['width'] ) )
+ $args['width'] = $atts['width'];
+ else if ( $embed_size_w = get_option( 'embed_size_w' ) )
+ $args['width'] = $embed_size_w;
+ else if ( ! empty( $GLOBALS['content_width'] ) )
+ $args['width'] = (int)$GLOBALS['content_width'];
+ else
+ $args['width'] = 500;
+
+ // Default to a 16x9 aspect ratio if there's no height set
+ if ( is_numeric( $atts['height'] ) )
+ $args['height'] = $atts['height'];
+ else
+ $args['height'] = $args['width'] * 0.5625;
+
+ if ( ! empty( $atts['lang'] ) ) {
+ $args['lang'] = sanitize_key( $atts['lang'] );
+ add_filter( 'oembed_fetch_url', 'ted_filter_oembed_fetch_url', 10, 3 );
+ }
+ $retval = $wp_embed->shortcode( $args, $url );
+ remove_filter( 'oembed_fetch_url', 'ted_filter_oembed_fetch_url', 10 );
+ return $retval;
+}
+
+/**
+ * Filter the request URL to also include the $lang parameter
+ */
+function ted_filter_oembed_fetch_url( $provider, $url, $args ) {
+ return add_query_arg( 'lang', $args['lang'], $provider );
+}
diff --git a/plugins/jetpack/modules/shortcodes/videopress.php b/plugins/jetpack/modules/shortcodes/videopress.php
index 912ab4cf..6aebae03 100644
--- a/plugins/jetpack/modules/shortcodes/videopress.php
+++ b/plugins/jetpack/modules/shortcodes/videopress.php
@@ -4,7 +4,7 @@
* @category video
* @author Automattic Inc
* @link http://automattic.com/wordpress-plugins/#videopress VideoPress
- * @version 1.5
+ * @version 1.5.4
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
@@ -15,8 +15,8 @@ Description: Upload new videos to <a href="http://videopress.com/">VideoPress</a
Author: Automattic, Niall Kennedy, Joseph Scott, Gary Pendergast
Contributor: Hailin Wu
Author URI: http://automattic.com/wordpress-plugins/#videopress
-Version: 1.5
-Stable tag: 1.5
+Version: 1.5.4
+Stable tag: 1.5.4
License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
@@ -33,7 +33,7 @@ class VideoPress {
* @var string
* @since 1.3
*/
- const version = '1.5';
+ const version = '1.5.4';
/**
* Minimum allowed width. We don't expect videos viewed below this width to be useful; we drop small values to help save publishers from themselves.
@@ -186,7 +186,7 @@ class VideoPress {
wp_enqueue_script( 'swfobject', $swfobject, false. '2.2' );
wp_enqueue_script( 'jquery', $jquery, false, '1.4.4' );
- wp_enqueue_script( 'videopress', $vpjs, array( 'jquery','swfobject' ), '1.07' );
+ wp_enqueue_script( 'videopress', $vpjs, array( 'jquery','swfobject' ), '1.09' );
$this->js_loaded = true;
return true;
@@ -228,10 +228,24 @@ class VideoPress {
'w' => 0,
'freedom' => false,
'flashonly' => false,
- 'autoplay' => false
+ 'autoplay' => false,
+ 'hd' => false
), $attr ) );
$freedom = (bool) $freedom;
+ /**
+ * Test if embedded blog prefers videos only displayed in Freedom-loving formats
+ */
+ if ( $freedom === false && (bool) get_option( 'video_player_freedom', false ) )
+ $freedom = true;
+
+ $forcestatic = get_option( 'video_player_static', false );
+
+ /**
+ * Set the video to HD if the blog option has it enabled
+ */
+ if ( (bool) get_option( 'video_player_high_quality', false ) )
+ $hd = true;
$width = absint($w);
unset($w);
@@ -250,7 +264,9 @@ class VideoPress {
$options = array(
'freedom' => $freedom,
'force_flash' => (bool) $flashonly,
- 'autoplay' => (bool) $autoplay
+ 'autoplay' => (bool) $autoplay,
+ 'forcestatic' => $forcestatic,
+ 'hd' => (bool) $hd
);
unset( $freedom );
unset( $flashonly );
@@ -586,7 +602,6 @@ class VideoPress_Video {
$url = 'https://v.wordpress.com/data/wordpress.json';
$response = wp_remote_get( $url . '?' . http_build_query( $request_params, null, '&' ), array(
- 'httpversion' => '1.1',
'redirection' => 1,
'user-agent' => 'VideoPress plugin ' . VideoPress::version . '; WordPress ' . $wp_version . ' (' . home_url('/') . ')'
) );
@@ -791,12 +806,15 @@ class VideoPress_Player {
$content = '';
} elseif ( is_wp_error( $this->video ) ) {
$content = $this->error_message( $this->video );
- } elseif ( ( isset( $this->video->restricted_embed ) && $this->video->restricted_embed === true ) || ( isset( $this->options['force_flash'] ) && $this->options['force_flash'] === true ) ) {
+ } elseif ( isset( $this->options['force_flash'] ) && $this->options['force_flash'] === true ) {
$content = $this->flash_object();
+ } elseif ( isset( $this->video->restricted_embed ) && $this->video->restricted_embed === true ) {
+ if( $this->options['forcestatic'] )
+ $content = $this->flash_object();
+ else
+ $content = $this->html5_dynamic();
} elseif ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true ) {
$content = $this->html5_static();
- } elseif ( ! in_the_loop() ) {
- $content = $this->flash_object();
} else {
$content = $this->html5_dynamic();
}
@@ -1029,7 +1047,8 @@ class VideoPress_Player {
'blog' => absint( $this->video->blog_id ),
'post' => absint( $this->video->post_id ),
'duration'=> absint( $this->video->duration ),
- 'poster' => esc_url_raw( $this->video->poster_frame_uri, array( 'http', 'https' ) )
+ 'poster' => esc_url_raw( $this->video->poster_frame_uri, array( 'http', 'https' ) ),
+ 'hd' => (bool) $this->options['hd']
);
if ( isset( $this->video->videos ) ) {
if ( isset( $this->video->videos->mp4 ) && isset( $this->video->videos->mp4->url ) )
@@ -1046,10 +1065,7 @@ class VideoPress_Player {
$guid = $this->video->guid;
$guid_js = json_encode( $guid );
$html .= '<script type="text/javascript">' . PHP_EOL;
-
- // Only need to wait until document is ready if the JS is being loaded in the footer
- if ( ! $videopress->js_loaded )
- $html .= 'jQuery(document).ready(function() {';
+ $html .= 'jQuery(document).ready(function() {';
$html .= 'if ( !jQuery.VideoPress.data[' . json_encode($guid) . '] ) { jQuery.VideoPress.data[' . json_encode($guid) . '] = new Array(); }' . PHP_EOL;
$html .= 'jQuery.VideoPress.data[' . json_encode( $guid ) . '][' . $videopress->shown[$guid] . ']=' . json_encode($data) . ';' . PHP_EOL;
@@ -1096,8 +1112,7 @@ class VideoPress_Player {
$html .= '}';
// close the jQuery(document).ready() function
- if ( !$videopress->js_loaded )
- $html .= '});';
+ $html .= '});';
}
$html .= '</script>' . PHP_EOL;
$html .= '</div>' . PHP_EOL;
diff --git a/plugins/jetpack/modules/shortcodes/vimeo.php b/plugins/jetpack/modules/shortcodes/vimeo.php
index 2225a5fe..02b417e1 100644
--- a/plugins/jetpack/modules/shortcodes/vimeo.php
+++ b/plugins/jetpack/modules/shortcodes/vimeo.php
@@ -39,14 +39,14 @@ function vimeo_shortcode( $atts ) {
if ( isset( $args['w'] ) ) {
$width = (int) $args['w'];
-
+
if ( ! isset( $args['h'] ) ) {
// The case where w=300 is specified without h=200, otherwise $height
// will always equal the default of 300, no matter what w was set to.
$height = round( ( $width / 640 ) * 360 );
}
}
-
+
if ( isset( $args['h'] ) ) {
$height = (int) $args['h'];
@@ -54,7 +54,7 @@ function vimeo_shortcode( $atts ) {
$width = round( ( $height / 360 ) * 640 );
}
}
-
+
if ( ! $width )
$width = absint( $content_width );
@@ -71,13 +71,13 @@ function vimeo_shortcode( $atts ) {
add_shortcode( 'vimeo', 'vimeo_shortcode' );
function vimeo_embed_to_shortcode( $content ) {
- if ( false === stripos( $content, 'player.vimeo.com/video/' ) )
+ if ( false === stripos( $content, 'player.vimeo.com/video/' ) )
return $content;
$regexp = '!<iframe\s+src=[\'"]http://player\.vimeo\.com/video/(\d+)[\'"]((?:\s+\w+=[\'"][^\'"]*[\'"])*)></iframe>!i';
- $regexp_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $regexp, ENT_NOQUOTES ) );
-
- foreach ( array( 'regexp', 'regexp_ent' ) as $reg ) {
+ $regexp_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $regexp, ENT_NOQUOTES ) );
+
+ foreach ( array( 'regexp', 'regexp_ent' ) as $reg ) {
if ( !preg_match_all( $$reg, $content, $matches, PREG_SET_ORDER ) )
continue;
@@ -86,7 +86,7 @@ function vimeo_embed_to_shortcode( $content ) {
$params = $match[2];
- if ( 'regexp_ent' == $reg )
+ if ( 'regexp_ent' == $reg )
$params = html_entity_decode( $params );
$params = wp_kses_hair( $params, array( 'http' ) );
@@ -95,8 +95,8 @@ function vimeo_embed_to_shortcode( $content ) {
$height = isset( $params['height'] ) ? (int) $params['height']['value'] : 0;
$wh = '';
- if ( $width && $height )
- $wh = ' w=' . $width . ' h=' . $height;
+ if ( $width && $height )
+ $wh = ' w=' . $width . ' h=' . $height;
$shortcode = '[vimeo ' . $id . $wh . ']';
$content = str_replace( $match[0], $shortcode, $content );
diff --git a/plugins/jetpack/modules/shortcodes/youtube.php b/plugins/jetpack/modules/shortcodes/youtube.php
index ebf989f0..74c497ed 100644
--- a/plugins/jetpack/modules/shortcodes/youtube.php
+++ b/plugins/jetpack/modules/shortcodes/youtube.php
@@ -140,6 +140,7 @@ function youtube_sanitize_url( $url ) {
function get_youtube_id( $url ) {
$url = youtube_sanitize_url( $url );
$url = parse_url( $url );
+ $id = false;
if ( ! isset( $url['query'] ) )
return false;
@@ -149,7 +150,8 @@ function get_youtube_id( $url ) {
if ( ! isset( $qargs['v'] ) && ! isset( $qargs['list'] ) )
return false;
- $id = preg_replace( '|[^_a-z0-9-]|i', '', $qargs['list'] );
+ if ( isset( $qargs['list'] ) )
+ $id = preg_replace( '|[^_a-z0-9-]|i', '', $qargs['list'] );
if ( empty( $id ) )
$id = preg_replace( '|[^_a-z0-9-]|i', '', $qargs['v'] );
@@ -175,12 +177,6 @@ function youtube_id( $url ) {
parse_str( $url['query'], $qargs );
- $agent = $_SERVER['HTTP_USER_AGENT'];
- // Bloglines & Google Reader handle YouTube well now, instead of
- // big blank space of yester year, so they can skip this treatment
- if ( is_feed() && ! preg_match( '#' . apply_filters( 'jetpack_shortcode_youtube_whitelist_user_agents', 'Bloglines|FeedFetcher-Google|feedburner' ) . '#i', $agent ) )
- return '<span style="text-align:center; display: block;"><a href="' . get_permalink() . '"><img src="http://img.youtube.com/vi/' . $id . '/2.jpg" alt="" /></a></span>';
-
// calculate the width and height, taking content_width into consideration
global $content_width;
diff --git a/plugins/jetpack/modules/stats.php b/plugins/jetpack/modules/stats.php
index 32c6cf2c..260b3f58 100644
--- a/plugins/jetpack/modules/stats.php
+++ b/plugins/jetpack/modules/stats.php
@@ -10,11 +10,26 @@ if ( defined( 'STATS_VERSION' ) ) {
return;
}
-define( 'STATS_VERSION', '7' );
+define( 'STATS_VERSION', '8' );
defined( 'STATS_DASHBOARD_SERVER' ) or define( 'STATS_DASHBOARD_SERVER', 'dashboard.wordpress.com' );
add_action( 'jetpack_modules_loaded', 'stats_load' );
+// Tell HQ about changed settings
+Jetpack_Sync::sync_options( __FILE__,
+ 'stats_options',
+ 'home',
+ 'siteurl',
+ 'blogname',
+ 'blogdescription',
+ 'gmt_offset',
+ 'timezone_string',
+ 'page_on_front',
+ 'permalink_structure',
+ 'category_base',
+ 'tag_base'
+);
+
function stats_load() {
global $wp_roles;
@@ -23,6 +38,14 @@ function stats_load() {
Jetpack::module_configuration_head( __FILE__, 'stats_configuration_head' );
Jetpack::module_configuration_screen( __FILE__, 'stats_configuration_screen' );
+ // Tell HQ about changed posts
+ $post_stati = get_post_stati( array( 'public' => true ) ); // All public post stati
+ $post_stati[] = 'private'; // Content from private stati will be redacted
+ Jetpack_Sync::sync_posts( __FILE__, array(
+ 'post_types' => get_post_types( array( 'public' => true ) ), // All public post types
+ 'post_stati' => $post_stati,
+ ) );
+
// Generate the tracking code after wp() has queried for posts.
add_action( 'template_redirect', 'stats_template_redirect', 1 );
@@ -32,22 +55,6 @@ function stats_load() {
add_action( 'wp_dashboard_setup', 'stats_register_dashboard_widget' );
- // Tell HQ about changed settings
- add_action( 'update_option_home', 'stats_update_blog' );
- add_action( 'update_option_siteurl', 'stats_update_blog' );
- add_action( 'update_option_blogname', 'stats_update_blog' );
- add_action( 'update_option_blogdescription', 'stats_update_blog' );
- add_action( 'update_option_timezone_string', 'stats_update_blog' );
- add_action( 'add_option_timezone_string', 'stats_update_blog' );
- add_action( 'update_option_gmt_offset', 'stats_update_blog' );
- add_action( 'update_option_page_on_front', 'stats_update_blog' );
- add_action( 'update_option_permalink_structure', 'stats_update_blog' );
- add_action( 'update_option_category_base', 'stats_update_blog' );
- add_action( 'update_option_tag_base', 'stats_update_blog' );
-
- // Tell HQ about changed posts
- add_action( 'save_post', 'stats_update_post', 10, 1 );
-
add_filter( 'jetpack_xmlrpc_methods', 'stats_xmlrpc_methods' );
// Map stats caps
@@ -111,6 +118,7 @@ function stats_template_redirect() {
add_action( 'wp_head', 'stats_add_shutdown_action' );
$blog = Jetpack::get_option( 'id' );
+ $tz = get_option( 'gmt_offset' );
$v = 'ext';
$j = sprintf( '%s:%s', JETPACK__API_VERSION, JETPACK__VERSION );
if ( $wp_the_query->is_single || $wp_the_query->is_page || $wp_the_query->is_posts_page ) {
@@ -134,7 +142,7 @@ function stats_template_redirect() {
$http = is_ssl() ? 'https' : 'http';
$week = gmdate( 'YW' );
- $data = stats_array( compact( 'v', 'j', 'blog', 'post' ) );
+ $data = stats_array( compact( 'v', 'j', 'blog', 'post', 'tz' ) );
$stats_footer = <<<END
@@ -369,7 +377,7 @@ function stats_reports_page() {
'data' => 'data',
'blog_subscribers' => 'int',
'comment_subscribers' => null,
- 'type' => array( 'email', 'pending' ),
+ 'type' => array( 'wpcom', 'email', 'pending' ),
'pagenum' => 'int',
);
foreach ( $args as $var => $vals ) {
@@ -401,24 +409,21 @@ function stats_reports_page() {
$url = add_query_arg( $q, $url );
$method = 'GET';
$timeout = 90;
- $user_id = 1; // means send the wp.com user_id, not 1
+ $user_id = JETPACK_MASTER_USER; // means send the wp.com user_id
$get = Jetpack_Client::remote_request( compact( 'url', 'method', 'timeout', 'user_id' ) );
$get_code = wp_remote_retrieve_response_code( $get );
- $get_code_type = intval( $get_code / 100 );
- if ( is_wp_error( $get ) || ( 2 != $get_code_type && 304 != $get_code ) ) {
- // @todo nicer looking error
- if ( 3 == $get_code_type ) {
- echo '<p>' . __( 'We were unable to get your stats just now (too many redirects). Please try again.', 'jetpack' ) . '</p>';
- } else {
- echo '<p>' . __( 'We were unable to get your stats just now. Please try again.', 'jetpack' ) . '</p>';
- }
+ if ( is_wp_error( $get ) || ( 2 != intval( $get_code / 100 ) && 304 != $get_code ) || empty( $get['body'] ) ) {
+ stats_print_wp_remote_error( $get, $url );
} else {
if ( !empty( $get['headers']['content-type'] ) ) {
$type = $get['headers']['content-type'];
if ( substr( $type, 0, 5 ) == 'image' ) {
+ $img = $get['body'];
header( 'Content-Type: ' . $type );
- die( $get['body'] );
+ header( 'Content-Length: ' . strlen( $img ) );
+ echo $img;
+ die();
}
}
$body = stats_convert_post_titles( $get['body'] );
@@ -442,7 +447,13 @@ function stats_convert_image_urls( $html ) {
}
function stats_convert_chart_urls( $html ) {
- $html = preg_replace( '|https?://[-.a-z0-9]+/wp-includes/charts/([-.a-z0-9]+).php|', 'admin.php?page=stats&noheader&chart=$1', $html );
+ $html = preg_replace_callback( '|https?://[-.a-z0-9]+/wp-includes/charts/([-.a-z0-9]+).php(\??)|',
+ create_function(
+ '$matches',
+ // If there is a query string, change the beginning '?' to a '&' so it fits into the middle of this query string
+ 'return "admin.php?page=stats&noheader&chart=" . $matches[1] . str_replace( "?", "&", $matches[2] );'
+ ),
+ $html );
return $html;
}
@@ -591,7 +602,9 @@ function stats_admin_bar_menu( &$wp_admin_bar ) {
$img_src = esc_attr( add_query_arg( array( 'noheader'=>'', 'proxy'=>'', 'chart'=>'admin-bar-hours-scale' ), $url ) );
$img_src_2x = esc_attr( add_query_arg( array( 'noheader'=>'', 'proxy'=>'', 'chart'=>'admin-bar-hours-scale-2x' ), $url ) );
- $title = __( 'Views over 48 hours. Click for more Site Stats.', 'jetpack' );
+ $alt = esc_attr( __( 'Stats', 'jetpack' ) );
+
+ $title = esc_attr( __( 'Views over 48 hours. Click for more Site Stats.', 'jetpack' ) );
$menu = array( 'id' => 'stats', 'title' => "<div><script type='text/javascript'>var src;if(typeof(window.devicePixelRatio)=='undefined'||window.devicePixelRatio<2){src='$img_src';}else{src='$img_src_2x';}document.write('<img src=\''+src+'\' alt=\'$alt\' title=\'$title\' />');</script></div>", 'href' => $url );
@@ -602,14 +615,6 @@ function stats_update_blog() {
Jetpack::xmlrpc_async_call( 'jetpack.updateBlog', stats_get_blog() );
}
-function stats_update_post( $post ) {
- if ( !$stats_post = stats_get_post( $post ) )
- return;
-
- $jetpack = Jetpack::init();
- $jetpack->sync->post( $stats_post->ID, array_keys( get_object_vars( $stats_post ) ) );
-}
-
function stats_get_blog() {
$home = parse_url( trailingslashit( get_option( 'home' ) ) );
$blog = array(
@@ -632,36 +637,9 @@ function stats_get_blog() {
return array_map( 'esc_html', $blog );
}
-function stats_get_posts( $args ) {
- list( $post_ids ) = $args;
- $post_ids = array_map( 'intval', (array) $post_ids );
- $r = array(
- 'include' => $post_ids,
- 'post_type' => array_values( get_post_types( array( 'public' => true ) ) ),
- 'post_status' => array_values( get_post_stati( array( 'public' => true ) ) ),
- );
- $posts = get_posts( $r );
- foreach ( $posts as $i => $post )
- $posts[$i] = stats_get_post( $post );
- return $posts;
-}
-
-function stats_get_post( $post ) {
- if ( !$post = get_post( $post ) ) {
- return null;
- }
-
- $stats_post = wp_clone( $post );
- $stats_post->permalink = get_permalink( $post );
- foreach ( array( 'post_content', 'post_excerpt', 'post_content_filtered', 'post_password' ) as $do_not_want )
- unset( $stats_post->$do_not_want );
- return $stats_post;
-}
-
function stats_xmlrpc_methods( $methods ) {
$my_methods = array(
'jetpack.getBlog' => 'stats_get_blog',
- 'jetpack.getPosts' => 'stats_get_posts',
);
return array_merge( $methods, $my_methods );
@@ -737,7 +715,7 @@ function stats_dashboard_widget_control() {
</p>
<p>
- <label for="top"><?php _e( 'Show top posts over', 'jetpack'); ?></label>
+ <label for="top"><?php _e( 'Show top posts over', 'jetpack' ); ?></label>
<select id="top" name="top">
<?php
foreach ( $intervals as $val => $label ) {
@@ -750,7 +728,7 @@ function stats_dashboard_widget_control() {
</p>
<p>
- <label for="search"><?php _e( 'Show top search terms over', 'jetpack'); ?></label>
+ <label for="search"><?php _e( 'Show top search terms over', 'jetpack' ); ?></label>
<select id="search" name="search">
<?php
foreach ( $intervals as $val => $label ) {
@@ -892,18 +870,12 @@ function stats_dashboard_widget_content() {
$url = add_query_arg( $q, $url );
$method = 'GET';
$timeout = 90;
- $user_id = 1; // means send the wp.com user_id, not 1
+ $user_id = JETPACK_MASTER_USER;
$get = Jetpack_Client::remote_request( compact( 'url', 'method', 'timeout', 'user_id' ) );
$get_code = wp_remote_retrieve_response_code( $get );
- $get_code_type = intval( $get_code / 100 );
- if ( is_wp_error( $get ) || ( 2 != $get_code_type && 304 != $get_code ) || empty( $get['body'] ) ) {
- // @todo
- if ( 3 == $get_code_type ) {
- echo '<p>' . __( 'We were unable to get your stats just now (too many redirects). Please try again.', 'jetpack' ) . '</p>';
- } else {
- echo '<p>' . __( 'We were unable to get your stats just now. Please try again.', 'jetpack' ) . '</p>';
- }
+ if ( is_wp_error( $get ) || ( 2 != intval( $get_code / 100 ) && 304 != $get_code ) || empty( $get['body'] ) ) {
+ stats_print_wp_remote_error( $get, $url );
} else {
$body = stats_convert_post_titles($get['body']);
$body = stats_convert_chart_urls($body);
@@ -976,6 +948,50 @@ function stats_dashboard_widget_content() {
exit;
}
+function stats_print_wp_remote_error( $get, $url ) {
+ $state_name = 'stats_remote_error_' . substr( md5( $url ), 0, 8 );
+ $previous_error = Jetpack::state( $state_name );
+ $error = md5( serialize( compact( 'get', 'url' ) ) );
+ Jetpack::state( $state_name, $error );
+ if ( $error !== $previous_error ) {
+?>
+ <div class="wrap">
+ <p><?php _e( 'We were unable to get your stats just now. Please reload this page to try again.', 'jetpack' ); ?></p>
+ </div>
+<?php
+ return;
+ }
+?>
+ <div class="wrap">
+ <p><?php printf( __( 'We were unable to get your stats just now. Please reload this page to try again. If this error persists, please <a href="%1$s">contact support</a>. In your report please include the information below.', 'jetpack' ), 'http://support.wordpress.com/contact/?jetpack=needs-service' ); ?></p>
+ <pre>
+ User Agent: "<?php print htmlspecialchars( $_SERVER['HTTP_USER_AGENT'] ); ?>"
+ Page URL: "http<?php print (is_ssl()?'s':'') . '://' . htmlspecialchars( $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ); ?>"
+ API URL: "<?php print clean_url( $url ); ?>"
+<?php
+ if ( is_wp_error( $get ) ) {
+ foreach ( $get->get_error_codes() as $code ) {
+ foreach ( $get->get_error_messages($code) as $message ) {
+ ?>
+ <?php print $code . ': "' . $message . '"' ?>
+
+<?php
+ }
+ }
+ } else {
+ $get_code = wp_remote_retrieve_response_code( $get );
+ $content_length = strlen( wp_remote_retrieve_body( $get ) );
+ ?>
+ Response code: "<?php print $get_code ?>"
+ Content length: "<?php print $content_length ?>"
+
+<?php
+ }
+ ?></pre>
+ </div>
+ <?php
+}
+
function stats_get_csv( $table, $args = null ) {
$defaults = array( 'end' => false, 'days' => false, 'limit' => 3, 'post_id' => false, 'summarize' => '' );
@@ -1034,7 +1050,7 @@ function stats_get_csv( $table, $args = null ) {
function stats_get_remote_csv( $url ) {
$method = 'GET';
$timeout = 90;
- $user_id = 1; // means send the wp.com user_id, not 1
+ $user_id = JETPACK_MASTER_USER;
$get = Jetpack_Client::remote_request( compact( 'url', 'method', 'timeout', 'user_id' ) );
$get_code = wp_remote_retrieve_response_code( $get );
diff --git a/plugins/jetpack/modules/subscriptions.php b/plugins/jetpack/modules/subscriptions.php
index 2355867e..39c639ff 100644
--- a/plugins/jetpack/modules/subscriptions.php
+++ b/plugins/jetpack/modules/subscriptions.php
@@ -8,6 +8,23 @@
add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
+Jetpack_Sync::sync_options( __FILE__,
+ 'home',
+ 'blogname',
+ 'siteurl',
+ 'page_on_front',
+ 'permalink_structure',
+ 'category_base',
+ 'rss_use_excerpt',
+ 'subscription_options',
+ 'stb_enabled',
+ 'stc_enabled',
+ 'tag_base'
+);
+
+Jetpack_Sync::sync_posts( __FILE__ );
+Jetpack_Sync::sync_comments( __FILE__ );
+
function jetpack_subscriptions_load() {
Jetpack::enable_module_configurable( __FILE__ );
Jetpack::module_configuration_load( __FILE__, 'jetpack_subscriptions_configuration_load' );
@@ -17,6 +34,7 @@ function jetpack_subscriptions_configuration_load() {
wp_safe_redirect( admin_url( 'options-discussion.php#jetpack-subscriptions-settings' ) );
exit;
}
+
class Jetpack_Subscriptions {
var $jetpack = false;
@@ -43,22 +61,6 @@ class Jetpack_Subscriptions {
// Add Configuration Page
add_action( 'admin_init', array( $this, 'configure' ) );
-
- // Handle Posts
- add_action( 'transition_post_status', array( $this, 'transition_post_status' ), 10, 3 );
- add_action( 'trashed_post', array( $this, 'delete_post' ) );
- add_action( 'delete_post', array( $this, 'delete_post' ) );
-
- // Handle Taxonomy
- add_action( 'created_term', array( $this, 'save_taxonomy'), 10, 3);
- add_action( 'edited_term', array( $this, 'save_taxonomy'), 10, 3 );
- add_action( 'delete_term', array( $this, 'delete_taxonomy'), 10, 3 );
-
- // Handle Comments
- add_action( 'wp_insert_comment', array( $this, 'save_comment' ), 10, 2 );
- add_action( 'transition_comment_status', array( $this, 'transition_comment_status' ), 10, 3 );
- add_action( 'trashed_comment', array( $this, 'delete_comment' ) );
- add_action( 'delete_comment', array( $this, 'delete_comment' ) );
// Set up the subscription widget.
add_action( 'widgets_init', array( $this, 'widget_init' ) );
@@ -82,73 +84,6 @@ class Jetpack_Subscriptions {
return 'publish' === $post->post_status && strlen( (string) $post->post_password ) < 1;
}
- function transition_post_status( $new, $old, $the_post ) {
- if ( 'publish' == $old && 'publish' != $new ) {
- // A published post was trashed or something else
- $this->delete_post( $the_post->ID );
- return;
- }
-
- clean_post_cache( $the_post->ID );
-
- // Publish a new post
- if (
- 'publish' != $old
- &&
- $this->post_is_public( $the_post->ID )
- &&
- ( 'post' == $the_post->post_type || 'page' == $the_post->post_type )
- ) {
- $this->jetpack->sync->post( $the_post->ID );
- }
- }
-
- function save_taxonomy( $term, $tt_id, $taxonomy = null ) {
- if ( is_null( $taxonomy ) )
- return;
-
- $tax = get_term_by( 'id', $term, $taxonomy );
- $this->jetpack->sync->taxonomy( $tax->slug, true, $taxonomy );
- }
-
- function delete_taxonomy( $term, $tt_id, $taxonomy ) {
- $tags = get_terms( $taxonomy, array( 'hide_empty' => 0 ) ); // since we can't figure out what the slug is... we will do an array comparison on the remote site and remove old taxonomy...
- $this->jetpack->sync->delete_taxonomy( $tags, $taxonomy );
- }
-
- function delete_post( $id ) {
- $the_post = get_post( $id );
- if ( 'post' == $the_post->post_type || 'page' == $the_post->post_type )
- $this->jetpack->sync->delete_post( $id );
- }
-
- function save_comment( $id, $comment ) {
- if ( !$this->post_is_public( $comment->comment_post_ID ) ) {
- return;
- }
-
- if ( 1 == $comment->comment_approved ) {
- $this->jetpack->sync->comment( $id );
- }
- }
-
- function transition_comment_status( $new, $old, $the_comment ) {
- if ( !$this->post_is_public( $the_comment->comment_post_ID ) ) {
- return;
- }
-
- if ( 'approved' == $new ) {
- $this->jetpack->sync->comment( $the_comment->comment_ID );
- } else if ( 'approved' == $old && 'approved' != $new ) {
- // Delete comments that are changing to anything but approved
- $this->jetpack->sync->delete_comment( $the_comment->comment_ID );
- }
- }
-
- function delete_comment( $id ) {
- $this->jetpack->sync->delete_comment( $id );
- }
-
/**
* Jetpack_Subscriptions::xmlrpc_methods()
*
@@ -204,6 +139,37 @@ class Jetpack_Subscriptions {
'discussion',
'stc_enabled'
);
+
+ /** Subscription Messaging Options ******************************************************/
+
+ register_setting(
+ 'reading',
+ 'subscription_options',
+ array( $this, 'validate_settings' )
+ );
+
+ add_settings_section(
+ 'email_settings',
+ __( 'Follower Settings', 'jetpack' ),
+ array( $this, 'reading_section' ),
+ 'reading'
+ );
+
+ add_settings_field(
+ 'invitation',
+ __( 'Blog follow email text' , 'jetpack' ),
+ array( $this, 'setting_invitation' ),
+ 'reading',
+ 'email_settings'
+ );
+
+ add_settings_field(
+ 'comment-follow',
+ __( 'Comment follow email text', 'jetpack' ),
+ array( $this, 'setting_comment_follow' ),
+ 'reading',
+ 'email_settings'
+ );
}
/**
@@ -249,6 +215,51 @@ class Jetpack_Subscriptions {
<?php
}
+ function validate_settings( $settings ) {
+ global $allowedposttags;
+
+ $default = $this->get_default_settings();
+
+ // Blog Follow
+ $settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
+ if ( empty( $settings['invitation'] ) )
+ $settings['invitation'] = $default['invitation'];
+
+ // Comments Follow (single post)
+ $settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
+ if ( empty( $settings['comment_follow'] ) )
+ $settings['comment_follow'] = $default['comment_follow'];
+
+ return $settings;
+ }
+
+ public function reading_section() {
+ _e( 'These settings change emails sent from your blog to followers.' , 'jetpack');
+ }
+
+ public function setting_invitation() {
+ $settings = $this->get_settings();
+ echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">'.$settings['invitation'].'</textarea>';
+ echo '<p><span class="description">'.__( 'Introduction text sent when someone follows your blog. (Site and confirmation details will be automatically added for you.)' , 'jetpack').'</span></p>';
+ }
+
+ public function setting_comment_follow() {
+ $settings = $this->get_settings();
+ echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">'.$settings['comment_follow'].'</textarea>';
+ echo '<p><span class="description">'.__( 'Introduction text sent when someone follows a post on your blog. (Site and confirmation details will be automatically added for you.)' , 'jetpack').'</span></p>';
+ }
+
+ function get_default_settings() {
+ return array(
+ 'invitation' => __( "Howdy.\n\nYou recently followed this blog's posts. This means you will receive each new post by email.\n\nTo activate, click confirm below. If you believe this is an error, ignore this message and we'll never bother you again." , 'jetpack'),
+ 'comment_follow' => __( "Howdy.\n\nYou recently followed one of my posts. This means you will receive an email when new comments are posted.\n\nTo activate, click confirm below. If you believe this is an error, ignore this message and we'll never bother you again." , 'jetpack')
+ );
+ }
+
+ function get_settings() {
+ return wp_parse_args( (array) get_option( 'subscription_options', array() ), $this->get_default_settings() );
+ }
+
/**
* Jetpack_Subscriptions::subscribe()
*
@@ -356,7 +367,9 @@ class Jetpack_Subscriptions {
*/
function widget_submit() {
// Check the nonce.
- check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
+ if ( is_user_logged_in() ) {
+ check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
+ }
if ( empty( $_REQUEST['email'] ) )
return false;
@@ -428,17 +441,19 @@ class Jetpack_Subscriptions {
$str = '';
- if ( FALSE === has_filter( 'comment_form', 'show_subscription_checkbox' ) ) {
+ if ( FALSE === has_filter( 'comment_form', 'show_subscription_checkbox' ) && 1 == get_option( 'stc_enabled', 1 ) ) {
// Subscribe to comments checkbox
$str .= '<p class="comment-subscription-form"><input type="checkbox" name="subscribe_comments" id="subscribe_comments" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;"' . $comments_checked . ' /> ';
- $str .= '<label class="subscribe-label" id="subscribe-label" for="subscribe_comments">' . __( 'Notify me of follow-up comments by email.', 'jetpack' ) . '</label>';
+ $str .= '<label class="subscribe-label" id="subscribe-label" for="subscribe_comments" style="display: inline;">' . __( 'Notify me of follow-up comments by email.', 'jetpack' ) . '</label>';
$str .= '</p>';
}
- // Subscribe to blog checkbox
- $str .= '<p class="comment-subscription-form"><input type="checkbox" name="subscribe_blog" id="subscribe_blog" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;"' . $blog_checked . ' /> ';
- $str .= '<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog">' . __( 'Notify me of new posts by email.', 'jetpack' ) . '</label>';
- $str .= '</p>';
+ if ( 1 == get_option( 'stb_enabled', 1 ) ) {
+ // Subscribe to blog checkbox
+ $str .= '<p class="comment-subscription-form"><input type="checkbox" name="subscribe_blog" id="subscribe_blog" value="subscribe" style="width: auto; -moz-appearance: checkbox; -webkit-appearance: checkbox;"' . $blog_checked . ' /> ';
+ $str .= '<label class="subscribe-label" id="subscribe-blog-label" for="subscribe_blog" style="display: inline;">' . __( 'Notify me of new posts by email.', 'jetpack' ) . '</label>';
+ $str .= '</p>';
+ }
echo apply_filters( 'jetpack_comment_subscription_form', $str );
}
@@ -516,83 +531,79 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
extract( $args );
$instance = wp_parse_args( (array) $instance, $this->defaults() );
- $title = stripslashes( $instance['title'] );
- $subscribe_text = stripslashes( $instance['subscribe_text'] );
- $subscribe_button = stripslashes( $instance['subscribe_button'] );
- $subscribe_logged_in = stripslashes( $instance['subscribe_logged_in'] );
+ $title = isset( $instance['title'] ) ? stripslashes( $instance['title'] ) : '';
+ $subscribe_text = isset( $instance['subscribe_text'] ) ? stripslashes( $instance['subscribe_text'] ) : '';
+ $subscribe_button = isset( $instance['subscribe_button'] ) ? stripslashes( $instance['subscribe_button'] ) : '';
+ $subscribe_logged_in = isset( $instance['subscribe_logged_in'] ) ? stripslashes( $instance['subscribe_logged_in'] ) : '';
$show_subscribers_total = (bool) $instance['show_subscribers_total'];
$subscribers_total = $this->fetch_subscriber_count();
if ( ! is_array( $subscribers_total ) )
$show_subscribers_total = FALSE;
- echo $before_widget;
- echo $before_title . '<label for="subscribe-field">' . esc_attr( $instance['title'] ) . '</label>' . $after_title . "\n";
+ echo $args['before_widget'];
+ echo $args['before_title'] . '<label for="subscribe-field">' . esc_attr( $instance['title'] ) . '</label>' . $args['after_title'] . "\n";
$referer = ( is_ssl() ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
// Check for subscription confirmation.
- if ( isset( $_GET['subscribe'] ) && 'success' == $_GET['subscribe'] ) {
- ?>
+ if ( isset( $_GET['subscribe'] ) && 'success' == $_GET['subscribe'] ) : ?>
<div class="success">
- <p><?php _e( 'An email was just sent to confirm your subscription. Please find the email now and click activate to start subscribing.', 'jetpack' ); ?></p>
+ <p><?php esc_html_e( 'An email was just sent to confirm your subscription. Please find the email now and click activate to start subscribing.', 'jetpack' ); ?></p>
</div>
- <?php
- }
+ <?php endif;
// Display any errors
if ( isset( $_GET['subscribe'] ) ) :
switch ( $_GET['subscribe'] ) :
- case 'invalid_email' : ?>
- <p class="error"><?php _e( 'The email you entered was invalid, please check and try again.', 'jetpack' ); ?></p>
- <?php break;
- case 'already' : ?>
- <p class="error"><?php _e( 'You have already subscribed to this site, please check your inbox.', 'jetpack' ); ?></p>
- <?php break;
- case 'success' :
-
- echo wpautop( $subscribe_text );
- break;
- default : ?>
- <p class="error"><?php _e( 'There was an error when subscribing, please try again.', 'jetpack' ) ?></p>
- <?php break;
+ case 'invalid_email' : ?>
+ <p class="error"><?php esc_html_e( 'The email you entered was invalid, please check and try again.', 'jetpack' ); ?></p>
+ <?php break;
+ case 'already' : ?>
+ <p class="error"><?php esc_html_e( 'You have already subscribed to this site, please check your inbox.', 'jetpack' ); ?></p>
+ <?php break;
+ case 'success' :
+ echo wpautop( $subscribe_text );
+ break;
+ default : ?>
+ <p class="error"><?php esc_html_e( 'There was an error when subscribing, please try again.', 'jetpack' ) ?></p>
+ <?php break;
endswitch;
endif;
- $email_address = '';
- if ( ! empty( $current_user->user_email ) )
- $email_address = $current_user->user_email;
-
// Display a subscribe form ?>
- <a name="subscribe-blog"></a>
- <form action="" method="post" accept-charset="utf-8" id="subscribe-blog">
+ <form action="" method="post" accept-charset="utf-8" id="subscribe-blog-<?php echo !empty( $args['widget_id'] ) ? esc_attr( $args['widget_id'] ) : mt_rand( 450, 550 ); ?>">
<?php
if ( ! isset ( $_GET['subscribe'] ) ) {
?><p><?php echo $subscribe_text ?></p><?php
}
- if ( $show_subscribers_total && $subscribers_total['value'] > 0 ) {
+ if ( $show_subscribers_total && 0 < $subscribers_total['value'] ) {
echo wpautop( sprintf( _n( 'Join %s other subscriber', 'Join %s other subscribers', $subscribers_total['value'], 'jetpack' ), number_format_i18n( $subscribers_total['value'] ) ) );
}
?>
- <p><input type="text" name="email" style="width: 95%; padding: 1px 2px" value="<?php if ( !empty( $email_address ) ) { echo $email_address; } else { _e( 'Email Address', 'jetpack' ); } ?>" id="subscribe-field" onclick="if ( this.value == '<?php _e( 'Email Address', 'jetpack' ) ?>' ) { this.value = ''; }" onblur="if ( this.value == '' ) { this.value = '<?php _e( 'Email Address', 'jetpack' ) ?>'; }" /></p>
+ <p><input type="text" name="email" style="width: 95%; padding: 1px 2px" value="<?php echo !empty( $current_user->user_email ) ? esc_attr( $current_user->user_email ) : esc_html__( 'Email Address', 'jetpack' ); ?>" id="subscribe-field" onclick="if ( this.value == '<?php esc_html_e( 'Email Address', 'jetpack' ) ?>' ) { this.value = ''; }" onblur="if ( this.value == '' ) { this.value = '<?php esc_html_e( 'Email Address', 'jetpack' ) ?>'; }" /></p>
<p>
<input type="hidden" name="action" value="subscribe" />
<input type="hidden" name="source" value="<?php echo esc_url( $referer ); ?>" />
<input type="hidden" name="sub-type" value="<?php echo esc_attr( $source ); ?>" />
<input type="hidden" name="redirect_fragment" value="<?php echo esc_attr( $widget_id ); ?>" />
- <?php wp_nonce_field( 'blogsub_subscribe_'. get_current_blog_id(), '_wpnonce', false ); ?>
+ <?php
+ if ( is_user_logged_in() ) {
+ wp_nonce_field( 'blogsub_subscribe_'. get_current_blog_id(), '_wpnonce', false );
+ }
+ ?>
<input type="submit" value="<?php echo esc_attr( $subscribe_button ); ?>" name="jetpack_subscriptions_widget" />
</p>
</form>
<?php
- echo "\n" . $after_widget;
+ echo "\n" . $args['after_widget'];
}
function increment_subscriber_count( $current_subs_array = array() ) {
@@ -610,7 +621,7 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
Jetpack:: load_xml_rpc_client();
$xml = new Jetpack_IXR_Client( array(
- 'user_id' => $GLOBALS['current_user']->ID
+ 'user_id' => JETPACK_MASTER_USER,
) );
$xml->query( 'jetpack.fetchSubscriberCount' );
@@ -638,10 +649,10 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
function update( $new_instance, $old_instance ) {
$instance = $old_instance;
- $instance['title'] = strip_tags( stripslashes( $new_instance['title'] ) );
+ $instance['title'] = wp_kses( stripslashes( $new_instance['title'] ), array() );
$instance['subscribe_text'] = wp_filter_post_kses( stripslashes( $new_instance['subscribe_text'] ) );
$instance['subscribe_logged_in'] = wp_filter_post_kses( stripslashes( $new_instance['subscribe_logged_in'] ) );
- $instance['subscribe_button'] = strip_tags( stripslashes( $new_instance['subscribe_button'] ) );
+ $instance['subscribe_button'] = wp_kses( stripslashes( $new_instance['subscribe_button'] ), array() );
$instance['show_subscribers_total'] = isset( $new_instance['show_subscribers_total'] ) && $new_instance['show_subscribers_total'];
return $instance;
@@ -649,10 +660,10 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
function defaults() {
return array(
- 'title' => __( 'Subscribe to Blog via Email', 'jetpack' ),
- 'subscribe_text' => __( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
- 'subscribe_button' => __( 'Subscribe', 'jetpack' ),
- 'subscribe_logged_in' => __( 'Click to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
+ 'title' => esc_html__( 'Subscribe to Blog via Email', 'jetpack' ),
+ 'subscribe_text' => esc_html__( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
+ 'subscribe_button' => esc_html__( 'Subscribe', 'jetpack' ),
+ 'subscribe_logged_in' => esc_html__( 'Click to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
'show_subscribers_total' => true,
);
}
@@ -660,9 +671,9 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
function form( $instance ) {
$instance = wp_parse_args( (array) $instance, $this->defaults() );
- $title = esc_attr( stripslashes( $instance['title'] ) );
- $subscribe_text = esc_attr( stripslashes( $instance['subscribe_text'] ) );
- $subscribe_button = esc_attr( stripslashes( $instance['subscribe_button'] ) );
+ $title = stripslashes( $instance['title'] );
+ $subscribe_text = stripslashes( $instance['subscribe_text'] );
+ $subscribe_button = stripslashes( $instance['subscribe_button'] );
$show_subscribers_total = checked( $instance['show_subscribers_total'], true, false );
$subs_fetch = $this->fetch_subscriber_count();
@@ -702,3 +713,13 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
}
}
+add_shortcode( 'jetpack_subscription_form', 'jetpack_do_subscription_form' );
+
+function jetpack_do_subscription_form( $args ) {
+ $args['show_subscribers_total'] = empty( $args['show_subscribers_total'] ) ? false : true;
+ $args = shortcode_atts( Jetpack_Subscriptions_Widget::defaults(), $args );
+ ob_start();
+ the_widget( 'Jetpack_Subscriptions_Widget', $args );
+ $output = ob_get_clean();
+ return $output;
+}
diff --git a/plugins/jetpack/modules/tiled-gallery.php b/plugins/jetpack/modules/tiled-gallery.php
new file mode 100644
index 00000000..6db87144
--- /dev/null
+++ b/plugins/jetpack/modules/tiled-gallery.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * Module Name: Tiled Galleries
+ * Module Description: Create elegant magazine-style mosaic layouts for your photos without using an external graphic editor.
+ * First Introduced: 2.1
+ */
+
+function jetpack_load_tiled_gallery() {
+ include dirname( __FILE__ ) . "/tiled-gallery/tiled-gallery.php";
+}
+
+add_action( 'jetpack_modules_loaded', 'jetpack_tiled_gallery_loaded' );
+
+function jetpack_tiled_gallery_loaded() {
+ Jetpack::enable_module_configurable( __FILE__ );
+ Jetpack::module_configuration_load( __FILE__, 'jetpack_tiled_gallery_configuration_load' );
+}
+
+function jetpack_tiled_gallery_configuration_load() {
+ wp_safe_redirect( admin_url( 'options-media.php' ) );
+ exit;
+}
+
+jetpack_load_tiled_gallery(); \ No newline at end of file
diff --git a/plugins/jetpack/modules/tiled-gallery/math/class-constrained-array-rounding.php b/plugins/jetpack/modules/tiled-gallery/math/class-constrained-array-rounding.php
new file mode 100644
index 00000000..dab5fd27
--- /dev/null
+++ b/plugins/jetpack/modules/tiled-gallery/math/class-constrained-array-rounding.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * Lets you round the numeric elements of an array to integers while preserving their sum.
+ *
+ * Usage:
+ *
+ * Jetpack_Constrained_Array_Rounding::get_rounded_constrained_array( $bound_array )
+ * if a specific sum doesn't need to be specified for the bound array
+ *
+ * Jetpack_Constrained_Array_Rounding::get_rounded_constrained_array( $bound_array, $sum )
+ * If the sum of $bound_array must equal $sum after rounding.
+ *
+ * If $sum is less than the sum of the floor of the elements of the array, the class defaults to using the sum of the array elements.
+ */
+class Jetpack_Constrained_Array_Rounding {
+ public static function get_rounded_constrained_array( $bound_array, $sum = false ) {
+ // Convert associative arrays before working with them and convert them back before returning the values
+ $keys = array_keys( $bound_array );
+ $bound_array = array_values( $bound_array );
+
+ $bound_array_int = self::get_int_floor_array( $bound_array );
+
+ $lower_sum = array_sum( wp_list_pluck( $bound_array_int, 'floor' ) );
+ if ( ! $sum || ( $sum < $lower_sum ) ) {
+ // If value of sum is not supplied or is invalid, calculate the sum that the returned array is constrained to match
+ $sum = array_sum( $bound_array );
+ }
+ $diff_sum = $sum - $lower_sum;
+
+ self::adjust_constrained_array( $bound_array_int, $diff_sum );
+
+ $bound_array_fin = wp_list_pluck( $bound_array_int, 'floor' );
+ return array_combine( $keys, $bound_array_fin );
+ }
+
+ private static function get_int_floor_array( $bound_array ) {
+ $bound_array_int_floor = array();
+ foreach ( $bound_array as $i => $value ){
+ $bound_array_int_floor[$i] = array(
+ 'floor' => (int) floor( $value ),
+ 'fraction' => $value - floor( $value ),
+ 'index' => $i,
+ );
+ }
+
+ return $bound_array_int_floor;
+ }
+
+ private static function adjust_constrained_array( &$bound_array_int, $adjustment ) {
+ usort( $bound_array_int, array( 'self', 'cmp_desc_fraction' ) );
+
+ $start = 0;
+ $end = $adjustment - 1;
+ $length = count( $bound_array_int );
+
+ for ( $i = $start; $i <= $end; $i++ ) {
+ $bound_array_int[ $i % $length ]['floor']++;
+ }
+
+ usort( $bound_array_int, array( 'self', 'cmp_asc_index' ) );
+ }
+
+ private static function cmp_desc_fraction( $a, $b ) {
+ if ( $a['fraction'] == $b['fraction'] )
+ return 0;
+ return $a['fraction'] > $b['fraction'] ? -1 : 1;
+ }
+
+ private static function cmp_asc_index( $a, $b ) {
+ if ( $a['index'] == $b['index'] )
+ return 0;
+ return $a['index'] < $b['index'] ? -1 : 1;
+ }
+}
diff --git a/plugins/jetpack/modules/tiled-gallery/tiled-gallery.php b/plugins/jetpack/modules/tiled-gallery/tiled-gallery.php
new file mode 100644
index 00000000..342e8a65
--- /dev/null
+++ b/plugins/jetpack/modules/tiled-gallery/tiled-gallery.php
@@ -0,0 +1,588 @@
+<?php
+
+// Include the class file containing methods for rounding constrained array elements.
+// Here the constrained array element is the dimension of a row, group or an image in the tiled gallery.
+include_once dirname( __FILE__ ) . '/math/class-constrained-array-rounding.php';
+
+class Jetpack_Tiled_Gallery {
+
+ public function __construct() {
+ add_action( 'admin_init', array( $this, 'settings_api_init' ) );
+ add_filter( 'jetpack_gallery_types', array( $this, 'jetpack_gallery_types' ), 9 );
+ }
+
+ public function tiles_enabled() {
+ // Check the setting status
+ return '' != get_option( 'tiled_galleries' );
+ }
+
+ public function set_atts( $atts ) {
+ global $post;
+
+ $this->atts = shortcode_atts( array(
+ 'order' => 'ASC',
+ 'orderby' => 'menu_order ID',
+ 'id' => $post->ID,
+ 'include' => '',
+ 'exclude' => '',
+ 'type' => '',
+ 'grayscale' => false,
+ 'link' => '',
+ ), $atts );
+
+ $this->atts['id'] = (int) $this->atts['id'];
+ $this->float = is_rtl() ? 'right' : 'left';
+
+ // Default to rectangular is tiled galleries are checked
+ if ( $this->tiles_enabled() && ( ! $this->atts['type'] || 'default' == $this->atts['type'] ) )
+ $this->atts['type'] = 'rectangular';
+
+ if ( !$this->atts['orderby'] ) {
+ $this->atts['orderby'] = sanitize_sql_orderby( $this->atts['orderby'] );
+ if ( !$this->atts['orderby'] )
+ $this->atts['orderby'] = 'menu_order ID';
+ }
+
+ if ( 'RAND' == $this->atts['order'] )
+ $this->atts['orderby'] = 'none';
+ }
+
+ public function get_attachments() {
+ extract( $this->atts );
+
+ if ( !empty( $include ) ) {
+ $include = preg_replace( '/[^0-9,]+/', '', $include );
+ $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
+
+ $attachments = array();
+ foreach ( $_attachments as $key => $val ) {
+ $attachments[$val->ID] = $_attachments[$key];
+ }
+ } elseif ( !empty( $exclude ) ) {
+ $exclude = preg_replace( '/[^0-9,]+/', '', $exclude );
+ $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
+ } else {
+ $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby ) );
+ }
+ return $attachments;
+ }
+
+ public function get_attachment_link( $attachment_id, $orig_file ) {
+ if ( isset( $this->atts['link'] ) && $this->atts['link'] == 'file' )
+ return $orig_file;
+ else
+ return get_attachment_link( $attachment_id );
+ }
+
+ public function default_scripts_and_styles() {
+ wp_enqueue_script( 'tiled-gallery', plugins_url( 'tiled-gallery/tiled-gallery.js', __FILE__ ), array( 'jquery' ) );
+ wp_enqueue_style( 'tiled-gallery', plugins_url( 'tiled-gallery/tiled-gallery.css', __FILE__ ), array(), '2012-09-21' );
+ }
+
+ public function gallery_shortcode( $val, $atts ) {
+ if ( ! empty( $val ) ) // something else is overriding post_gallery, like a custom VIP shortcode
+ return $val;
+
+ global $post;
+
+ $this->set_atts( $atts );
+
+ $attachments = $this->get_attachments();
+ if ( empty( $attachments ) )
+ return '';
+
+ if ( is_feed() || defined( 'IS_HTML_EMAIL' ) )
+ return '';
+
+ if ( method_exists( $this, $this->atts['type'] . '_talavera' ) ) {
+ // Enqueue styles and scripts
+ $this->default_scripts_and_styles();
+ $gallery_html = call_user_func_array( array( $this, $this->atts['type'] . '_talavera' ), array( $attachments ) );
+
+ if ( $gallery_html && class_exists( 'Jetpack' ) && class_exists( 'Jetpack_Photon' ) ) {
+ // Tiled Galleries in Jetpack require that Photon be active.
+ // If it's not active, run it just on the gallery output.
+ if ( ! in_array( 'photon', Jetpack::get_active_modules() ) )
+ $gallery_html = Jetpack_Photon::filter_the_content( $gallery_html );
+ }
+
+ return $gallery_html;
+ }
+
+ return '';
+ }
+
+ public function rectangular_talavera( $attachments ) {
+ $grouper = new Jetpack_Tiled_Gallery_Grouper( $attachments );
+
+ Jetpack_Tiled_Gallery_Shape::reset_last_shape();
+
+ $output = $this->generate_carousel_container();
+ foreach ( $grouper->grouped_images as $row ) {
+ $output .= '<div class="gallery-row" style="' . esc_attr( 'width: ' . $row->width . 'px; height: ' . ( $row->height - 4 ) . 'px;' ) . '">';
+ foreach( $row->groups as $group ) {
+ $count = count( $group->images );
+ $output .= '<div class="gallery-group images-' . esc_attr( $count ) . '" style="' . esc_attr( 'width: ' . $group->width . 'px; height: ' . $group->height . 'px;' ) . '">';
+ foreach ( $group->images as $image ) {
+
+ $size = 'large';
+ if ( $image->width < 250 )
+ $size = 'small';
+
+ $image_title = $image->post_title;
+ $orig_file = wp_get_attachment_url( $image->ID );
+ $link = $this->get_attachment_link( $image->ID, $orig_file );
+
+ $img_src = add_query_arg( array( 'w' => $image->width, 'h' => $image->height ), $orig_file );
+
+ $output .= '<div class="tiled-gallery-item tiled-gallery-item-' . esc_attr( $size ) . '"><a href="' . esc_url( $link ) . '"><img ' . $this->generate_carousel_image_args( $image ) . ' src="' . esc_url( $img_src ) . '" width="' . esc_attr( $image->width ) . '" height="' . esc_attr( $image->height ) . '" align="left" title="' . esc_attr( $image_title ) . '" /></a>';
+
+ if ( $this->atts['grayscale'] == true ) {
+ $img_src_grayscale = jetpack_photon_url( $img_src, array( 'filter' => 'grayscale' ) );
+ $output .= '<a href="'. esc_url( $link ) . '"><img ' . $this->generate_carousel_image_args( $image ) . ' class="grayscale" src="' . esc_url( $img_src_grayscale ) . '" width="' . esc_attr( $image->width ) . '" height="' . esc_attr( $image->height ) . '" align="left" title="' . esc_attr( $image_title ) . '" /></a>';
+ }
+
+ if ( trim( $image->post_excerpt ) )
+ $output .= '<div class="tiled-gallery-caption">' . wptexturize( $image->post_excerpt ) . '</div>';
+
+ $output .= '</div>';
+ }
+ $output .= '</div>';
+ }
+ $output .= '</div>';
+ }
+ $output .= '</div>';
+ return $output;
+ }
+
+ public function square_talavera( $attachments ) {
+ $content_width = self::get_content_width();
+ $images_per_row = 3;
+ $margin = 2;
+
+ $margin_space = ( $images_per_row * $margin ) * 2;
+ $size = floor( ( $content_width - $margin_space ) / $images_per_row );
+ $remainder = count( $attachments ) % $images_per_row;
+ if ( $remainder > 0 ) {
+ $remainder_space = ( $remainder * $margin ) * 2;
+ $remainder_size = ceil( ( $content_width - $remainder_space - $margin ) / $remainder );
+ }
+ $output = $this->generate_carousel_container();
+ $c = 1;
+ foreach( $attachments as $image ) {
+ if ( $remainder > 0 && $c <= $remainder )
+ $img_size = $remainder_size;
+ else
+ $img_size = $size;
+
+ $orig_file = wp_get_attachment_url( $image->ID );
+ $link = $this->get_attachment_link( $image->ID, $orig_file );
+ $image_title = $image->post_title;
+
+ $img_src = add_query_arg( array( 'w' => $img_size, 'h' => $img_size, 'crop' => 1 ), $orig_file );
+
+ $output .= '<div class="tiled-gallery-item">';
+ $output .= '<a border="0" href="' . esc_url( $link ) . '"><img ' . $this->generate_carousel_image_args( $image ) . ' style="' . esc_attr( 'margin: ' . $margin . 'px' ) . '" src="' . esc_url( $img_src ) . '" width=' . esc_attr( $img_size ) . ' height=' . esc_attr( $img_size ) . ' title="' . esc_attr( $image_title ) . '" /></a>';
+
+ // Grayscale effect
+ if ( $this->atts['grayscale'] == true ) {
+ $src = urlencode( $image->guid );
+ $output .= '<a border="0" href="' . esc_url( $link ) . '"><img ' . $this->generate_carousel_image_args( $image ) . ' style="margin: 2px" class="grayscale" src="' . esc_url( 'http://en.wordpress.com/imgpress?url=' . urlencode( $image->guid ) . '&resize=' . $img_size . ',' . $img_size . '&filter=grayscale' ) . '" width=' . esc_attr( $img_size ) . ' height=' . esc_attr( $img_size ) . ' title="' . esc_attr( $image_title ) . '" /></a>';
+ }
+
+ // Captions
+ if ( trim( $image->post_excerpt ) )
+ $output .= '<div class="tiled-gallery-caption">' . wptexturize( $image->post_excerpt ) . '</div>';
+ $output .= '</div>';
+ $c ++;
+ }
+ $output .= '</div>';
+ return $output;
+ }
+
+ public function circle_talavera( $attachments ) {
+ return $this->square_talavera( $attachments );
+ }
+
+ public function rectangle_talavera( $attachments ) {
+ return $this->rectangular_talavera( $attachments );
+ }
+
+ function generate_carousel_container() {
+ global $post;
+
+ $html = '<div '. $this->gallery_classes() . ' data-original-width="' . esc_attr( self::get_content_width() ) . '">';
+ $blog_id = (int) get_current_blog_id();
+ $extra_data = array( 'data-carousel-extra' => array( 'blog_id' => $blog_id, 'permalink' => get_permalink( $post->ID ) ) );
+
+ foreach ( (array) $extra_data as $data_key => $data_values ) {
+ $html = str_replace( '<div ', '<div ' . esc_attr( $data_key ) . "='" . json_encode( $data_values ) . "' ", $html );
+ }
+
+ return $html;
+ }
+
+ function generate_carousel_image_args( $image ) {
+ $attachment_id = $image->ID;
+ $orig_file = wp_get_attachment_url( $attachment_id );
+ $meta = wp_get_attachment_metadata( $attachment_id );
+ $size = isset( $meta['width'] ) ? intval( $meta['width'] ) . ',' . intval( $meta['height'] ) : '';
+ $img_meta = ( ! empty( $meta['image_meta'] ) ) ? (array) $meta['image_meta'] : array();
+ $comments_opened = intval( comments_open( $attachment_id ) );
+
+ $medium_file_info = wp_get_attachment_image_src( $attachment_id, 'medium' );
+ $medium_file = isset( $medium_file_info[0] ) ? $medium_file_info[0] : '';
+
+ $large_file_info = wp_get_attachment_image_src( $attachment_id, 'large' );
+ $large_file = isset( $large_file_info[0] ) ? $large_file_info[0] : '';
+ $attachment_title = wptexturize( $image->post_title );
+ $attachment_desc = wpautop( wptexturize( $image->post_content ) );
+
+ // Not yet providing geo-data, need to "fuzzify" for privacy
+ if ( ! empty( $img_meta ) ) {
+ foreach ( $img_meta as $k => $v ) {
+ if ( 'latitude' == $k || 'longitude' == $k )
+ unset( $img_meta[$k] );
+ }
+ }
+
+ $img_meta = json_encode( array_map( 'strval', $img_meta ) );
+
+ $output = sprintf(
+ 'data-attachment-id="%1$d" data-orig-file="%2$s" data-orig-size="%3$s" data-comments-opened="%4$s" data-image-meta="%5$s" data-image-title="%6$s" data-image-description="%7$s" data-medium-file="%8$s" data-large-file="%9$s"',
+ esc_attr( $attachment_id ),
+ esc_url( wp_get_attachment_url( $attachment_id ) ),
+ esc_attr( $size ),
+ esc_attr( $comments_opened ),
+ esc_attr( $img_meta ),
+ esc_attr( $attachment_title ),
+ esc_attr( $attachment_desc ),
+ esc_url( $medium_file ),
+ esc_url( $large_file )
+ );
+ return $output;
+ }
+
+ public function gallery_classes() {
+ $classes = 'class="tiled-gallery type-' . esc_attr( $this->atts['type'] ) . '"';
+ return $classes;
+ }
+
+ public static function gallery_already_redefined() {
+ global $shortcode_tags;
+ if ( ! isset( $shortcode_tags[ 'gallery' ] ) || $shortcode_tags[ 'gallery' ] !== 'gallery_shortcode' )
+ return true;
+ }
+
+ public static function init() {
+ if ( self::gallery_already_redefined() )
+ return;
+
+ $gallery = new Jetpack_Tiled_Gallery;
+ add_filter( 'post_gallery', array( $gallery, 'gallery_shortcode' ), 1001, 2 );
+ }
+
+ public static function get_content_width() {
+ global $content_width;
+
+ $tiled_gallery_content_width = $content_width;
+
+ if ( ! $tiled_gallery_content_width )
+ $tiled_gallery_content_width = 500;
+
+ return apply_filters( 'tiled_gallery_content_width', $tiled_gallery_content_width );
+ }
+
+ /**
+ * Media UI integration
+ */
+ function jetpack_gallery_types( $types ) {
+ $types['rectangular'] = __( 'Tiles', 'jetpack' );
+ $types['square'] = __( 'Square Tiles', 'jetpack' );
+ $types['circle'] = __( 'Circles', 'jetpack' );
+ return $types;
+ }
+
+ /**
+ * Add a checkbox field to the Carousel section in Settings > Media
+ * for setting tiled galleries as the default.
+ */
+ function settings_api_init() {
+ global $wp_settings_sections;
+
+ // Add the setting field [tiled_galleries] and place it in Settings > Media
+ if ( isset( $wp_settings_sections['media']['carousel_section'] ) )
+ $section = 'carousel_section';
+ else
+ $section = 'default';
+
+ add_settings_field( 'tiled_galleries', __( 'Tiled Galleries', 'jetpack' ), array( $this, 'setting_html' ), 'media', $section );
+ register_setting( 'media', 'tiled_galleries', 'esc_attr' );
+ }
+
+ function setting_html() {
+ echo '<label><input name="tiled_galleries" type="checkbox" value="1" ' .
+ checked( 1, '' != get_option( 'tiled_galleries' ), false ) . ' /> ' .
+ __( 'Display all your gallery pictures in a cool mosaic.', 'jetpack' ) . '</br></label>';
+ }
+}
+
+class Jetpack_Tiled_Gallery_Shape {
+ static $shapes_used = array();
+
+ public function __construct( $images ) {
+ $this->images = $images;
+ $this->images_left = count( $images );
+ }
+
+ public function sum_ratios( $number_of_images = 3 ) {
+ return array_sum( array_slice( wp_list_pluck( $this->images, 'ratio' ), 0, $number_of_images ) );
+ }
+
+ public function next_images_are_symmetric() {
+ return $this->images_left > 2 && $this->images[0]->ratio == $this->images[2]->ratio;
+ }
+
+ public function is_not_as_previous( $n = 1 ) {
+ return ! in_array( get_class( $this ), array_slice( self::$shapes_used, -$n ) );
+ }
+
+ public function is_wide_theme() {
+ global $content_width;
+ return $content_width > 1000;
+ }
+
+ public static function set_last_shape( $last_shape ) {
+ self::$shapes_used[] = $last_shape;
+ }
+
+ public static function reset_last_shape() {
+ self::$shapes_used = array();
+ }
+}
+
+class Jetpack_Tiled_Gallery_Three extends Jetpack_Tiled_Gallery_Shape {
+ public $shape = array( 1, 1, 1 );
+
+ public function is_possible() {
+ $ratio = $this->sum_ratios( 3 );
+ return $this->images_left > 2 && $this->is_not_as_previous() &&
+ ( ( $ratio < 2.5 ) || ( $ratio < 5 && $this->next_images_are_symmetric() ) || $this->is_wide_theme() );
+ }
+}
+
+class Jetpack_Tiled_Gallery_Four extends Jetpack_Tiled_Gallery_Shape {
+ public $shape = array( 1, 1, 1, 1 );
+
+ public function is_possible() {
+ return $this->is_not_as_previous() && $this->sum_ratios( 4 ) < 3.5 &&
+ ( $this->images_left == 4 || ( $this->images_left != 8 && $this->images_left > 5 ) );
+ }
+}
+
+class Jetpack_Tiled_Gallery_Five extends Jetpack_Tiled_Gallery_Shape {
+ public $shape = array( 1, 1, 1, 1, 1 );
+
+ public function is_possible() {
+ return $this->is_wide_theme() && $this->is_not_as_previous() && $this->sum_ratios( 5 ) < 5 &&
+ ( $this->images_left == 5 || ( $this->images_left != 10 && $this->images_left > 6 ) );
+ }
+}
+
+class Jetpack_Tiled_Gallery_Two_One extends Jetpack_Tiled_Gallery_Shape {
+ public $shape = array( 2, 1 );
+
+ public function is_possible() {
+ return $this->is_not_as_previous( 3 ) && $this->images_left >= 2 &&
+ $this->images[2]->ratio < 1.6 && $this->images[0]->ratio >=0.9 && $this->images[1]->ratio >= 0.9;
+ }
+}
+
+class Jetpack_Tiled_Gallery_One_Two extends Jetpack_Tiled_Gallery_Shape {
+ public $shape = array( 1, 2 );
+
+ public function is_possible() {
+ return $this->is_not_as_previous( 3 ) && $this->images_left >= 2 &&
+ $this->images[0]->ratio < 1.6 && $this->images[1]->ratio >=0.9 && $this->images[2]->ratio >= 0.9;
+ }
+}
+
+class Jetpack_Tiled_Gallery_One_Three extends Jetpack_Tiled_Gallery_Shape {
+ public $shape = array( 1, 3 );
+
+ public function is_possible() {
+ return $this->is_not_as_previous() && $this->images_left >= 3 &&
+ $this->images[0]->ratio < 0.8 && $this->images[1]->ratio >=0.9 && $this->images[2]->ratio >= 0.9 && $this->images[3]->ratio >= 0.9;
+ }
+}
+
+class Jetpack_Tiled_Gallery_Symmetric_Row extends Jetpack_Tiled_Gallery_Shape {
+ public $shape = array( 1, 2, 1 );
+
+ public function is_possible() {
+ return $this->is_not_as_previous() && $this->images_left >= 3 && $this->images_left != 5 &&
+ $this->images[0]->ratio < 0.8 && $this->images[0]->ratio == $this->images[3]->ratio;
+ }
+}
+
+class Jetpack_Tiled_Gallery_Grouper {
+ public $margin = 4;
+ public function __construct( $attachments ) {
+ $content_width = Jetpack_Tiled_Gallery::get_content_width();
+ $ua_info = new Jetpack_User_Agent_Info();
+
+ $this->last_shape = '';
+ $this->images = $this->get_images_with_sizes( $attachments );
+ $this->grouped_images = $this->get_grouped_images();
+ $this->apply_content_width( $content_width - 5 ); //reduce the margin hack to 5px. It will be further reduced when we fix more themes and the rounding error.
+ }
+
+ public function get_current_row_size() {
+ $images_left = count( $this->images );
+ if ( $images_left < 3 )
+ return array_fill( 0, $images_left, 1 );
+
+ foreach ( array( 'One_Three', 'One_Two', 'Five', 'Four', 'Three', 'Two_One', 'Symmetric_Row' ) as $shape_name ) {
+ $class_name = "Jetpack_Tiled_Gallery_$shape_name";
+ $shape = new $class_name( $this->images );
+ if ( $shape->is_possible() ) {
+ Jetpack_Tiled_Gallery_Shape::set_last_shape( $class_name );
+ return $shape->shape;
+ }
+ }
+
+ Jetpack_Tiled_Gallery_Shape::set_last_shape( 'Two' );
+ return array( 1, 1 );
+ }
+
+ public function get_images_with_sizes( $attachments ) {
+ $images_with_sizes = array();
+
+ foreach ( $attachments as $image ) {
+ $meta = wp_get_attachment_metadata( $image->ID );
+ $image->width_orig = ( $meta['width'] > 0 )? $meta['width'] : 1;
+ $image->height_orig = ( $meta['height'] > 0 )? $meta['height'] : 1;
+ $image->ratio = $image->width_orig / $image->height_orig;
+ $image->ratio = $image->ratio? $image->ratio : 1;
+ $images_with_sizes[] = $image;
+ }
+
+ return $images_with_sizes;
+ }
+
+ public function read_row() {
+ $vector = $this->get_current_row_size();
+
+ $row = array();
+ foreach ( $vector as $group_size ) {
+ $row[] = new Jetpack_Tiled_Gallery_Group( array_splice( $this->images, 0, $group_size ) );
+ }
+
+ return $row;
+ }
+
+ public function get_grouped_images() {
+ $grouped_images = array();
+
+ while( !empty( $this->images ) ) {
+ $grouped_images[] = new Jetpack_Tiled_Gallery_Row( $this->read_row() );
+ }
+
+ return $grouped_images;
+ }
+
+ // todo: split in functions
+ // todo: do not stretch images
+ public function apply_content_width( $width ) {
+ foreach ( $this->grouped_images as $row ) {
+ $row->width = $width;
+ $row->raw_height = 1 / $row->ratio * ( $width - $this->margin * ( count( $row->groups ) - $row->weighted_ratio ) );
+ $row->height = round( $row->raw_height );
+
+ $this->calculate_group_sizes( $row );
+ }
+ }
+
+ public function calculate_group_sizes( $row ) {
+ // Storing the calculated group heights in an array for rounding them later while preserving their sum
+ // This fixes the rounding error that can lead to a few ugly pixels sticking out in the gallery
+ $group_widths_array = array();
+ foreach ( $row->groups as $group ) {
+ $group->height = $row->height;
+ // Storing the raw calculations in a separate property to prevent rounding errors from cascading down and for diagnostics
+ $group->raw_width = ( $row->raw_height - $this->margin * count( $group->images ) ) * $group->ratio + $this->margin;
+ $group_widths_array[] = $group->raw_width;
+ }
+ $rounded_group_widths_array = Jetpack_Constrained_Array_Rounding::get_rounded_constrained_array( $group_widths_array, $row->width );
+
+ foreach ( $row->groups as $group ) {
+ $group->width = array_shift( $rounded_group_widths_array );
+ $this->calculate_image_sizes( $group );
+ }
+ }
+
+ public function calculate_image_sizes( $group ) {
+ // Storing the calculated image heights in an array for rounding them later while preserving their sum
+ // This fixes the rounding error that can lead to a few ugly pixels sticking out in the gallery
+ $image_heights_array = array();
+ foreach ( $group->images as $image ) {
+ $image->width = $group->width - $this->margin;
+ // Storing the raw calculations in a separate property for diagnostics
+ $image->raw_height = ( $group->raw_width - $this->margin ) / $image->ratio;
+ $image_heights_array[] = $image->raw_height;
+ }
+
+ $image_height_sum = $group->height - count( $image_heights_array ) * $this->margin;
+ $rounded_image_heights_array = Jetpack_Constrained_Array_Rounding::get_rounded_constrained_array( $image_heights_array, $image_height_sum );
+
+ foreach ( $group->images as $image ) {
+ $image->height = array_shift( $rounded_image_heights_array );
+ }
+ }
+}
+
+class Jetpack_Tiled_Gallery_Row {
+ public function __construct( $groups ) {
+ $this->groups = $groups;
+ $this->ratio = $this->get_ratio();
+ $this->weighted_ratio = $this->get_weighted_ratio();
+ }
+
+ public function get_ratio() {
+ $ratio = 0;
+ foreach ( $this->groups as $group ) {
+ $ratio += $group->ratio;
+ }
+ return $ratio > 0? $ratio : 1;
+ }
+
+ public function get_weighted_ratio() {
+ $weighted_ratio = 0;
+ foreach ( $this->groups as $group ) {
+ $weighted_ratio += $group->ratio * count( $group->images );
+ }
+ return $weighted_ratio > 0 ? $weighted_ratio : 1;
+ }
+}
+
+class Jetpack_Tiled_Gallery_Group {
+ public function __construct( $images ) {
+ $this->images = $images;
+ $this->ratio = $this->get_ratio();
+ }
+
+ public function get_ratio() {
+ $ratio = 0;
+ foreach ( $this->images as $image ) {
+ if ( $image->ratio )
+ $ratio += 1/$image->ratio;
+ }
+ if ( !$ratio )
+ return 1;
+
+ return 1/$ratio;
+ }
+}
+
+add_action( 'init', array( 'Jetpack_Tiled_Gallery', 'init' ) );
+
diff --git a/plugins/jetpack/modules/tiled-gallery/tiled-gallery/rtl/tiled-gallery-rtl.css b/plugins/jetpack/modules/tiled-gallery/tiled-gallery/rtl/tiled-gallery-rtl.css
new file mode 100644
index 00000000..007c0ccf
--- /dev/null
+++ b/plugins/jetpack/modules/tiled-gallery/tiled-gallery/rtl/tiled-gallery-rtl.css
@@ -0,0 +1,88 @@
+/* This file was automatically generated on Jan 05 2013 15:45:53 */
+
+/* =Tiled Gallery Default Styles
+-------------------------------------------------------------- */
+
+.tiled-gallery {
+ clear: both;
+ margin: 0;
+ overflow: hidden;
+}
+.tiled-gallery img {
+ margin: 2px !important; /* Ensure that this value isn't overridden by themes that give content images blanket margins */
+}
+.tiled-gallery .gallery-group {
+ float: right;
+ overflow-y: hidden;
+ position: relative;
+}
+.tiled-gallery .tiled-gallery-item {
+ float: right;
+ margin: 0;
+ position: relative;
+}
+.tiled-gallery .gallery-row {
+ overflow: hidden;
+ margin-bottom: 2px;
+}
+.tiled-gallery .tiled-gallery-item a { /* Needs to reset some properties for theme compatibility */
+ background: transparent;
+ border: none;
+ color: none;
+ margin: 0;
+ padding: 0;
+ text-decoration: none;
+ width: auto;
+}
+.tiled-gallery .tiled-gallery-item img,
+.tiled-gallery .tiled-gallery-item img:hover { /* Needs to reset some properties for theme compatibility */
+ background: none;
+ border: none;
+ box-shadow: none;
+ max-width: 100%;
+ padding: 0;
+ vertical-align: middle;
+}
+.tiled-gallery-caption { /* Captions */
+ background: #eee;
+ background: rgba( 255,255,255,0.8 );
+ color: #333;
+ font-size: 13px;
+ font-weight: 400;
+ overflow: hidden;
+ padding: 10px 0;
+ position: absolute;
+ bottom: 0;
+ text-indent: 10px;
+ text-overflow: ellipsis;
+ width: 100%;
+ white-space: nowrap;
+}
+.tiled-gallery .tiled-gallery-item-small .tiled-gallery-caption { /* Smaller captions */
+ font-size: 11px;
+}
+
+
+/* =Greyscale
+-------------------------------------------------------------- */
+
+.tiled-gallery .tiled-gallery-item img.grayscale {
+ position: absolute;
+ right: 0;
+ top: 0;
+}
+.tiled-gallery .tiled-gallery-item img.grayscale:hover {
+ opacity: 0;
+}
+
+
+/* =Circles Layout
+-------------------------------------------------------------- */
+
+.tiled-gallery.type-circle .tiled-gallery-item img {
+ border-radius: 50% !important; /* Ensure that circles are displayed in themes that add border-radius to all images as a default */
+}
+.tiled-gallery.type-circle .tiled-gallery-caption {
+ display: none;
+ opacity: 0;
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.css b/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.css
new file mode 100644
index 00000000..3a1924df
--- /dev/null
+++ b/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.css
@@ -0,0 +1,85 @@
+/* =Tiled Gallery Default Styles
+-------------------------------------------------------------- */
+
+.tiled-gallery {
+ clear: both;
+ margin: 0;
+ overflow: hidden;
+}
+.tiled-gallery img {
+ margin: 2px !important; /* Ensure that this value isn't overridden by themes that give content images blanket margins */
+}
+.tiled-gallery .gallery-group {
+ float: left;
+ position: relative;
+}
+.tiled-gallery .tiled-gallery-item {
+ float: left;
+ margin: 0;
+ position: relative;
+}
+.tiled-gallery .gallery-row {
+ overflow: hidden;
+ margin-bottom: 2px;
+}
+.tiled-gallery .tiled-gallery-item a { /* Needs to reset some properties for theme compatibility */
+ background: transparent;
+ border: none;
+ color: none;
+ margin: 0;
+ padding: 0;
+ text-decoration: none;
+ width: auto;
+}
+.tiled-gallery .tiled-gallery-item img,
+.tiled-gallery .tiled-gallery-item img:hover { /* Needs to reset some properties for theme compatibility */
+ background: none;
+ border: none;
+ box-shadow: none;
+ max-width: 100%;
+ padding: 0;
+ vertical-align: middle;
+}
+.tiled-gallery-caption { /* Captions */
+ background: #eee;
+ background: rgba( 255,255,255,0.8 );
+ color: #333;
+ font-size: 13px;
+ font-weight: 400;
+ overflow: hidden;
+ padding: 10px 0;
+ position: absolute;
+ bottom: 0;
+ text-indent: 10px;
+ text-overflow: ellipsis;
+ width: 100%;
+ white-space: nowrap;
+}
+.tiled-gallery .tiled-gallery-item-small .tiled-gallery-caption { /* Smaller captions */
+ font-size: 11px;
+}
+
+
+/* =Greyscale
+-------------------------------------------------------------- */
+
+.tiled-gallery .tiled-gallery-item img.grayscale {
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+.tiled-gallery .tiled-gallery-item img.grayscale:hover {
+ opacity: 0;
+}
+
+
+/* =Circles Layout
+-------------------------------------------------------------- */
+
+.tiled-gallery.type-circle .tiled-gallery-item img {
+ border-radius: 50% !important; /* Ensure that circles are displayed in themes that add border-radius to all images as a default */
+}
+.tiled-gallery.type-circle .tiled-gallery-caption {
+ display: none;
+ opacity: 0;
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.js b/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.js
new file mode 100644
index 00000000..90f8ed76
--- /dev/null
+++ b/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.js
@@ -0,0 +1,150 @@
+( function($) {
+
+var TiledGallery = function() {
+ this.resizeTimeout = null;
+
+ this.populate();
+
+ var self = this;
+
+ $( window ).on( 'resize', function () {
+ clearTimeout( self.resizeTimeout );
+
+ self.resizeTimeout = setTimeout( function () { self.resize(); }, 150 );
+ } );
+
+ // Make any new galleries loaded by Infinite Scroll flexible
+ $( 'body' ).on( 'post-load', $.proxy( self.initialize, self ) );
+
+ // Populate and set up captions on newdash galleries.
+ $( document ).on( 'page-rendered.wpcom-newdash', $.proxy( self.populate, self ) );
+
+ this.resize();
+};
+
+TiledGallery.prototype.populate = function() {
+ this.gallery = $( '.tiled-gallery' );
+ this.item = this.gallery.find( '.tiled-gallery-item' );
+ this.caption = this.gallery.find( '.tiled-gallery-caption' );
+
+ this.Captions();
+};
+
+TiledGallery.prototype.initialize = function() {
+ var self = this;
+
+ self.populate();
+
+ // After each image load, run resize in case all images in the gallery are loaded.
+ self.gallery.find( 'img' ).off( 'load.tiled-gallery' ).on( 'load.tiled-gallery', function () {
+ self.resize();
+ } );
+
+ // Run resize now in case all images loaded from cache.
+ self.resize();
+};
+
+/**
+ * Story
+ */
+TiledGallery.prototype.Captions = function() {
+ /* Hide captions */
+ this.caption.hide();
+
+ this.item.on( 'hover', function() {
+ $( this ).find( '.tiled-gallery-caption' ).slideToggle( 'fast' );
+ });
+};
+
+TiledGallery.prototype.resize = function() {
+ var resizeableElements = '.gallery-row, .gallery-group, .tiled-gallery-item img';
+
+ this.gallery.each( function ( galleryIndex, galleryElement ) {
+ var thisGallery = $( galleryElement );
+
+ // All images must be loaded before proceeding.
+ var imagesLoaded = true;
+
+ thisGallery.find( 'img' ).each( function () {
+ if ( ! this.complete ) {
+ imagesLoaded = false;
+ return false;
+ }
+ } );
+
+ if ( ! imagesLoaded ) {
+ var loadCallback = arguments.callee;
+
+ // Once all of the images have loaded,
+ // re-call this containing function.
+ $( window ).load( function () {
+ loadCallback( null, thisGallery );
+ } );
+
+ return;
+ }
+
+ if ( ! thisGallery.data( 'sizes-set' ) ) {
+ // Maintain a record of the original widths and heights of these elements
+ // for proper scaling.
+ thisGallery.data( 'sizes-set', true );
+
+ thisGallery.find( resizeableElements ).each( function () {
+ var thisGalleryElement = $( this );
+
+ // Don't change margins, but remember what they were so they can be
+ // accounted for in size calculations. When the screen width gets
+ // small enough, ignoring the margins can cause images to overflow
+ // into new rows.
+ var extraWidth = ( parseInt( thisGalleryElement.css( 'marginLeft' ), 10 ) || 0 ) + ( parseInt( thisGalleryElement.css( 'marginRight' ), 10 ) || 0 );
+ var extraHeight = ( parseInt( thisGalleryElement.css( 'marginTop' ), 10 ) || 0 ) + ( parseInt( thisGalleryElement.css( 'marginBottom' ), 10 ) || 0 )
+
+ // In some situations, tiled galleries in Firefox have shown scrollbars on the images because
+ // the .outerWidth() call on the image returns a value larger than the container. Restrict
+ // widths used in the resizing functions to the maximum width of the container.
+ var parentElement = $( thisGalleryElement.parents( resizeableElements ).get( 0 ) );
+
+ if ( parentElement && parentElement.data( 'original-width' ) ) {
+ thisGalleryElement
+ .data( 'original-width', Math.min( parentElement.data( 'original-width' ), thisGalleryElement.outerWidth( true ) ) )
+ .data( 'original-height', Math.min( parentElement.data( 'original-height' ), thisGalleryElement.outerHeight( true ) ) );
+ }
+ else {
+ thisGalleryElement
+ .data( 'original-width', thisGalleryElement.outerWidth( true ) )
+ .data( 'original-height', thisGalleryElement.outerHeight( true ) );
+ }
+
+ thisGalleryElement
+ .data( 'extra-width', extraWidth )
+ .data( 'extra-height', extraHeight );
+ } );
+ }
+
+ // Resize everything in the gallery based on the ratio of the current content width
+ // to the original content width;
+ var originalWidth = thisGallery.data( 'original-width' );
+ var currentWidth = thisGallery.parent().width();
+ var resizeRatio = Math.min( 1, currentWidth / originalWidth );
+
+ thisGallery.find( resizeableElements ).each( function () {
+ var thisGalleryElement = $( this );
+
+ thisGalleryElement
+ .width( Math.floor( resizeRatio * thisGalleryElement.data( 'original-width' ) ) - thisGalleryElement.data( 'extra-width' ) )
+ .height( Math.floor( resizeRatio * thisGalleryElement.data( 'original-height' ) ) - thisGalleryElement.data( 'extra-height' ) );
+ } );
+ } );
+};
+
+/**
+ * Ready, set...
+ */
+$( document ).ready( function() {
+
+ // Instance!
+ var TiledGalleryInstance = new TiledGallery;
+
+});
+
+})(jQuery); \ No newline at end of file
diff --git a/plugins/jetpack/modules/widgets.php b/plugins/jetpack/modules/widgets.php
index 3d9c2f8b..5771cdbe 100644
--- a/plugins/jetpack/modules/widgets.php
+++ b/plugins/jetpack/modules/widgets.php
@@ -24,11 +24,22 @@ function jetpack_widgets_configuration_load() {
exit;
}
-function jetpack_register_widgets() {
- register_widget( 'WPCOM_Widget_Facebook_LikeBox' );
- register_widget( 'Jetpack_Gravatar_Profile_Widget' );
+/**
+ * Loads file for front-end widget styles.
+ */
+function jetpack_widgets_styles() {
+ wp_enqueue_style( 'jetpack-widgets', plugins_url( 'widgets/widgets.css', __FILE__ ), array(), '20121003' );
}
+add_action( 'wp_enqueue_scripts', 'jetpack_widgets_styles' );
+
+/**
+ * Add the "(Jetpack)" suffix to the widget names
+ */
+function jetpack_widgets_add_suffix( $widget_name ) {
+ return sprintf( __( '%s (Jetpack)', 'jetpack' ), $widget_name );
+}
+add_filter( 'jetpack_widget_name', 'jetpack_widgets_add_suffix' );
-jetpack_load_widgets();
-add_action( 'widgets_init', 'jetpack_register_widgets' );
+
+jetpack_load_widgets();
diff --git a/plugins/jetpack/modules/widgets/facebook-likebox.php b/plugins/jetpack/modules/widgets/facebook-likebox.php
index 64d03f8a..f8ab2512 100644
--- a/plugins/jetpack/modules/widgets/facebook-likebox.php
+++ b/plugins/jetpack/modules/widgets/facebook-likebox.php
@@ -1,6 +1,15 @@
<?php
/**
+ * Register the widget for use in Appearance -> Widgets
+ */
+add_action( 'widgets_init', 'jetpack_facebook_likebox_init' );
+
+function jetpack_facebook_likebox_init() {
+ register_widget( 'WPCOM_Widget_Facebook_LikeBox' );
+}
+
+/**
* Facebook Like Box widget class
* Display a Facebook Like Box as a widget
* http://developers.facebook.com/docs/reference/plugins/like-box/
@@ -17,7 +26,14 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
private $allowed_colorschemes = array( 'light', 'dark' );
function __construct() {
- parent::__construct( 'facebook-likebox', __( 'Facebook Like Box', 'jetpack' ), array( 'classname' => 'widget_facebook_likebox', 'description' => __( 'Display a Facebook Like Box to connect visitors to your Facebook Page', 'jetpack' ) ) );
+ parent::__construct(
+ 'facebook-likebox',
+ apply_filters( 'jetpack_widget_name', __( 'Facebook Like Box', 'jetpack' ) ),
+ array(
+ 'classname' => 'widget_facebook_likebox',
+ 'description' => __( 'Display a Facebook Like Box to connect visitors to your Facebook Page', 'jetpack' )
+ )
+ );
}
function widget( $args, $instance ) {
@@ -29,7 +45,7 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
if ( empty( $like_args['href'] ) || ! $this->is_valid_facebook_url( $like_args['href'] ) ) {
if ( current_user_can('edit_theme_options') ) {
echo $before_widget;
- echo '<p>' . sprintf( __( 'It looks like your Facebook URL is incorrectly configured. Please check it in your <a href="%s">widget settings</a>.' ), admin_url( 'widgets.php' ) ) . '</p>';
+ echo '<p>' . sprintf( __( 'It looks like your Facebook URL is incorrectly configured. Please check it in your <a href="%s">widget settings</a>.', 'jetpack' ), admin_url( 'widgets.php' ) ) . '</p>';
echo $after_widget;
}
echo '<!-- Invalid Facebook Page URL -->';
@@ -244,26 +260,33 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
}
function guess_locale_from_lang( $lang ) {
- $lang = strtolower( str_replace( '-', '_', $lang ) );
+ if ( 'en' == $lang || 'en_US' == $lang || !$lang ) {
+ return 'en_US';
+ }
+
+ if ( !class_exists( 'GP_Locales' ) ) {
+ if ( !defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) || !file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
+ return false;
+ }
+
+ require JETPACK__GLOTPRESS_LOCALES_PATH;
+ }
- if ( 5 == strlen( $lang ) ) {
- $lang = substr( $lang, 0, 3 ) . strtoupper( substr( $lang, 3, 2 ) );
- } else if ( 3 == strlen( $lang ) ) {
- $lang = $lang;
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ // WP.com: get_locale() returns 'it'
+ $locale = GP_Locales::by_slug( $lang );
} else {
- $lang = $lang . '_' . strtoupper( $lang );
+ // Jetpack: get_locale() returns 'it_IT';
+ $locale = GP_Locales::by_field( 'wp_locale', $lang );
}
-
- if ( 'en_EN' == $lang ) {
- $lang = 'en_US';
- } else if ( 'he_HE' == $lang ) {
- $lang = 'he_IL';
- } else if ( 'ja_JA' == $lang )
- $lang = 'ja_JP';
- return $lang;
+ if ( !$locale || empty( $locale->facebook_locale ) ) {
+ return false;
+ }
+
+ return $locale->facebook_locale;
}
-
+
function get_locale() {
return $this->guess_locale_from_lang( get_locale() );
}
diff --git a/plugins/jetpack/modules/widgets/gravatar-profile.css b/plugins/jetpack/modules/widgets/gravatar-profile.css
index 230a3b16..1663ae07 100644
--- a/plugins/jetpack/modules/widgets/gravatar-profile.css
+++ b/plugins/jetpack/modules/widgets/gravatar-profile.css
@@ -1,8 +1,7 @@
.widget-grofile {
}
.widget-grofile h4 {
- margin: 1em 0 1.2em;
- /*font-size: 1.2em;*/
+ margin: 1em 0 .5em;
}
.widget-grofile ul.grofile-urls {
margin-left: 0;
@@ -17,7 +16,7 @@
content: "" !important; /* Kubrick :( */
}
.widget-grofile .grofile-accounts-logo {
- background-image: url('http://0.gravatar.com/images/grav-share-sprite.png');
+ background-image: url('//0.gravatar.com/images/grav-share-sprite.png');
background-repeat: no-repeat;
/*background-position: -16px -16px;*/
width: 16px; /* So we don't show the topmost logo */
@@ -34,3 +33,13 @@
.grofile-thumbnail {
width: 100%;
}
+ @media
+only screen and (-webkit-min-device-pixel-ratio: 1.5),
+only screen and (-o-min-device-pixel-ratio: 3/2),
+only screen and (min--moz-device-pixel-ratio: 1.5),
+only screen and (min-device-pixel-ratio: 1.5) {
+ .widget-grofile .grofile-accounts-logo {
+ background-image: url('//0.gravatar.com/images/grav-share-sprite-2x.png');
+ background-size: 16px 784px;
+ }
+} \ No newline at end of file
diff --git a/plugins/jetpack/modules/widgets/gravatar-profile.php b/plugins/jetpack/modules/widgets/gravatar-profile.php
index c33e6996..190427fe 100644
--- a/plugins/jetpack/modules/widgets/gravatar-profile.php
+++ b/plugins/jetpack/modules/widgets/gravatar-profile.php
@@ -1,15 +1,29 @@
<?php
+
+/**
+ * Register the widget for use in Appearance -> Widgets
+ */
+add_action( 'widgets_init', 'jetpack_gravatar_profile_widget_init' );
+
+function jetpack_gravatar_profile_widget_init() {
+ register_widget( 'Jetpack_Gravatar_Profile_Widget' );
+}
+
/**
* Display a widgetized version of your Gravatar Profile
* http://blog.gravatar.com/2010/03/26/gravatar-profiles/
*/
class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
-
+
function __construct() {
- parent::__construct( 'grofile', __( 'Gravatar Profile', 'jetpack' ), array(
- 'classname' => 'widget-grofile grofile',
- 'description' => __( 'Display a mini version of your Gravatar Profile', 'jetpack' )
- ) );
+ parent::__construct(
+ 'grofile',
+ apply_filters( 'jetpack_widget_name', __( 'Gravatar Profile', 'jetpack' ) ),
+ array(
+ 'classname' => 'widget-grofile grofile',
+ 'description' => __( 'Display a mini version of your Gravatar Profile', 'jetpack' )
+ )
+ );
if ( is_admin() ) {
add_action( 'admin_footer-widgets.php', array( $this, 'admin_script' ) );
@@ -24,7 +38,7 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
echo $args['before_widget'];
if ( ! empty( $title ) )
echo $args['before_title'] . $title . $args['after_title'];
- echo '<p>' . sprintf( __( 'You need to select what to show in this <a href="%s">Gravatar Profile widget</a>.' ), admin_url( 'widgets.php' ) ) . '</p>';
+ echo '<p>' . sprintf( __( 'You need to select what to show in this <a href="%s">Gravatar Profile widget</a>.', 'jetpack' ), admin_url( 'widgets.php' ) ) . '</p>';
echo $args['after_widget'];
}
return;
@@ -35,24 +49,39 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
echo $args['before_title'] . $title . $args['after_title'];
$profile = $this->get_profile( $instance['email'] );
-
+
if( ! empty( $profile ) ) {
- $gravatar_url = add_query_arg( 's', 500, $profile['thumbnailUrl'] ); // the default grav returned by grofiles is super small
-
+ $profile = wp_parse_args( $profile, array(
+ 'thumbnailUrl' => '',
+ 'profileUrl' => '',
+ 'displayName' => '',
+ 'aboutMe' => '',
+ 'urls' => array(),
+ 'accounts' => array(),
+ ) );
+ $gravatar_url = add_query_arg( 's', 200, $profile['thumbnailUrl'] ); // the default grav returned by grofiles is super small
+
wp_enqueue_style(
'gravatar-profile-widget',
plugins_url( 'gravatar-profile.css', __FILE__ ),
array(),
'20120711'
);
-
+
+ wp_enqueue_style(
+ 'gravatar-card-services',
+ is_ssl() ? 'https://secure.gravatar.com/css/services.css' : 'http://s.gravatar.com/css/services.css',
+ array(),
+ defined( 'GROFILES__CACHE_BUSTER' ) ? GROFILES__CACHE_BUSTER : gmdate( 'YW' )
+ );
+
?>
- <img src="<?php echo esc_url( $gravatar_url ); ?>" class="grofile-thumbnail no-grav" />
+ <img src="<?php echo esc_url( $gravatar_url ); ?>" class="grofile-thumbnail no-grav" style="width: auto; max-width: 200px;" />
<div class="grofile-meta">
<h4><a href="<?php echo esc_url( $profile['profileUrl'] ); ?>"><?php echo esc_html( $profile['displayName'] ); ?></a></h4>
- <p><?php echo esc_html( wp_kses( $profile['aboutMe'], array() ) ); ?></p>
+ <p><?php echo wp_kses_data( $profile['aboutMe'] ); ?></p>
</div>
-
+
<?php
if( $instance['show_personal_links'] )
@@ -60,15 +89,15 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
if( $instance['show_account_links'] )
$this->display_accounts( (array) $profile['accounts'] );
-
+
?>
-
- <h4><a href="<?php echo esc_url( $profile['profileUrl'] ); ?>" class="grofile-full-link"><?php esc_html_e( 'View Full Profile &rarr;' ); ?></a></h4>
-
+
+ <h4><a href="<?php echo esc_url( $profile['profileUrl'] ); ?>" class="grofile-full-link"><?php esc_html_e( 'View Full Profile &rarr;', 'jetpack' ); ?></a></h4>
+
<?php
- do_action( 'jetpack_stats_extra', 'widgets', 'grofile' );
-
+ do_action( 'jetpack_stats_extra', 'widget', 'grofile' );
+
} else {
if ( current_user_can( 'edit_theme_options' ) ) {
echo '<p>' . esc_html__( 'Error loading profile', 'jetpack' ) . '</p>';
@@ -85,7 +114,7 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
<h4><?php esc_html_e( 'Personal Links', 'jetpack' ); ?></h4>
<ul class="grofile-urls grofile-links">
-
+
<?php foreach( $personal_links as $personal_link ) : ?>
<li>
<a href="<?php echo esc_url( $personal_link['value'] ); ?>">
@@ -98,30 +127,30 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
<?php
}
- function display_accounts( $accounts = array() ) {
+ function display_accounts( $accounts = array() ) {
if ( empty( $accounts ) )
return;
?>
-
+
<h4><?php esc_html_e( 'Verified Services', 'jetpack' ); ?></h4>
<ul class="grofile-urls grofile-accounts">
-
+
<?php foreach( $accounts as $account ) :
if( $account['verified'] != 'true' )
continue;
-
+
$sanitized_service_name = $this->get_sanitized_service_name( $account['shortname'] );
?>
-
+
<li>
<a href="<?php echo esc_url( $account['url'] ); ?>" title="<?php echo sprintf( _x( '%1$s on %2$s', '1: User Name, 2: Service Name (Facebook, Twitter, ...)', 'jetpack' ), esc_html( $account['display'] ), esc_html( $sanitized_service_name ) ); ?>">
<span class="grofile-accounts-logo grofile-accounts-<?php echo esc_attr( $account['shortname'] ); ?> accounts_<?php echo esc_attr( $account['shortname'] ); ?>"></span>
</a>
</li>
-
+
<?php endforeach; ?>
</ul>
-
+
<?php
}
@@ -133,6 +162,12 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
$show_personal_links = isset( $instance['show_personal_links'] ) ? (bool) $instance['show_personal_links'] : '';
$show_account_links = isset( $instance['show_account_links'] ) ? (bool) $instance['show_account_links'] : '';
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ $profile_url = admin_url( 'profile.php' );
+ } else {
+ $profile_url = 'https://gravatar.com/profile/edit';
+ }
+
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>">
@@ -144,7 +179,7 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
<label for="<?php echo $this->get_field_id( 'email_user' ); ?>">
<?php esc_html_e( 'Select a user or pick "custom" and enter a custom email address.', 'jetpack' ); ?>
<br />
-
+
<?php wp_dropdown_users( array(
'show_option_none' => __( 'Custom', 'jetpack' ),
'selected' => $email_user,
@@ -154,13 +189,13 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
) );?>
</label>
</p>
-
+
<p class="gprofile-email-container <?php echo empty( $email_user ) || $email_user == -1 ? '' : 'hidden'; ?>">
<label for="<?php echo $this->get_field_id( 'email' ); ?>"><?php esc_html_e( 'Custom Email Address', 'jetpack' ); ?>
<input class="widefat" id="<?php echo $this->get_field_id('email'); ?>" name="<?php echo $this->get_field_name( 'email' ); ?>" type="text" value="<?php echo esc_attr( $email ); ?>" />
</label>
</p>
-
+
<p>
<label for="<?php echo $this->get_field_id( 'show_personal_links' ); ?>">
<input type="checkbox" name="<?php echo $this->get_field_name( 'show_personal_links' ); ?>" id="<?php echo $this->get_field_id( 'show_personal_links' ); ?>" <?php checked( $show_personal_links ); ?> />
@@ -178,8 +213,8 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
<small><?php esc_html_e( 'Links to services that you use across the web.', 'jetpack' ); ?></small>
</label>
</p>
-
- <p><a href="<?php echo admin_url( 'profile.php' ); ?>" target="_blank" title="<?php esc_attr_e( 'Opens in new window', 'jetpack' ); ?>"><?php esc_html_e( 'Edit Your Profile', 'jetpack' )?></a> | <a href="http://gravatar.com" target="_blank" title="<?php esc_attr_e( 'Opens in new window', 'jetpack' ); ?>"><?php esc_html_e( "What's a Gravatar?", 'jetpack' ); ?></a></p>
+
+ <p><a href="<?php echo esc_url( $profile_url ); ?>" target="_blank" title="<?php esc_attr_e( 'Opens in new window', 'jetpack' ); ?>"><?php esc_html_e( 'Edit Your Profile', 'jetpack' )?></a> | <a href="http://gravatar.com" target="_blank" title="<?php esc_attr_e( 'Opens in new window', 'jetpack' ); ?>"><?php esc_html_e( "What's a Gravatar?", 'jetpack' ); ?></a></p>
<?php
}
@@ -202,7 +237,7 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
}
function update( $new_instance, $old_instance ) {
-
+
$instance = array();
$instance['title'] = isset( $new_instance['title'] ) ? wp_kses( $new_instance['title'], array() ) : '';
@@ -216,42 +251,45 @@ class Jetpack_Gravatar_Profile_Widget extends WP_Widget {
$instance['email'] = $user->user_email;
}
+ $hashed_email = md5( strtolower( trim( $instance['email'] ) ) );
+ $cache_key = 'grofile-' . $hashed_email;
+ delete_transient( $cache_key );
+
return $instance;
}
-
+
private function get_profile( $email ) {
$hashed_email = md5( strtolower( trim( $email ) ) );
- $cache_key = 'widget-grofile-' . $hashed_email;
-
- if( ! $profile = get_transient( $cache_key, 'widget' ) ) {
-
+ $cache_key = 'grofile-' . $hashed_email;
+
+ if( ! $profile = get_transient( $cache_key ) ) {
$profile_url = esc_url_raw( sprintf( '%s.gravatar.com/%s.php', ( is_ssl() ? 'https://secure' : 'http://www' ), $hashed_email ), array( 'http', 'https' ) );
-
+
$expire = 300;
$response = wp_remote_get( $profile_url, array( 'User-Agent' => 'WordPress.com Gravatar Profile Widget' ) );
$response_code = wp_remote_retrieve_response_code( $response );
if ( 200 == $response_code ) {
$profile = wp_remote_retrieve_body( $response );
$profile = unserialize( $profile );
-
+
if ( is_array( $profile ) && ! empty( $profile['entry'] ) && is_array( $profile['entry'] ) ) {
$expire = 900; // cache for 15 minutes
$profile = $profile['entry'][0];
} else {
+ // Something strange happend. Cache for 5 minutes.
$profile = array();
}
-
+
} else {
- $expire =
+ $expire = 900; // cache for 15 minutes
$profile = array();
- set_transient( $cache_key . '-response-code', $response_code, $expire );
}
-
+
set_transient( $cache_key, $profile, $expire );
}
return $profile;
}
-
+
private function get_sanitized_service_name( $shortname ) {
// Some services have stylized or mixed cap names *cough* WP *cough*
switch( $shortname ) {
diff --git a/plugins/jetpack/modules/widgets/image-widget.php b/plugins/jetpack/modules/widgets/image-widget.php
index 0e7e227b..03d4d5c7 100644
--- a/plugins/jetpack/modules/widgets/image-widget.php
+++ b/plugins/jetpack/modules/widgets/image-widget.php
@@ -43,7 +43,7 @@ class Jetpack_Image_Widget extends WP_Widget {
if ( '' != $instance['caption'] )
$output = '[caption align="align' . esc_attr( $instance['align'] ) . '" width="' . esc_attr( $instance['img_width'] ) .'" caption="' . esc_attr( $instance['caption'] ) . '"]' . $output . '[/caption]';
- echo '<div style="overflow:hidden;">' . do_shortcode( $output ) . '</div>';
+ echo '<div class="jetpack-image-container">' . do_shortcode( $output ) . '</div>';
}
echo "\n" . $after_widget;
diff --git a/plugins/jetpack/modules/widgets/readmill.php b/plugins/jetpack/modules/widgets/readmill.php
new file mode 100644
index 00000000..7729ed3e
--- /dev/null
+++ b/plugins/jetpack/modules/widgets/readmill.php
@@ -0,0 +1,138 @@
+<?php
+class Jetpack_Readmill_Widget extends WP_Widget {
+ var $default_title, $default_size;
+
+ /**
+ * Registers the widget with WordPress.
+ */
+ function __construct() {
+ parent::__construct(
+ 'jetpack_readmill_widget', // Base ID
+ apply_filters( 'jetpack_widget_name', esc_html__( 'Send To Readmill', 'jetpack' ) ),
+ array(
+ 'description' => esc_html__( 'Readmill is the best book reader for phones and tablets. With this widget you can enable users to send a book to their device with one click.', 'jetpack' ),
+ )
+ );
+
+ if ( is_active_widget( false, false, $this->id_base ) || is_active_widget( false, false, 'monster' ) ) {
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_script' ) );
+ }
+
+ $this->default_title = __( 'Send To Readmill', 'jetpack' );
+ $this->default_size = 'large';
+ }
+
+ function enqueue_script() {
+ wp_enqueue_script( 'readmill', 'https://platform.readmill.com/send.js', array(), '20130220', false );
+ }
+
+ /**
+ * Back-end widget form.
+ *
+ * @see WP_Widget::form()
+ *
+ * @param array $instance Previously saved values from database.
+ */
+ function form( $instance ) {
+ $title = isset( $instance['title' ] ) ? $instance['title'] : false;
+ if ( false === $title ) {
+ $title = $this->default_title;
+ }
+
+ $epub_link = isset( $instance['epub_link'] ) ? $instance['epub_link'] : '';
+ $buy_link = isset( $instance['buy_link'] ) ? $instance['buy_link'] : '';
+ $size = isset( $instance['size'] ) ? $instance['size'] : $this->default_size;
+ ?>
+
+ <p><?php printf( __( "Just enter the URL to your book, make sure it's a PDF or EPUB file, and you are ready to go. For more help, head to <a href='%s'>the Readmill WordPress Widget support page</a>." ), 'http://en.support.wordpress.com/widgets/readmill/' ); ?></p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
+ <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 ); ?>" />
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'epub_link' ); ?>"><?php esc_html_e( 'Download URL:', 'jetpack' ); ?></label>
+ <input class="widefat" id="<?php echo $this->get_field_id( 'epub_link' ); ?>" name="<?php echo $this->get_field_name( 'epub_link' ); ?>" type="text" value="<?php echo esc_attr( $epub_link ); ?>" />
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'buy_link' ); ?>"><?php esc_html_e( 'Item URL:', 'jetpack' ); ?></label>
+ <input class="widefat" id="<?php echo $this->get_field_id( 'buy_link' ); ?>" name="<?php echo $this->get_field_name( 'buy_link' ); ?>" type="text" value="<?php echo esc_attr( $buy_link ); ?>" />
+ </p>
+
+ <p>
+ <label><?php esc_html_e( 'What size icon?', 'jetpack' ); ?></label>
+ <ul>
+ <li><label><input id="<?php echo $this->get_field_id( 'size' ); ?>-few" name="<?php echo $this->get_field_name( 'size' ); ?>" type="radio" value="large" <?php checked( 'large', $size ); ?> /> <?php esc_html_e( 'Large', 'jetpack' ); ?></label></li>
+ <li><label><input id="<?php echo $this->get_field_id( 'size' ); ?>-lots" name="<?php echo $this->get_field_name( 'size' ); ?>" type="radio" value="small" <?php checked( 'small', $size ); ?> /> <?php esc_html_e( 'Small', 'jetpack' ); ?></label></li>
+ </ul>
+ </p>
+
+ <?php
+ }
+
+ /**
+ * Sanitize widget form values as they are saved.
+ *
+ * @see WP_Widget::update()
+ *
+ * @param array $new_instance Values just sent to be saved.
+ * @param array $old_instance Previously saved values from database.
+ *
+ * @return array Updated safe values to be saved.
+ */
+ function update( $new_instance, $old_instance ) {
+ $instance = array();
+ $instance['title'] = wp_kses( $new_instance['title'], array() );
+ $instance['epub_link'] = wp_kses( $new_instance['epub_link'], array() );
+ $instance['buy_link'] = wp_kses( $new_instance['buy_link'], array() );
+ $instance['size'] = wp_kses( $new_instance['size'], array() );
+
+ if ( $this->default_title === $instance['title'] ) {
+ $instance['title'] = false; // Store as false in case of language change
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Front-end display of widget.
+ *
+ * @see WP_Widget::widget()
+ *
+ * @param array $args Widget arguments.
+ * @param array $instance Saved values from database.
+ */
+ function widget( $args, $instance ) {
+ $title = isset( $instance['title' ] ) ? $instance['title'] : false;
+
+ if ( false === $title )
+ $title = $this->default_title;
+
+ $title = apply_filters( 'widget_title', $title );
+
+ echo $args['before_widget'];
+
+ if ( ! empty( $title ) )
+ echo $args['before_title'] . $title . $args['after_title'];
+
+ $epub_link = isset( $instance['epub_link'] ) ? $instance['epub_link'] : '';
+ $buy_link = isset( $instance['buy_link'] ) ? $instance['buy_link'] : '';
+ $size = isset( $instance['size'] ) ? $instance['size'] : $this->default_size;
+
+ if ( empty( $epub_link ) && current_user_can( 'edit_theme_options' ) ) :
+ ?><p><?php esc_html_e( 'Your ePub link is empty. Provide an ePub link to display the Send to Readmill widget.', 'jetpack' ); ?></p><?php
+ else :
+ ?><a class="send-to-readmill" href="https://readmill.com" data-download-url="<?php echo esc_attr( $epub_link ); ?>" data-buy-url="<?php echo esc_attr( $epub_link ); ?>" data-display="<?php echo esc_attr( $size ); ?>">Send to Readmill</a><?php
+ endif;
+
+ echo $args['after_widget'];
+ }
+}
+
+function jetpack_readmill_widget_init() {
+ register_widget( 'Jetpack_Readmill_Widget' );
+}
+
+add_action( 'widgets_init', 'jetpack_readmill_widget_init' );
diff --git a/plugins/jetpack/modules/widgets/top-posts.php b/plugins/jetpack/modules/widgets/top-posts.php
new file mode 100644
index 00000000..b6f2c8d7
--- /dev/null
+++ b/plugins/jetpack/modules/widgets/top-posts.php
@@ -0,0 +1,295 @@
+<?php
+
+/*
+ * Currently, this widget depends on the Stats Module. To not load this file
+ * when the Stats Module is not active would potentially bypass Jetpack's
+ * fatal error detection on module activation, so we always load this file.
+ * Instead, we don't register the widget if the Stats Module isn't active.
+ */
+
+/**
+ * Register the widget for use in Appearance -> Widgets
+ */
+add_action( 'widgets_init', 'jetpack_top_posts_widget_init' );
+
+function jetpack_top_posts_widget_init() {
+ // Currently, this widget depends on the Stats Module
+ if (
+ ( !defined( 'IS_WPCOM' ) || !IS_WPCOM )
+ &&
+ !function_exists( 'stats_get_csv' )
+ ) {
+ return;
+ }
+
+ register_widget( 'Jetpack_Top_Posts_Widget' );
+}
+
+class Jetpack_Top_Posts_Widget extends WP_Widget {
+ var $alt_option_name = 'widget_stats_topposts';
+ var $default_title = '';
+
+ function __construct() {
+ parent::__construct(
+ 'top-posts',
+ apply_filters( 'jetpack_widget_name', __( 'Top Posts &amp; Pages', 'jetpack' ) ),
+ array(
+ 'description' => __( 'Shows your most viewed posts and pages.', 'jetpack' ),
+ )
+ );
+
+ $this->default_title = __( 'Top Posts &amp; Pages', 'jetpack' );
+
+ if ( is_active_widget( false, false, $this->id_base ) ) {
+ add_action( 'wp_print_styles', array( $this, 'enqueue_style' ) );
+ }
+ }
+
+ function enqueue_style() {
+ wp_register_style( 'widget-grid-and-list', plugins_url( 'widget-grid-and-list.css', __FILE__ ) );
+ wp_enqueue_style( 'widget-grid-and-list' );
+ }
+
+ function form( $instance ) {
+ $title = isset( $instance['title' ] ) ? $instance['title'] : false;
+ if ( false === $title ) {
+ $title = $this->default_title;
+ }
+
+ $count = isset( $instance['count'] ) ? (int) $instance['count'] : 10;
+ if ( $count < 1 || 20 < $count ) {
+ $count = 10;
+ }
+
+ if ( isset( $instance['display'] ) && in_array( $instance['display'], array( 'grid', 'list', 'text' ) ) ) {
+ $display = $instance['display'];
+ } else {
+ $display = 'text';
+ }
+
+ ?>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
+ <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 ); ?>" />
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'count' ); ?>"><?php esc_html_e( 'Number of posts to show:', 'jetpack' ); ?></label>
+ <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="20" />
+ </p>
+
+ <p>
+ <label><?php esc_html_e( 'Display as:', 'jetpack' ); ?></label>
+ <ul>
+ <li><label><input id="<?php echo $this->get_field_id( 'display' ); ?>-text" name="<?php echo $this->get_field_name( 'display' ); ?>" type="radio" value="text" <?php checked( 'text', $display ); ?> /> <?php esc_html_e( 'Text List', 'jetpack' ); ?></label></li>
+ <li><label><input id="<?php echo $this->get_field_id( 'display' ); ?>-list" name="<?php echo $this->get_field_name( 'display' ); ?>" type="radio" value="list" <?php checked( 'list', $display ); ?> /> <?php esc_html_e( 'Image List', 'jetpack' ); ?></label></li>
+ <li><label><input id="<?php echo $this->get_field_id( 'display' ); ?>-grid" name="<?php echo $this->get_field_name( 'display' ); ?>" type="radio" value="grid" <?php checked( 'grid', $display ); ?> /> <?php esc_html_e( 'Image Grid', 'jetpack' ); ?></label></li>
+ </ul>
+ </p>
+
+ <p><?php esc_html_e( 'Top Posts &amp; Pages by views are calculated from 24-48 hours of stats. They take a while to change.', 'jetpack' ); ?></p>
+
+ <?php
+ }
+
+ function update( $new_instance, $old_instance ) {
+ $instance = array();
+ $instance['title'] = wp_kses( $new_instance['title'], array() );
+ if ( $instance['title'] === $this->default_title ) {
+ $instance['title'] = false; // Store as false in case of language change
+ }
+
+ $instance['count'] = (int) $new_instance['count'];
+ if ( $instance['count'] < 1 || 20 < $instance['count'] ) {
+ $instance['count'] = 10;
+ }
+
+ if ( isset( $new_instance['display'] ) && in_array( $new_instance['display'], array( 'grid', 'list', 'text' ) ) ) {
+ $instance['display'] = $new_instance['display'];
+ } else {
+ $instance['display'] = 'text';
+ }
+
+ return $instance;
+ }
+
+ function widget( $args, $instance ) {
+ $title = isset( $instance['title' ] ) ? $instance['title'] : false;
+ if ( false === $title )
+ $title = $this->default_title;
+ $title = apply_filters( 'widget_title', $title );
+
+ $count = isset( $instance['count'] ) ? (int) $instance['count'] : false;
+ if ( $count < 1 || 20 < $count ) {
+ $count = 10;
+ }
+
+ if ( isset( $instance['display'] ) && in_array( $instance['display'], array( 'grid', 'list', 'text' ) ) ) {
+ $display = $instance['display'];
+ } else {
+ $display = 'text';
+ }
+
+ if ( 'text' != $display ) {
+ $get_image_options = array(
+ 'fallback_to_avatars' => true,
+ 'gravatar_default' => apply_filters( 'jetpack_static_url', is_ssl() ? 'https' : 'http' . '://en.wordpress.com/i/logo/white-gray-80.png' ),
+ );
+ if ( 'grid' == $display ) {
+ if ( $count %2 != 0 ) {
+ $count++;
+ }
+
+ $get_image_options['avatar_size'] = 200;
+ } else {
+ $get_image_options['avatar_size'] = 40;
+ }
+ $get_image_options = apply_filters( 'jetpack_top_posts_widget_image_options', $get_image_options );
+ }
+
+ $posts = $this->get_by_views( $count );
+
+ if ( !$posts ) {
+ $posts = $this->get_fallback_posts();
+ }
+
+ echo $args['before_widget'];
+ if ( ! empty( $title ) )
+ echo $args['before_title'] . $title . $args['after_title'];
+
+ if ( !$posts ) {
+ if ( current_user_can( 'edit_theme_options' ) ) {
+ echo '<p>' . sprintf(
+ __( 'There are no posts to display. <a href="%s">Want more traffic?</a>', 'jetpack' ),
+ 'http://en.support.wordpress.com/getting-more-site-traffic/'
+ ) . '</p>';
+ }
+
+ echo $args['after_widget'];
+ return;
+ }
+
+ switch ( $display ) {
+ case 'list' :
+ case 'grid' :
+ wp_enqueue_style( 'widget-grid-and-list' );
+ foreach ( $posts as &$post ) {
+ $image = Jetpack_PostImages::get_image( $post['post_id'] );
+ $post['image'] = $image['src'];
+ if ( 'blavatar' != $image['from'] && 'gravatar' != $image['from'] ) {
+ $size = (int) $get_image_options['avatar_size'];
+ $post['image'] = jetpack_photon_url( $post['image'], array( 'resize' => "$size,$size" ) );
+ }
+ }
+
+ unset( $post );
+
+ if ( 'grid' == $display ) {
+ echo "<div class='widgets-grid-layout no-grav'>\n";
+ foreach ( $posts as $post ) :
+ ?>
+ <div class="widget-grid-view-image">
+ <a href="<?php echo esc_url( $post['permalink'] ); ?>" title="<?php echo esc_attr( wp_kses( $post['title'], array() ) ); ?>" class="bump-view" data-bump-view="tp"><img src="<?php echo esc_url( $post['image'] ); ?>" /></a>
+ </div>
+
+ <?php
+ endforeach;
+ echo "</div>\n";
+ } else {
+ echo "<ul class='widgets-list-layout no-grav'>\n";
+ foreach ( $posts as $post ) :
+ ?>
+ <li>
+ <img src="<?php echo esc_url( $post['image'] ); ?>" class='widgets-list-layout-blavatar' />
+ <div class="widgets-list-layout-links"><a href="<?php echo esc_url( $post['permalink'] ); ?>" class="bump-view" data-bump-view="tp"><?php echo esc_html( wp_kses( $post['title'], array() ) ); ?></a></div>
+ </li>
+ <?php
+ endforeach;
+ echo "</ul>\n";
+ }
+ break;
+ default :
+ echo '<ul>';
+ foreach ( $posts as $post ) {
+ echo '<li><a href="' . esc_url( $post['permalink'] ) . '" class="bump-view" data-bump-view="tp">' . esc_html( $post['title'] ) . "</a></li>\n";
+ }
+ echo '</ul>';
+ }
+
+ echo $args['after_widget'];
+ }
+
+ function get_by_views( $count ) {
+ global $wpdb;
+ $post_view_posts = stats_get_csv( 'postviews', array( 'days' => 2, 'limit' => 10 ) );
+ if ( !$post_view_posts ) {
+ return array();
+ }
+
+ $post_view_ids = array_filter( wp_list_pluck( $post_view_posts, 'post_id' ) );
+ if ( !$post_view_ids ) {
+ return array();
+ }
+
+ return $this->get_posts( $post_view_ids, $count );
+ }
+
+ function get_fallback_posts() {
+ if ( current_user_can( 'edit_theme_options' ) ) {
+ return array();
+ }
+
+ $post_query = new WP_Query;
+
+ $posts = $post_query->query( array(
+ 'posts_per_page' => 1,
+ 'post_status' => 'publish',
+ 'post_type' => array( 'post', 'page' ),
+ 'no_found_rows' => true,
+ ) );
+
+ if ( !$posts ) {
+ return array();
+ }
+
+ $post = array_pop( $posts );
+
+ return $this->get_posts( $post->ID, 1 );
+ }
+
+ function get_posts( $post_ids, $count ) {
+ $counter = 0;
+
+ $posts = array();
+ foreach ( (array) $post_ids as $post_id ) {
+ $post = get_post( $post_id );
+
+ if ( !$post )
+ continue;
+
+ // hide private and password protected posts
+ if ( 'publish' != $post->post_status || !empty( $post->post_password ) || empty( $post->ID ) )
+ continue;
+
+ // Both get HTML stripped etc on display
+ if ( empty( $post->post_title ) ) {
+ $title_source = $post->post_content;
+ $title = wp_html_excerpt( $title_source, 50 );
+ $title .= '&hellip;';
+ } else {
+ $title = $post->post_title;
+ }
+
+ $permalink = get_permalink( $post->ID );
+
+ $posts[] = compact( 'title', 'permalink', 'post_id' );
+ $counter++;
+
+ if ( $counter == $count )
+ break; // only need to load and show x number of likes
+ }
+
+ return $posts;
+ }
+}
diff --git a/plugins/jetpack/modules/widgets/twitter.php b/plugins/jetpack/modules/widgets/twitter.php
new file mode 100644
index 00000000..ff49abf7
--- /dev/null
+++ b/plugins/jetpack/modules/widgets/twitter.php
@@ -0,0 +1,407 @@
+<?php
+
+/**
+ * Twitter widget class
+ * Display the latest N tweets from a Twitter screenname as a widget
+ * Customize screenname, maximum number of tweets displayed, show or hide @replies, and text displayed between tweet text and a timestamp
+ *
+ */
+
+/**
+ * Register the widget for use in Appearance -> Widgets
+ */
+add_action( 'widgets_init', 'jetpack_twitter_widget_init' );
+
+function jetpack_twitter_widget_init() {
+ register_widget( 'Jetpack_Widget_Twitter' );
+}
+
+class Jetpack_Widget_Twitter extends WP_Widget {
+
+ function __construct() {
+ parent::__construct(
+ 'twitter',
+ apply_filters( 'jetpack_widget_name', __( 'Twitter', 'jetpack' ) ),
+ array(
+ 'classname' => 'widget_twitter',
+ 'description' => __( 'Display your Tweets from Twitter', 'jetpack' )
+ )
+ );
+
+ if ( is_active_widget( false, false, $this->id_base ) || is_active_widget( false, false, 'monster' ) ) {
+ add_action( 'wp_head', array( $this, 'style' ) );
+ }
+ }
+
+ function style() {
+?>
+<style type="text/css">
+.widget_twitter li {
+ word-wrap: break-word;
+}
+</style>
+<?php
+ }
+
+ function widget( $args, $instance ) {
+ $account = trim( urlencode( $instance['account'] ) );
+
+ if ( empty( $account ) ) {
+ if ( current_user_can('edit_theme_options') ) {
+ echo $args['before_widget'];
+ echo '<p>' . sprintf( __( 'Please configure your Twitter username for the <a href="%s">Twitter Widget</a>.', 'jetpack' ), admin_url( 'widgets.php' ) ) . '</p>';
+ echo $args['after_widget'];
+ }
+
+ return;
+ }
+
+ $title = apply_filters( 'widget_title', $instance['title'] );
+
+ if ( empty( $title ) )
+ $title = __( 'Twitter Updates', 'jetpack' );
+
+ $show = absint( $instance['show'] ); // # of Updates to show
+
+ if ( $show > 200 ) // Twitter paginates at 200 max tweets. update() should not have accepted greater than 20
+ $show = 200;
+
+ $hidereplies = (bool) $instance['hidereplies'];
+ $hidepublicized = (bool) $instance['hidepublicized'];
+ $include_retweets = (bool) $instance['includeretweets'];
+ $follow_button = (bool) $instance['followbutton'];
+
+ echo "{$args['before_widget']}{$args['before_title']}<a href='" . esc_url( "http://twitter.com/{$account}" ) . "'>" . esc_html( $title ) . "</a>{$args['after_title']}";
+
+ $tweets = $this->fetch_twitter_user_stream( $account, $hidereplies, $show, $include_retweets );
+
+ if ( isset( $tweets['error'] ) && ( isset( $tweets['data'] ) && ! empty( $tweets['data'] ) ) )
+ $tweets['error'] = '';
+
+ if ( empty( $tweets['error'] ) ) {
+ $before_tweet = isset( $instance['beforetweet'] ) ? stripslashes( wp_filter_post_kses( $instance['beforetweet'] ) ) : '';
+ $before_timesince = ( isset( $instance['beforetimesince'] ) && ! empty( $instance['beforetimesince'] ) ) ? esc_html( $instance['beforetimesince'] ) : ' ';
+
+ $this->display_tweets( $show, $tweets['data'], $hidepublicized, $before_tweet, $before_timesince, $account );
+
+ if ( $follow_button )
+ $this->display_follow_button( $account );
+
+ add_action( 'wp_footer', array( $this, 'twitter_widget_script' ) );
+ } else {
+ echo $tweets['error'];
+ }
+
+ echo $args['after_widget'];
+ do_action( 'jetpack_bump_stats_extras', 'widget', 'twitter' );
+ }
+
+ function display_tweets( $show, $tweets, $hidepublicized, $before_tweet, $before_timesince, $account ) {
+ $tweets_out = 0;
+ ?><ul class='tweets'><?php
+
+ foreach( (array) $tweets as $tweet ) {
+ if ( $tweets_out >= $show )
+ break;
+
+ if ( empty( $tweet['text'] ) )
+ continue;
+
+ if( $hidepublicized && false !== strstr( $tweet['source'], 'http://publicize.wp.com/' ) )
+ continue;
+
+ $tweet['text'] = esc_html( $tweet['text'] ); // escape here so that Twitter handles in Tweets don't get mangled
+ $tweet = $this->expand_tco_links( $tweet );
+ $tweet['text'] = make_clickable( $tweet['text'] );
+
+ /*
+ * Create links from plain text based on Twitter patterns
+ * @link http://github.com/mzsanford/twitter-text-rb/blob/master/lib/regex.rb Official Twitter regex
+ */
+ $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'] );
+ $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'] );
+
+ if ( isset( $tweet['id_str'] ) )
+ $tweet_id = urlencode( $tweet['id_str'] );
+ else
+ $tweet_id = urlencode( $tweet['id'] );
+
+ ?>
+
+ <li>
+ <?php echo esc_attr( $before_tweet ) . $tweet['text'] . esc_attr( $before_timesince ) ?>
+ <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>
+ </li>
+
+ <?php
+
+ unset( $tweet_it );
+ $tweets_out++;
+ }
+
+ ?></ul><?php
+ }
+
+ function display_follow_button( $account ) {
+ global $themecolors;
+
+ $follow_colors = isset( $themecolors['link'] ) ? " data-link-color='#{$themecolors['link']}'" : '';
+ $follow_colors .= isset( $themecolors['text'] ) ? " data-text-color='#{$themecolors['text']}'" : '';
+ $follow_button_attrs = " class='twitter-follow-button' data-show-count='false'{$follow_colors}";
+
+ ?><a href="http://twitter.com/<?php echo esc_attr( $account ); ?>" <?php echo $follow_button_attrs; ?>>Follow @<?php echo esc_attr( $account ); ?></a><?php
+ }
+
+ function expand_tco_links( $tweet ) {
+ if ( ! empty( $tweet['entities']['urls'] ) && is_array( $tweet['entities']['urls'] ) ) {
+ foreach ( $tweet['entities']['urls'] as $entity_url ) {
+ if ( ! empty( $entity_url['expanded_url'] ) ) {
+ $tweet['text'] = str_replace(
+ $entity_url['url'],
+ '<a href="' . esc_url( $entity_url['expanded_url'] ) . '"> ' . esc_html( $entity_url['display_url'] ) . '</a>',
+ $tweet['text']
+ );
+ }
+ }
+ }
+
+ return $tweet;
+ }
+
+ function fetch_twitter_user_stream( $account, $hidereplies, $show, $include_retweets ) {
+ $tweets = get_transient( 'widget-twitter-' . $this->number );
+ $the_error = get_transient( 'widget-twitter-error-' . $this->number );
+
+ if ( ! $tweets ) {
+ $params = array(
+ 'screen_name' => $account, // Twitter account name
+ 'trim_user' => true, // only basic user data (slims the result)
+ 'include_entities' => true
+ );
+
+ // If combined with $count, $exclude_replies only filters that number of tweets (not all tweets up to the requested count).
+ if ( $hidereplies )
+ $params['exclude_replies'] = true;
+ else
+ $params['count'] = $show;
+
+ if ( $include_retweets )
+ $params['include_rts'] = true;
+
+ $twitter_json_url = esc_url_raw( 'http://api.twitter.com/1/statuses/user_timeline.json?' . http_build_query( $params ), array( 'http', 'https' ) );
+ unset( $params );
+
+ $response = wp_remote_get( $twitter_json_url, array( 'User-Agent' => 'WordPress.com Twitter Widget' ) );
+ $response_code = wp_remote_retrieve_response_code( $response );
+
+ switch( $response_code ) {
+ case 200 : // process tweets and display
+ $tweets = json_decode( wp_remote_retrieve_body( $response ), true );
+
+ if ( ! is_array( $tweets ) || isset( $tweets['error'] ) ) {
+ do_action( 'jetpack_bump_stats_extras', 'twitter_widget', "request-fail-{$response_code}-bad-data" );
+ $the_error = '<p>' . esc_html__( 'Error: Twitter did not respond. Please wait a few minutes and refresh this page.', 'jetpack' ) . '</p>';
+ $tweet_cache_expire = 300;
+ break;
+ } else {
+ set_transient( 'widget-twitter-backup-' . $this->number, $tweets, 86400 ); // A one day backup in case there is trouble talking to Twitter
+ }
+
+ do_action( 'jetpack_bump_stats_extras', 'twitter_widget', 'request-success' );
+ $tweet_cache_expire = 900;
+ break;
+ case 401 : // display private stream notice
+ do_action( 'jetpack_bump_stats_extras', 'twitter_widget', "request-fail-{$response_code}" );
+
+ $tweets = array();
+ $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>';
+ $tweet_cache_expire = 300;
+ break;
+ default : // display an error message
+ do_action( 'jetpack_bump_stats_extras', 'twitter_widget', "request-fail-{$response_code}" );
+
+ $tweets = get_transient( 'widget-twitter-backup-' . $this->number );
+ $the_error = '<p>' . esc_html__( 'Error: Twitter did not respond. Please wait a few minutes and refresh this page.', 'jetpack' ) . '</p>';
+ $tweet_cache_expire = 300;
+ break;
+ }
+
+ set_transient( 'widget-twitter-' . $this->number, $tweets, $tweet_cache_expire );
+ set_transient( 'widget-twitter-error-' . $this->number, $the_error, $tweet_cache_expire );
+ }
+
+ return array( 'data' => $tweets, 'error' => $the_error );
+ }
+
+ function update( $new_instance, $old_instance ) {
+ $instance = array();
+
+ $instance['account'] = trim( wp_kses( $new_instance['account'], array() ) );
+ $instance['account'] = str_replace( array( 'http://twitter.com/', '/', '@', '#!', ), array( '', '', '', '', ), $instance['account'] );
+
+ $instance['title'] = wp_kses( $new_instance['title'], array() );
+ $instance['show'] = absint( $new_instance['show'] );
+ $instance['hidereplies'] = isset( $new_instance['hidereplies'] );
+ $instance['hidepublicized'] = isset( $new_instance['hidepublicized'] );
+ $instance['includeretweets'] = isset( $new_instance['includeretweets'] );
+
+ if ( $instance['followbutton'] != $new_instance['followbutton'] ) {
+ if ( $new_instance['followbutton'] )
+ do_action( 'jetpack_bump_stats_extras', 'twitter_widget', 'follow_button_enabled' );
+ else
+ do_action( 'jetpack_bump_stats_extras', 'twitter_widget', 'follow_button_disabled' );
+ }
+
+ $instance['followbutton'] = ! isset( $new_instance['followbutton'] ) ? 0 : 1;
+ $instance['beforetimesince'] = $new_instance['beforetimesince'];
+
+ delete_transient( 'widget-twitter-' . $this->number );
+ delete_transient( 'widget-twitter-error-' . $this->number );
+
+ return $instance;
+ }
+
+ function form( $instance ) {
+ //Defaults
+ $account = isset( $instance['account'] ) ? wp_kses( $instance['account'], array() ) : '';
+ $title = isset( $instance['title'] ) ? $instance['title'] : '';
+ $show = isset( $instance['show'] ) ? absint( $instance['show'] ) : 5;
+ $show = ( $show < 1 || 20 < $show ) ? 5 : $show;
+ $hidereplies = isset( $instance['hidereplies'] ) && ! empty( $instance['hidereplies'] ) ? (bool) $instance['hidereplies'] : false;
+ $hidepublicized = isset( $instance['hidepublicized'] ) && ! empty( $instance['hidepublicized'] ) ? (bool) $instance['hidepublicized'] : false;
+ $include_retweets = isset( $instance['includeretweets'] ) && ! empty( $instance['includeretweets'] ) ? (bool) $instance['includeretweets'] : false;
+ $follow_button = isset( $instance['followbutton'] ) && ! empty( $instance['followbutton'] ) ? 1 : 0;
+ $before_timesince = isset( $instance['beforetimesince'] ) && ! empty( $instance['beforetimesince'] ) ? esc_attr( $instance['beforetimesince'] ) : '';
+ ?>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'title' ); ?>">
+ <?php esc_html_e( 'Title:', 'jetpack' )?>
+ <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 ); ?>" />
+ </label>
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'account' ); ?>">
+ <?php esc_html_e( 'Twitter username:', 'jetpack' ); ?> <a href="http://support.wordpress.com/widgets/twitter-widget/#twitter-username" target="_blank">( ? )</a>
+ <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 ); ?>" />
+ </label>
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'show' ); ?>">
+ <?php esc_html_e( 'Maximum number of Tweets to show:', 'jetpack' ); ?>
+ <select id="<?php echo $this->get_field_id( 'show' ); ?>" name="<?php echo $this->get_field_name( 'show' ); ?>">
+ <?php
+ for ( $i = 1; $i <= 20; ++$i ) :
+ ?><option value="<?php echo esc_attr( $i ); ?>" <?php selected( $show, $i ); ?>><?php echo esc_attr( $i ); ?></option><?php
+ endfor;
+ ?>
+ </select>
+ </label>
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'hidereplies' ); ?>">
+ <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 ); ?> />
+ <?php esc_html_e( 'Hide replies', 'jetpack' ); ?>
+ </label>
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'hidepublicized' ); ?>">
+ <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 ); ?> />
+ <?php esc_html_e( 'Hide Tweets pushed by Publicize', 'jetpack' ); ?>
+ </label>
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'includeretweets' ); ?>">
+ <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 ); ?> />
+ <?php esc_html_e( 'Include retweets', 'jetpack' ); ?>
+ </label>
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'followbutton' ); ?>">
+ <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 ); ?> />
+ <?php esc_html_e( 'Display Follow Button', 'jetpack' ); ?>
+ </label>
+ </p>
+
+ <p>
+ <label for="<?php echo $this->get_field_id( 'beforetimesince' ); ?>">
+ <?php esc_html_e( 'Text to display between Tweet and timestamp:', 'jetpack' ); ?>
+ <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 ); ?>" />
+ </label>
+ </p>
+
+ <?php
+ }
+
+ function time_since( $original, $do_more = 0 ) {
+ // array of time period chunks
+ $chunks = array(
+ array(60 * 60 * 24 * 365 , 'year'),
+ array(60 * 60 * 24 * 30 , 'month'),
+ array(60 * 60 * 24 * 7, 'week'),
+ array(60 * 60 * 24 , 'day'),
+ array(60 * 60 , 'hour'),
+ array(60 , 'minute'),
+ );
+
+ $today = time();
+ $since = $today - $original;
+
+ for ($i = 0, $j = count($chunks); $i < $j; $i++) {
+ $seconds = $chunks[$i][0];
+ $name = $chunks[$i][1];
+
+ if (($count = floor($since / $seconds)) != 0)
+ break;
+ }
+
+ $print = ($count == 1) ? '1 '.$name : "$count {$name}s";
+
+ if ($i + 1 < $j) {
+ $seconds2 = $chunks[$i + 1][0];
+ $name2 = $chunks[$i + 1][1];
+
+ // add second item if it's greater than 0
+ if ( (($count2 = floor(($since - ($seconds * $count)) / $seconds2)) != 0) && $do_more )
+ $print .= ($count2 == 1) ? ', 1 '.$name2 : ", $count2 {$name2}s";
+ }
+ return $print;
+ }
+
+ /**
+ * Link a Twitter user mentioned in the tweet text to the user's page on Twitter.
+ *
+ * @param array $matches regex match
+ * @return string Tweet text with inserted @user link
+ */
+ function _jetpack_widget_twitter_username( array $matches ) { // $matches has already been through wp_specialchars
+ return "$matches[1]@<a href='" . esc_url( 'http://twitter.com/' . urlencode( $matches[3] ) ) . "'>$matches[3]</a>";
+ }
+
+ /**
+ * Link a Twitter hashtag with a search results page on Twitter.com
+ *
+ * @param array $matches regex match
+ * @return string Tweet text with inserted #hashtag link
+ */
+ function _jetpack_widget_twitter_hashtag( array $matches ) { // $matches has already been through wp_specialchars
+ return "$matches[1]<a href='" . esc_url( 'http://twitter.com/search?q=%23' . urlencode( $matches[3] ) ) . "'>#$matches[3]</a>";
+ }
+
+ function twitter_widget_script() {
+ if ( ! wp_script_is( 'twitter-widgets', 'registered' ) ) {
+ if ( is_ssl() )
+ $twitter_widget_js = 'https://platform.twitter.com/widgets.js';
+ else
+ $twitter_widget_js = 'http://platform.twitter.com/widgets.js';
+ wp_register_script( 'twitter-widgets', $twitter_widget_js, array(), '20111117', true );
+ wp_print_scripts( 'twitter-widgets' );
+ }
+ }
+}
diff --git a/plugins/jetpack/modules/widgets/widget-grid-and-list.css b/plugins/jetpack/modules/widgets/widget-grid-and-list.css
new file mode 100644
index 00000000..984016c9
--- /dev/null
+++ b/plugins/jetpack/modules/widgets/widget-grid-and-list.css
@@ -0,0 +1,110 @@
+/* 2-Column Grid Layout */
+
+.widgets-grid-layout {
+ width: 100%;
+}
+
+.widgets-grid-layout:before,
+.widgets-grid-layout:after {
+ content: " ";
+ display: table;
+}
+
+.widgets-grid-layout:after {
+ clear: both;
+}
+
+.widget-grid-view-image {
+ float: left;
+ max-width: 50%;
+}
+
+.widget-grid-view-image a {
+ display: block;
+ margin: 0 2px 4px 0;
+}
+
+.widget-grid-view-image:image:nth-child(even) {
+ float: right;
+}
+
+.widget-grid-view-image:nth-child(even) a {
+ margin: 0 0 4px 2px;
+}
+
+.widgets-grid-layout .widget-grid-view-image img {
+ max-width: 100%;
+ height: auto;
+}
+
+/* Multi-Column Grid Layout */
+
+.widgets-multi-column-grid ul {
+ overflow: hidden;
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
+}
+
+.widgets-multi-column-grid ul li {
+ background: none;
+ clear: none;
+ float: left;
+ margin: 0 -5px -3px 0;
+ padding: 0 8px 6px 0;
+ border: none;
+ list-style-type: none !important;
+}
+
+.widgets-multi-column-grid ul li a {
+ background: none;
+ margin: 0;
+ padding: 0;
+ border: 0;
+}
+
+.widgets-multi-column-grid .avatar {
+ vertical-align: middle;
+}
+
+/* List Layout */
+
+.widgets-list-layout {
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
+}
+
+.widgets-list-layout li:before,
+.widgets-list-layout li:after {
+ content:"";
+ display:table;
+}
+.widgets-list-layout li:after {
+ clear:both;
+}
+.widgets-list-layout li {
+ zoom:1;
+ margin-bottom: 1em;
+ list-style-type: none !important;
+}
+
+.widgets-list-layout .widgets-list-layout-blavatar {
+ float: left;
+ width: 21.276596%;
+ max-width: 40px;
+ height: auto;
+}
+
+.widgets-list-layout-links {
+ float: right;
+ width: 73.404255%;
+}
+
+.widgets-list-layout span {
+ opacity: 0.5;
+}
+
+.widgets-list-layout span:hover {
+ opacity: 0.8;
+}
diff --git a/plugins/jetpack/modules/widgets/widgets.css b/plugins/jetpack/modules/widgets/widgets.css
new file mode 100644
index 00000000..a2d62957
--- /dev/null
+++ b/plugins/jetpack/modules/widgets/widgets.css
@@ -0,0 +1,13 @@
+/*
+ * Widget styles for Jetpack
+ */
+
+/* Clear floats */
+.jetpack-image-container:after {
+ clear: both;
+}
+.jetpack-image-container:before,
+.jetpack-image-container:after {
+ display: table;
+ content: "";
+}
diff --git a/plugins/jetpack/readme.txt b/plugins/jetpack/readme.txt
index 60de369f..f4808dd2 100644
--- a/plugins/jetpack/readme.txt
+++ b/plugins/jetpack/readme.txt
@@ -1,9 +1,9 @@
=== Jetpack by WordPress.com ===
-Contributors: automattic, apeatling, beaulebens, hugobaeta, joen, mdawaffe, andy, designsimply, hew, westi, eoigal, tmoorewp, matt
-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
-Requires at least: 3.2
-Tested up to: 3.4.1
-Stable tag: 1.6.1
+Contributors: automattic, apeatling, beaulebens, hugobaeta, Joen, mdawaffe, andy, designsimply, hew, westi, eoigal, tmoorewp, matt, pento, cfinke, daniloercoli, chellycat, gibrown, jblz, jshreve, barry, alternatekev, azaozz, ethitter, johnjamesjacoby, lancewillett, martinremy, nickmomrik, stephdau, yoavf, matveb, jeherve
+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
+Requires at least: 3.3
+Tested up to: 3.5
+Stable tag: 2.2
Supercharge your WordPress site with powerful features previously only available to WordPress.com users.
@@ -18,15 +18,24 @@ Features include:
* Simple, concise stats with no additional load on your server. Previously provided by [WordPress.com Stats](http://wordpress.org/extend/plugins/stats/).
* Email subscriptions for your blog's posts and your post's comments.
* Social networking enabled comment system.
+* Likes, allowing your readers to show their appreciation of your posts.
+* Monitor and manage your site's activity with Notifications in your Toolbar and on WordPress.com.
* Simple, Akismet-backed contact forms.
* The [WP.me URL shortener](http://wp.me/sf2B5-shorten).
* Hovercard popups for your commenters via [Gravatar](http://gravatar.com/).
* Easily embedded media from popular sites like YouTube, Digg, and Vimeo.
+* The ability to post to your blog from any email client.
+* Integration with and automatic posting to your favorite social networks including Twitter, Facebook, Tumblr, and LinkedIn.
* For the Math geeks, a simple way to include beautiful mathematical expressions on your site.
* A widget for displaying recent tweets. Previously provided by [Wickett Twitter Widget](http://wordpress.org/extend/plugins/wickett-twitter-widget/)
* 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.
* Your writing will improve thanks to After the Deadline, an artificial intelligence based spell, style, and grammar checker. Previously provided by the [After the Deadline](http://wordpress.org/extend/plugins/after-the-deadline/) WordPress plugin.
* With Carousel active, any standard WordPress galleries you have embedded in posts or pages will launch a gorgeous full-screen photo browsing experience with comments and EXIF metadata.
+* A CSS editor that lets you customize your site design without modifying your theme.
+* A mobile theme that automatically streamlines your site for visitors on mobile devices.
+* Mobile push notifications for new comments via WordPress mobile apps.
+* The ability to allow applications to securely authenticate and access your site with your permission.
+* Creative formats for your image galleries: mosaic, circles, squares, and a slideshow view.
* and *many* more to come!
Note: The stats portion of Jetpack uses Quantcast to enhance its data.
@@ -59,14 +68,15 @@ Use [shortcodes](http://support.wordpress.com/shortcodes/) to embed your media.
* [[dailymotion]](http://support.wordpress.com/videos/dailymotion/)
* [[digg]](http://support.wordpress.com/digg/)
* [[flickr]](http://support.wordpress.com/videos/flickr-video/)
+* [[googlemaps]](http://en.support.wordpress.com/google-maps/)
* [[googlevideo]](http://support.wordpress.com/videos/google-video/)
* [[polldaddy]](http://support.polldaddy.com/wordpress-shortcodes/)
* [[scribd]](http://support.wordpress.com/scribd/)
* [[slideshare]](http://support.wordpress.com/slideshows/slideshare/)
* [[soundcloud]](http://support.wordpress.com/audio/soundcloud-audio-player/)
+* [[videopress]](http://support.wordpress.com/videopress/)
* [[vimeo]](http://support.wordpress.com/videos/vimeo/)
* [[youtube]](http://support.wordpress.com/videos/youtube/)
-* [[googlemaps]](http://en.support.wordpress.com/google-maps/)
== Screenshots ==
@@ -76,9 +86,236 @@ Use [shortcodes](http://support.wordpress.com/shortcodes/) to embed your media.
4. Gravatar Hovercards settings.
5. Spelling and Grammar demo.
6. Gallery Carousel.
+7. CSS Editor
+8. Mobile Theme
== Changelog ==
+= 2.2 =
+* Enhancement: Likes: Allow your readers to show their appreciation of your posts.
+* Enhancement: Shortcodes: SoundCloud: Update to version 2.3 of the SoundCloud plugin (HTML5 default player, various fixes).
+* Enhancement: Shortcodes: Subscriptions: Add a shortcode to enable placement of a subscription signup form in a post or page.
+* Enhancement: Sharedaddy: Allow selecting multiple images from a post using the Pinterest share button.
+* Enhancement: Contact Form: Allow feedbacks to be marked spam in bulk.
+* Enhancement: Widgets: Readmill Widget: Give your visitors a link to send your book to their Readmill library.
+* Note: Notifications: Discontinue support for Internet Explorer 7 and below.
+* Bug Fix: JSON API: Fix authorization problems that some users were experiencing.
+* Bug Fix: JSON API: Sticky posts were not being sorted correctly in /posts requests.
+* Bug Fix: Stats: sync stats_options so server has roles array needed for view_stats cap check.
+* Bug Fix: Infinite Scroll: Display improvements.
+* Bug Fix: Infinite Scroll: WordPress compatibility fixes.
+* Bug Fix: Photon: Only rewrite iamge urls if the URL is compatible with Photon.
+* Bug Fix: Photon: Account for registered image sizes with one or more dimesions set to zero.
+* Bug Fix: Subscriptions: Make HTML markup more valid.
+* Bug Fix: Subscriptions: Fixed notices displayed in debug mode.
+* Bug Fix: Custom CSS: CSS warnings and errors should now work in environments where JavaScript is concatenated or otherwise modified before being served.
+* Bug Fix: Hovercards: WordPress compatibility fixes.
+* Bug Fix: Improved image handling for the Sharing and Publicize modules.
+* Bug Fix: Carousel: Display and Scrollbar fixes.
+* Bug Fix: Tiled Galleries: Restrict images in tiled galleries from being set larger than their containers.
+* Bug Fix: Widgets: Gravatar Profile: CSS fixes.
+* Bug Fix: Publicize: Strip HTML comments from the data we send to the third party services.
+* Bug Fix: Notifications: Dropped support for IE7 and below in the notifications menu.
+* Bug Fix: Custom CSS Editor: Allow custom themes to save CSS more easily.
+* Bug Fix: Infinite Scroll: Waits until the DOM is ready before loading the scrolling code.
+* Bug Fix: Mobile Theme: If the user has disabled the custom header text color, show the default black header text color.
+* Bug Fix: Mobile Theme: Fix for the "View Full Site" link.
+* Bug Fix: Mobile Theme: Use a filter to modify the output of wp_title().
+* Bug Fix: Publicize: Twitter: Re-enable character count turning red when more than 140 characters are typed.
+
+= 2.1.2 =
+* Enhancement: Infinite Scroll: Introduce filters for Infinite Scroll.
+* Enhancement: Shortcodes: TED shortcode.
+* Bug Fix: Carousel: Make sure to use large image sizes.
+* Bug Fix: Carousel: Clicking the back button in your browser after exiting a carousel gallery brings you back to the gallery.
+* Bug Fix: Carousel: Fix a scrollbar issue.
+* Bug Fix: Comments: Move the get_avatar() function out of the base class.
+* Bug Fix: Contact Form: Prevent the form from displaying i18n characters.
+* Bug Fix: Contact Form: Remove the !important CSS rule.
+* Bug Fix: Infinite Scroll: Main query arguments are not respected when using default permalink.
+* Bug Fix: JSON API: Trap 'wp_die' for new comments and image uploads.
+* Bug Fix: JSON API: Use a better array key for the user_ID.
+* Bug Fix: JSON API: Make the class instantiable only once, but multi-use.
+* Bug Fix: JSON API: Fix lookup of pages by page slug.
+* Bug Fix: JSON API: Updates for post likes.
+* Bug Fix: Mobile Theme: Remove Android download link for BB10 and Playbook.
+* Bug Fix: Open Graph: Stop using Loop functions to get post data for meta tags.
+* Bug Fix: Photon: Suppress and check for warnings when pasing_url and using it.
+* Bug Fix: Photon: Ensure full image size can be used.
+* Bug Fix: Photon: Resolve Photon / YouTube embed conflict.
+* Bug Fix: Photon: Fix dimension parsing from URLs.
+* Bug Fix: Photon: Make sure that width/height atts are greater than zero.
+* Bug Fix: Sharedaddy: Layout fixes for share buttons.
+* Bug Fix: Sharedaddy: Always send Facebook a language locale.
+* Bug Fix: Sharedaddy: Don't look up share counts for empty URLs.
+* Bug Fix: Shortcodes: Ensure that images don't overflow their containers in the slideshow shortcode.
+* Bug Fix: Shortcodes: only enqueue jquery if archive supports Infinite Scroll in the Audio Shortcode.
+* Bug Fix: Tiled Galleries: Use a more specific class for gallery item size to avoid conflicts.
+* Bug Fix: Tiled Galleries: Fixing scrolling issue when tapping on a Tiled Gallery on Android.
+* Bug Fix: Widgets: Gravatar profile widget typo.
+* Bug Fix: Widgets: Add (Jetpack) to widget titles.
+* Bug Fix: Widgets: Twitter wasn't wrapping links in the t.co shortener.
+* Bug Fix: Widgets: Facebook Likebox updates to handling the language locale.
+* Bug Fix: Widgets: Top Posts: Fixed a WP_DEBUG notice.
+* Bug Fix: Widgets: Gravatar Profile Widget: transient names must be less than 45 characters long.
+* Bug Fix: typo in delete_post_action function.
+* Bug Fix: Load rendered LaTeX image on same protocol as its page.
+
+
+= 2.1.1 =
+* Bug Fix: Fix for an error appearing for blogs updating from Jetpack 1.9.2 or earlier to 2.1.
+
+= 2.1 =
+* Enhancement: Tiled Galleries: Show off your photos with cool mosaic galleries.
+* Enhancement: Slideshow gallery type: Display any gallery as a slideshow.
+* Enhancement: Custom CSS: Allow zoom property.
+* Enhancement: Stats: Show WordPress.com subscribers in stats.
+* Bug Fix: Fix errors shown after connecting Jetpack to WordPress.com.
+* Bug Fix: Photon: Fix bug causing errors to be shown in some posts.
+* Bug Fix: Photon: Convert all images in posts when Photon is active.
+* Bug Fix: Infinite Scroll: Improved compatibility with the other modules.
+* Bug Fix: Custom CSS: Updated editor to fix missing file errors.
+* Bug Fix: Publicize: Don't show the Facebook profile option if this is a Page-only account.
+* Bug Fix: Photon: A fix for photos appearing shrunken if they didn't load quickly enough.
+* Bug Fix: Sharing: A compatibility fix for posts that only have partial featured image data.
+* Bug Fix: Publicize/Sharing: For sites without a static homepage, don't set the OpenGraph url value to the first post permalink.
+* Bug Fix: Mobile Theme: Better compatibility with the customizer on mobile devices.
+* Bug Fix: Sharing: Don't show sharing options on front page if that option is turned off.
+* Bug Fix: Contact Form: Fix PHP warning shown when adding a Contact Form in WordPress 3.5.
+* Bug Fix: Photon: Handle images with relative paths.
+* Bug Fix: Contact Form: Fix compatibility with the Shortcode Embeds module.
+
+
+= 2.0.4 =
+* Bug Fix: Open Graph: Correct a bug that prevents Jetpack from being activated if the SharePress plugin isn't installed.
+
+= 2.0.3 =
+* Enhancement: Infinite Scroll: support [VideoPress](http://wordpress.org/extend/plugins/video/) plugin.
+* Enhancement: Photon: Apply to all images retrieved from the Media Library.
+* Enhancement: Photon: Retina image support.
+* Enhancement: Custom CSS: Refined editor interface.
+* Enhancement: Custom CSS: Support [Sass](http://sass-lang.com/) and [LESS](http://lesscss.org/) with built-in preprocessors.
+* Enhancement: Open Graph: Better checks for other plugins that may be loading Open Graph tags to prevent Jetpack from doubling meta tag output.
+* Bug Fix: Infinite Scroll: Respect relative image dimensions.
+* Bug Fix: Photon: Detect custom-cropped images and use those with Photon, rather than trying to use the original.
+* Bug Fix: Custom CSS: Fix for bug preventing @import from working with url()-style URLs.
+
+= 2.0.2 =
+* Bug Fix: Remove an erroneous PHP short open tag with the full tag to correct fatal errors under certain PHP configurations.
+
+= 2.0.1 =
+* Enhancement: Photon: Support for the [Lazy Load](http://wordpress.org/extend/plugins/lazy-load/) plugin.
+* Bug Fix: Photon: Fix warped images with un- or under-specified dimensions.
+* Bug Fix: Photon: Fix warped images with pre-photonized URLs; don't try to photonize them twice.
+* Bug Fix: Infinite Scroll: Check a child theme's parent theme for infinite scroll support.
+* Bug Fix: Infinite Scroll: Correct a bug with archives that resulted in posts appearing on archives that they didn't belong on.
+* Bug Fix: Publicize: Send the correct shortlink to Twitter (et al.) if your site uses a shortener other than wp.me.
+* Bug Fix: Sharing: Improved theme compatibility for the Google+ button.
+* Bug Fix: Notifications: Use locally-installed Javascript libraries if available.
+
+= 2.0 =
+* Enhancement: Publicize: Connect your site to popular social networks and automatically share new posts with your friends.
+* Enhancement: Post By Email: Publish posts to your blog directly from your personal email account.
+* Enhancement: Photon: Images served through the global WordPress.com cloud.
+* Enhancement: Infinite Scroll: Better/faster browsing by pulling the next set of posts into view automatically when the reader approaches the bottom of the page.
+* Enhancement: Open Graph: Provides more detailed information about your posts to social networks.
+* Enhancement: JSON API: New parameters for creating and viewing posts.
+* Enhancement: Improved compatibility for the upcoming WordPress 3.5.
+* Bug Fix: Sharing: When you set your sharing buttons to use icon, text, or icon + text mode, the Google+ button will display accordingly.
+* Bug Fix: Gravatar Profile Widget: Allow basic HTML to be displayed.
+* Bug Fix: Twitter Widget: Error handling fixes.
+* Bug Fix: Sharing: Improved theme compatibility
+* Bug Fix: JSON API: Fixed error when creating some posts in some versions of PHP.
+
+= 1.9.2 =
+* Bug Fix: Only sync options on upgrade once.
+
+= 1.9.1 =
+* Enhancement: Notifications feature is enabled for logged-out users when the module is active & the toolbar is shown by another plugin.
+* Bug Fix: Use proper CDN addresses to avoid SSL cert issues.
+* Bug Fix: Prioritize syncing comments over deleting comments on WordPress.com. Fixes comment notifications marked as spam appearing to be trashed.
+
+= 1.9 =
+* Enhancement: Notifications: Display Notifications in the toolbar and support reply/moderation of comment notifications.
+* Enhancement: Mobile Push Notifications: Added support for mobile push notifications of new comments for users that linked their accounts to WordPress.com accounts.
+* Enhancement: JSON API: Allows applications to send API requests via WordPress.com (see [the docs](http://developer.wordpress.com/docs/api/) )
+* Enhancement: Sync: Modules (that require the data) sync full Post/Comment to ensure consistent data on WP.com (eg Stats)
+* Enhancement: Sync: Improve syncing of site options to WP.com
+* Enhancement: Sync: Sync attachment parents to WP.com
+* Enhancement: Sync: Add signing of WP.com user ids for Jetpack Comments
+* Enhancement: Sync: Mark and obfuscate private posts.
+* Enhancement: Privacy: Default disable enhanced-distribution and json-api modules if site appears to be private.
+* Enhancement: Custom CSS: allow applying Custom CSS to mobile theme.
+* Enhancement: Sharing: On HTTPS pageloads, load as much of the sharing embeds as possible from HTTPS URLs.
+* Enhancement: Contact Form: Overhaul of the contact form code to fix incompatibilites with other plugins.
+* Bug Fix: Only allow users with manage_options permission to enable/disable modules
+* Bug Fix: Custom CSS: allow '/' in media query units; e.g. (-o-min-device-pixel-ratio: 3/2)
+* Bug Fix: Custom CSS: leave comments alone in CSS when editing but minify on the frontend
+* Bug Fix: Sharing: Keep "more" pane open so Google+ Button isn't obscured
+* Bug Fix: Carousel: Make sure the original size is used, even when it is exceedingly large.
+* Bug Fix: Exclude iPad from Twitter on iPhone mobile browsing
+* Bug Fix: Sync: On .org user role changes synchronize the change to .com
+* Bug Fix: Contact Form: Fix a bug where some web hosts would reject mail from the contact form due to email address spoofing.
+
+= 1.8.3 =
+* Bug Fix: Subscriptions: Fix a bug where subscriptions were not being sent from the blog.
+* Bug Fix: Twitter: Fix a bug where the Twitter username was being saved as blank.
+* Bug Fix: Fix a bug where Contact Form notification emails were not being sent.
+
+= 1.8.2 =
+* Bug Fix: Subscriptions: Fix a bug where subscriptions were not sent for posts and comments written by some authors.
+* Bug Fix: Widgets: Fix CSS that was uglifying some themes (like P2).
+* Bug Fix: Widgets: Improve Top Posts and Pages styling.
+* Bug Fix: Custom CSS: Make the default "Welcome" message translatable.
+* Bug Fix: Fix Lithuanian translation.
+
+= 1.8.1 =
+* Bug Fix: Stats: Fixed a bug preventing some users from viewing stats.
+* Bug Fix: Mobile Theme: Fixed some disabled toolbar buttons.
+* Bug Fix: Top Posts widget: Fixed a bug preventing the usage of the Top Posts widget.
+* Bug Fix: Mobile Theme: Fixed a bug that broke some sites when the Subscriptions module was not enabled and the Mobile Theme module was enabled.
+* Bug Fix: Mobile Theme: Made mobile app promos in the Mobile Theme footer opt-in.
+* Bug Fix: Twitter Widget: A fix to prevent malware warnings.
+* Bug Fix: Mobile Theme: Fixed a bug that caused errors for some users with custom header images.
+
+= 1.8 =
+* Enhancement: Mobile Theme: Automatically serve a slimmed down version of your site to users on mobile devices.
+* Enhancement: Multiuser: Allow multiple users to link their accounts to WordPress.com accounts.
+* Enhancement: Custom CSS: Added support for object-fit, object-position, transition, and filter properties.
+* Enhancement: Twitter Widget: Added Follow button
+* Enhancement: Widgets: Added Top Posts and Pages widget
+* Enhancement: Mobile Push Notifications: Added support for mobile push notifications on new comments.
+* Enhancement: VideoPress: Shortcodes now support the HD option, for default HD playback.
+* Bug Fix: Twitter Widget: Fixed tweet permalinks in the Twitter widget
+* Bug Fix: Custom CSS: @import rules and external images are no longer stripped out of custom CSS
+* Bug Fix: Custom CSS: Fixed warnings and notices displayed in debug mode
+* Bug Fix: Sharing: Fixed double-encoding of image URLs
+* Bug Fix: Sharing: Fix Google +1 button HTML validation issues (again :))
+* Bug Fix: Gravatar Profile Widget: Reduce size of header margins
+
+= 1.7 =
+* Enhancement: CSS Editor: Customize your site's design without modifying your theme.
+* Enhancement: Comments: Submit the comment within the iframe. No more full page load to jetpack.wordpress.com.
+* Enhancement: Sharing: Share counts for Twitter, Facebook, LinkedIn
+* Enhancement: Sharing: Improve styling
+* Enhancement: Sharing: Add support for ReCaptcha
+* Enhancement: Sharing: Better extensability through filters
+* Enhancement: Widgets: Twitter: Attempt to reduce errors by storing a long lasting copy of the data. Thanks, kareldonk :)
+* Regression Fix: Sharing: Properly store and display the sharing label option's default value.
+* Bug Fix: Contact Form: remove worse-than-useless nonce.
+* Bug Fix: Subscriptions: remove worse-than-useless nonce.
+* Bug Fix: Sharing: Don't show sharing buttons twice on attachment pages.
+* Bug Fix: Sharing: Increase width of Spanish Like button for Facebook.
+* Bug Fix: Sharing: Use the correct URL to the throbber.
+* Bug Fix: Stats: Fix notice about undefined variable $alt
+* Bug Fix: Subscriptions: Make Subscriptions module obey the settings of the Settngs -> Discussion checkboxes for Follow Blog/Comments
+* Bug Fix: Shortcodes: VideoPress: Compatibility with the latest version of VideoPress
+* Bug Fix: Shortcodes: Audio: Include JS File for HTML5 audio player
+* Bug Fix: Hovercards: Improve cache handling.
+* Bug Fix: Widgets: Gravatar Profle: Correctly display service icons in edge cases.
+* Bug Fix: Widgets: Gravatar Profle: Prevent ugly "flash" of too-large image when page first loads on some sites
+* Bug Fix: Carousel: CSS Compatibility with more themes.
+
= 1.6.1 =
* Bug Fix: Prevent Fatal error under certain conditions in sharing module
* Bug Fix: Add cachebuster to sharing.css
@@ -135,7 +372,7 @@ Use [shortcodes](http://support.wordpress.com/shortcodes/) to embed your media.
= 1.3.2 =
* Bug Fix: Fix Jetpack menu so that Akismet and VaultPress submenus show up.
-= 1.3.1 =
+= 1.3.1 =
* Enhancement: Add a new widget, the Facebook Likebox
* Bug Fix: Sharing: Sharing buttons can now be used on custom post types.
* Bug Fix: Contact Forms: Make Contact Forms widget shortcode less aggressive about the shortcodes it converts.
diff --git a/plugins/openid/admin_panels.php b/plugins/openid/admin_panels.php
index f448dc77..d373d5ce 100644
--- a/plugins/openid/admin_panels.php
+++ b/plugins/openid/admin_panels.php
@@ -741,7 +741,6 @@ function openid_profile_delete_openids($delete) {
openid_status('success');
// ensure that profile URL is still a verified OpenID
- set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once 'Auth/OpenID.php';
@include_once(ABSPATH . WPINC . '/registration.php'); // WP < 2.3
@include_once(ABSPATH . 'wp-admin/includes/admin.php'); // WP >= 2.3
@@ -781,7 +780,6 @@ function openid_finish_verify($identity_url, $action) {
$message = 3;
// ensure that profile URL is a verified OpenID
- set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once 'Auth/OpenID.php';
require_once(ABSPATH . 'wp-admin/includes/admin.php');
@@ -824,7 +822,6 @@ function openid_ensure_url_match($user, $url = null) {
$identities = get_user_openids($user->ID);
if (empty($identities)) return true;
- set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once 'Auth/OpenID.php';
if ($url == null) $url = $user->user_url;
diff --git a/plugins/openid/common.php b/plugins/openid/common.php
index 07a67b57..b3a4b12a 100644
--- a/plugins/openid/common.php
+++ b/plugins/openid/common.php
@@ -223,7 +223,7 @@ function openid_generate_new_username($url, $append = true) {
$i='';
while(true) {
$username = openid_normalize_username( $base . $i );
- $user = get_userdatabylogin($username);
+ $user = get_user_by('login', $username);
if ( $user ) {
if (!$append) return null;
$i++;
@@ -422,9 +422,7 @@ function openid_get_user_data($identity_url) {
* @see get_user_data
*/
function openid_get_user_data_ax($data, $identity_url) {
- set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once('Auth/OpenID/AX.php');
- restore_include_path();
$response = openid_response();
$ax = Auth_OpenID_AX_FetchResponse::fromSuccessResponse($response);
@@ -463,7 +461,7 @@ function openid_get_user_data_ax($data, $identity_url) {
* @see get_user_data
*/
function openid_get_user_data_sreg($data, $identity_url) {
- require_once(dirname(__FILE__) . '/Auth/OpenID/SReg.php');
+ require_once('Auth/OpenID/SReg.php');
$response = openid_response();
$sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);
$sreg = $sreg_resp->contents();
@@ -540,7 +538,7 @@ function openid_parse_request($wp) {
case 'ajax':
if ( check_admin_referer('openid_ajax') ) {
header('Content-Type: application/json');
- echo '{ valid:' . ( is_url_openid( $_REQUEST['url'] ) ? 'true' : 'false' ) . ', nonce:"' . wp_create_nonce('openid_ajax') . '" }';
+ echo '{ "valid":' . ( is_url_openid( $_REQUEST['url'] ) ? 'true' : 'false' ) . ', "nonce":"' . wp_create_nonce('openid_ajax') . '" }';
exit;
}
}
diff --git a/plugins/openid/consumer.php b/plugins/openid/consumer.php
index d88eeac0..d12aabdb 100644
--- a/plugins/openid/consumer.php
+++ b/plugins/openid/consumer.php
@@ -19,9 +19,7 @@ function openid_getConsumer() {
static $consumer;
if (!$consumer) {
- set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once 'Auth/OpenID/Consumer.php';
- restore_include_path();
$store = openid_getStore();
$consumer = new Auth_OpenID_Consumer($store);
@@ -185,9 +183,7 @@ function openid_start_login( $claimed_url, $action, $finish_url = null) {
*/
function openid_add_ax_extension($extensions, $auth_request) {
if(!get_user_by_openid($auth_request->endpoint->claimed_id)) {
- set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once('Auth/OpenID/AX.php');
- restore_include_path();
if ($auth_request->endpoint->usesExtension(Auth_OpenID_AX_NS_URI)) {
$ax_request = new Auth_OpenID_AX_FetchRequest();
@@ -208,9 +204,7 @@ function openid_add_ax_extension($extensions, $auth_request) {
*/
function openid_add_sreg_extension($extensions, $auth_request) {
if(!get_user_by_openid($auth_request->endpoint->claimed_id)) {
- set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once('Auth/OpenID/SReg.php');
- restore_include_path();
if ($auth_request->endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_0) || $auth_request->endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_1)) {
$extensions[] = Auth_OpenID_SRegRequest::build(array(),array('nickname','email','fullname'));
diff --git a/plugins/openid/lib/Auth/OpenID.php b/plugins/openid/lib/Auth/OpenID.php
new file mode 100644
index 00000000..c9d97796
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID.php
@@ -0,0 +1,563 @@
+<?php
+
+/**
+ * This is the PHP OpenID library by JanRain, Inc.
+ *
+ * This module contains core utility functionality used by the
+ * library. See Consumer.php and Server.php for the consumer and
+ * server implementations.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * The library version string
+ */
+define('Auth_OpenID_VERSION', '2.2.2');
+
+/**
+ * Require the fetcher code.
+ */
+require_once "Auth/Yadis/PlainHTTPFetcher.php";
+require_once "Auth/Yadis/ParanoidHTTPFetcher.php";
+require_once "Auth/OpenID/BigMath.php";
+require_once "Auth/OpenID/URINorm.php";
+
+/**
+ * Status code returned by the server when the only option is to show
+ * an error page, since we do not have enough information to redirect
+ * back to the consumer. The associated value is an error message that
+ * should be displayed on an HTML error page.
+ *
+ * @see Auth_OpenID_Server
+ */
+define('Auth_OpenID_LOCAL_ERROR', 'local_error');
+
+/**
+ * Status code returned when there is an error to return in key-value
+ * form to the consumer. The caller should return a 400 Bad Request
+ * response with content-type text/plain and the value as the body.
+ *
+ * @see Auth_OpenID_Server
+ */
+define('Auth_OpenID_REMOTE_ERROR', 'remote_error');
+
+/**
+ * Status code returned when there is a key-value form OK response to
+ * the consumer. The value associated with this code is the
+ * response. The caller should return a 200 OK response with
+ * content-type text/plain and the value as the body.
+ *
+ * @see Auth_OpenID_Server
+ */
+define('Auth_OpenID_REMOTE_OK', 'remote_ok');
+
+/**
+ * Status code returned when there is a redirect back to the
+ * consumer. The value is the URL to redirect back to. The caller
+ * should return a 302 Found redirect with a Location: header
+ * containing the URL.
+ *
+ * @see Auth_OpenID_Server
+ */
+define('Auth_OpenID_REDIRECT', 'redirect');
+
+/**
+ * Status code returned when the caller needs to authenticate the
+ * user. The associated value is a {@link Auth_OpenID_ServerRequest}
+ * object that can be used to complete the authentication. If the user
+ * has taken some authentication action, use the retry() method of the
+ * {@link Auth_OpenID_ServerRequest} object to complete the request.
+ *
+ * @see Auth_OpenID_Server
+ */
+define('Auth_OpenID_DO_AUTH', 'do_auth');
+
+/**
+ * Status code returned when there were no OpenID arguments
+ * passed. This code indicates that the caller should return a 200 OK
+ * response and display an HTML page that says that this is an OpenID
+ * server endpoint.
+ *
+ * @see Auth_OpenID_Server
+ */
+define('Auth_OpenID_DO_ABOUT', 'do_about');
+
+/**
+ * Defines for regexes and format checking.
+ */
+define('Auth_OpenID_letters',
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+
+define('Auth_OpenID_digits',
+ "0123456789");
+
+define('Auth_OpenID_punct',
+ "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");
+
+Auth_OpenID_include_init();
+
+/**
+ * The OpenID utility function class.
+ *
+ * @package OpenID
+ * @access private
+ */
+class Auth_OpenID {
+
+ /**
+ * Return true if $thing is an Auth_OpenID_FailureResponse object;
+ * false if not.
+ *
+ * @access private
+ */
+ static function isFailure($thing)
+ {
+ return is_a($thing, 'Auth_OpenID_FailureResponse');
+ }
+
+ /**
+ * Gets the query data from the server environment based on the
+ * request method used. If GET was used, this looks at
+ * $_SERVER['QUERY_STRING'] directly. If POST was used, this
+ * fetches data from the special php://input file stream.
+ *
+ * Returns an associative array of the query arguments.
+ *
+ * Skips invalid key/value pairs (i.e. keys with no '=value'
+ * portion).
+ *
+ * Returns an empty array if neither GET nor POST was used, or if
+ * POST was used but php://input cannot be opened.
+ *
+ * See background:
+ * http://lists.openidenabled.com/pipermail/dev/2007-March/000395.html
+ *
+ * @access private
+ */
+ static function getQuery($query_str=null)
+ {
+ $data = array();
+
+ if ($query_str !== null) {
+ $data = Auth_OpenID::params_from_string($query_str);
+ } else if (!array_key_exists('REQUEST_METHOD', $_SERVER)) {
+ // Do nothing.
+ } else {
+ // XXX HACK FIXME HORRIBLE.
+ //
+ // POSTing to a URL with query parameters is acceptable, but
+ // we don't have a clean way to distinguish those parameters
+ // when we need to do things like return_to verification
+ // which only want to look at one kind of parameter. We're
+ // going to emulate the behavior of some other environments
+ // by defaulting to GET and overwriting with POST if POST
+ // data is available.
+ $data = Auth_OpenID::params_from_string($_SERVER['QUERY_STRING']);
+
+ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ $str = file_get_contents('php://input');
+
+ if ($str === false) {
+ $post = array();
+ } else {
+ $post = Auth_OpenID::params_from_string($str);
+ }
+
+ $data = array_merge($data, $post);
+ }
+ }
+
+ return $data;
+ }
+
+ static function params_from_string($str)
+ {
+ $chunks = explode("&", $str);
+
+ $data = array();
+ foreach ($chunks as $chunk) {
+ $parts = explode("=", $chunk, 2);
+
+ if (count($parts) != 2) {
+ continue;
+ }
+
+ list($k, $v) = $parts;
+ $data[urldecode($k)] = urldecode($v);
+ }
+
+ return $data;
+ }
+
+ /**
+ * Create dir_name as a directory if it does not exist. If it
+ * exists, make sure that it is, in fact, a directory. Returns
+ * true if the operation succeeded; false if not.
+ *
+ * @access private
+ */
+ static function ensureDir($dir_name)
+ {
+ if (is_dir($dir_name) || @mkdir($dir_name)) {
+ return true;
+ } else {
+ $parent_dir = dirname($dir_name);
+
+ // Terminal case; there is no parent directory to create.
+ if ($parent_dir == $dir_name) {
+ return true;
+ }
+
+ return (Auth_OpenID::ensureDir($parent_dir) && @mkdir($dir_name));
+ }
+ }
+
+ /**
+ * Adds a string prefix to all values of an array. Returns a new
+ * array containing the prefixed values.
+ *
+ * @access private
+ */
+ static function addPrefix($values, $prefix)
+ {
+ $new_values = array();
+ foreach ($values as $s) {
+ $new_values[] = $prefix . $s;
+ }
+ return $new_values;
+ }
+
+ /**
+ * Convenience function for getting array values. Given an array
+ * $arr and a key $key, get the corresponding value from the array
+ * or return $default if the key is absent.
+ *
+ * @access private
+ */
+ static function arrayGet($arr, $key, $fallback = null)
+ {
+ if (is_array($arr)) {
+ if (array_key_exists($key, $arr)) {
+ return $arr[$key];
+ } else {
+ return $fallback;
+ }
+ } else {
+ trigger_error("Auth_OpenID::arrayGet (key = ".$key.") expected " .
+ "array as first parameter, got " .
+ gettype($arr), E_USER_WARNING);
+
+ return false;
+ }
+ }
+
+ /**
+ * Replacement for PHP's broken parse_str.
+ */
+ static function parse_str($query)
+ {
+ if ($query === null) {
+ return null;
+ }
+
+ $parts = explode('&', $query);
+
+ $new_parts = array();
+ for ($i = 0; $i < count($parts); $i++) {
+ $pair = explode('=', $parts[$i]);
+
+ if (count($pair) != 2) {
+ continue;
+ }
+
+ list($key, $value) = $pair;
+ $new_parts[urldecode($key)] = urldecode($value);
+ }
+
+ return $new_parts;
+ }
+
+ /**
+ * Implements the PHP 5 'http_build_query' functionality.
+ *
+ * @access private
+ * @param array $data Either an array key/value pairs or an array
+ * of arrays, each of which holding two values: a key and a value,
+ * sequentially.
+ * @return string $result The result of url-encoding the key/value
+ * pairs from $data into a URL query string
+ * (e.g. "username=bob&id=56").
+ */
+ static function httpBuildQuery($data)
+ {
+ $pairs = array();
+ foreach ($data as $key => $value) {
+ if (is_array($value)) {
+ $pairs[] = urlencode($value[0])."=".urlencode($value[1]);
+ } else {
+ $pairs[] = urlencode($key)."=".urlencode($value);
+ }
+ }
+ return implode("&", $pairs);
+ }
+
+ /**
+ * "Appends" query arguments onto a URL. The URL may or may not
+ * already have arguments (following a question mark).
+ *
+ * @access private
+ * @param string $url A URL, which may or may not already have
+ * arguments.
+ * @param array $args Either an array key/value pairs or an array of
+ * arrays, each of which holding two values: a key and a value,
+ * sequentially. If $args is an ordinary key/value array, the
+ * parameters will be added to the URL in sorted alphabetical order;
+ * if $args is an array of arrays, their order will be preserved.
+ * @return string $url The original URL with the new parameters added.
+ *
+ */
+ static function appendArgs($url, $args)
+ {
+ if (count($args) == 0) {
+ return $url;
+ }
+
+ // Non-empty array; if it is an array of arrays, use
+ // multisort; otherwise use sort.
+ if (array_key_exists(0, $args) &&
+ is_array($args[0])) {
+ // Do nothing here.
+ } else {
+ $keys = array_keys($args);
+ sort($keys);
+ $new_args = array();
+ foreach ($keys as $key) {
+ $new_args[] = array($key, $args[$key]);
+ }
+ $args = $new_args;
+ }
+
+ $sep = '?';
+ if (strpos($url, '?') !== false) {
+ $sep = '&';
+ }
+
+ return $url . $sep . Auth_OpenID::httpBuildQuery($args);
+ }
+
+ /**
+ * Implements python's urlunparse, which is not available in PHP.
+ * Given the specified components of a URL, this function rebuilds
+ * and returns the URL.
+ *
+ * @access private
+ * @param string $scheme The scheme (e.g. 'http'). Defaults to 'http'.
+ * @param string $host The host. Required.
+ * @param string $port The port.
+ * @param string $path The path.
+ * @param string $query The query.
+ * @param string $fragment The fragment.
+ * @return string $url The URL resulting from assembling the
+ * specified components.
+ */
+ static function urlunparse($scheme, $host, $port = null, $path = '/',
+ $query = '', $fragment = '')
+ {
+
+ if (!$scheme) {
+ $scheme = 'http';
+ }
+
+ if (!$host) {
+ return false;
+ }
+
+ if (!$path) {
+ $path = '';
+ }
+
+ $result = $scheme . "://" . $host;
+
+ if ($port) {
+ $result .= ":" . $port;
+ }
+
+ $result .= $path;
+
+ if ($query) {
+ $result .= "?" . $query;
+ }
+
+ if ($fragment) {
+ $result .= "#" . $fragment;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Given a URL, this "normalizes" it by adding a trailing slash
+ * and / or a leading http:// scheme where necessary. Returns
+ * null if the original URL is malformed and cannot be normalized.
+ *
+ * @access private
+ * @param string $url The URL to be normalized.
+ * @return mixed $new_url The URL after normalization, or null if
+ * $url was malformed.
+ */
+ static function normalizeUrl($url)
+ {
+ @$parsed = parse_url($url);
+
+ if (!$parsed) {
+ return null;
+ }
+
+ if (isset($parsed['scheme']) &&
+ isset($parsed['host'])) {
+ $scheme = strtolower($parsed['scheme']);
+ if (!in_array($scheme, array('http', 'https'))) {
+ return null;
+ }
+ } else {
+ $url = 'http://' . $url;
+ }
+
+ $normalized = Auth_OpenID_urinorm($url);
+ if ($normalized === null) {
+ return null;
+ }
+ list($defragged, $frag) = Auth_OpenID::urldefrag($normalized);
+ return $defragged;
+ }
+
+ /**
+ * Replacement (wrapper) for PHP's intval() because it's broken.
+ *
+ * @access private
+ */
+ static function intval($value)
+ {
+ $re = "/^\\d+$/";
+
+ if (!preg_match($re, $value)) {
+ return false;
+ }
+
+ return intval($value);
+ }
+
+ /**
+ * Count the number of bytes in a string independently of
+ * multibyte support conditions.
+ *
+ * @param string $str The string of bytes to count.
+ * @return int The number of bytes in $str.
+ */
+ static function bytes($str)
+ {
+ return strlen(bin2hex($str)) / 2;
+ }
+
+ /**
+ * Get the bytes in a string independently of multibyte support
+ * conditions.
+ */
+ static function toBytes($str)
+ {
+ $hex = bin2hex($str);
+
+ if (!$hex) {
+ return array();
+ }
+
+ $b = array();
+ for ($i = 0; $i < strlen($hex); $i += 2) {
+ $b[] = chr(base_convert(substr($hex, $i, 2), 16, 10));
+ }
+
+ return $b;
+ }
+
+ static function urldefrag($url)
+ {
+ $parts = explode("#", $url, 2);
+
+ if (count($parts) == 1) {
+ return array($parts[0], "");
+ } else {
+ return $parts;
+ }
+ }
+
+ static function filter($callback, &$sequence)
+ {
+ $result = array();
+
+ foreach ($sequence as $item) {
+ if (call_user_func_array($callback, array($item))) {
+ $result[] = $item;
+ }
+ }
+
+ return $result;
+ }
+
+ static function update(&$dest, &$src)
+ {
+ foreach ($src as $k => $v) {
+ $dest[$k] = $v;
+ }
+ }
+
+ /**
+ * Wrap PHP's standard error_log functionality. Use this to
+ * perform all logging. It will interpolate any additional
+ * arguments into the format string before logging.
+ *
+ * @param string $format_string The sprintf format for the message
+ */
+ static function log($format_string)
+ {
+ $args = func_get_args();
+ $message = call_user_func_array('sprintf', $args);
+ error_log($message);
+ }
+
+ static function autoSubmitHTML($form, $title="OpenId transaction in progress")
+ {
+ return("<html>".
+ "<head><title>".
+ $title .
+ "</title></head>".
+ "<body onload='document.forms[0].submit();'>".
+ $form .
+ "<script>".
+ "var elements = document.forms[0].elements;".
+ "for (var i = 0; i < elements.length; i++) {".
+ " elements[i].style.display = \"none\";".
+ "}".
+ "</script>".
+ "</body>".
+ "</html>");
+ }
+}
+
+/*
+ * Function to run when this file is included.
+ * Abstracted to a function to make life easier
+ * for some PHP optimizers.
+ */
+function Auth_OpenID_include_init() {
+ if (Auth_OpenID_getMathLib() === null) {
+ Auth_OpenID_setNoMathSupport();
+ }
+}
diff --git a/plugins/openid/lib/Auth/OpenID/AX.php b/plugins/openid/lib/Auth/OpenID/AX.php
new file mode 100644
index 00000000..7370715e
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/AX.php
@@ -0,0 +1,1022 @@
+<?php
+
+/**
+ * Implements the OpenID attribute exchange specification, version 1.0
+ * as of svn revision 370 from openid.net svn.
+ *
+ * @package OpenID
+ */
+
+/**
+ * Require utility classes and functions for the consumer.
+ */
+require_once "Auth/OpenID/Extension.php";
+require_once "Auth/OpenID/Message.php";
+require_once "Auth/OpenID/TrustRoot.php";
+
+define('Auth_OpenID_AX_NS_URI',
+ 'http://openid.net/srv/ax/1.0');
+
+// Use this as the 'count' value for an attribute in a FetchRequest to
+// ask for as many values as the OP can provide.
+define('Auth_OpenID_AX_UNLIMITED_VALUES', 'unlimited');
+
+// Minimum supported alias length in characters. Here for
+// completeness.
+define('Auth_OpenID_AX_MINIMUM_SUPPORTED_ALIAS_LENGTH', 32);
+
+/**
+ * AX utility class.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX {
+ /**
+ * @param mixed $thing Any object which may be an
+ * Auth_OpenID_AX_Error object.
+ *
+ * @return bool true if $thing is an Auth_OpenID_AX_Error; false
+ * if not.
+ */
+ static function isError($thing)
+ {
+ return is_a($thing, 'Auth_OpenID_AX_Error');
+ }
+}
+
+/**
+ * Check an alias for invalid characters; raise AXError if any are
+ * found. Return None if the alias is valid.
+ */
+function Auth_OpenID_AX_checkAlias($alias)
+{
+ if (strpos($alias, ',') !== false) {
+ return new Auth_OpenID_AX_Error(sprintf(
+ "Alias %s must not contain comma", $alias));
+ }
+ if (strpos($alias, '.') !== false) {
+ return new Auth_OpenID_AX_Error(sprintf(
+ "Alias %s must not contain period", $alias));
+ }
+
+ return true;
+}
+
+/**
+ * Results from data that does not meet the attribute exchange 1.0
+ * specification
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX_Error {
+ function Auth_OpenID_AX_Error($message=null)
+ {
+ $this->message = $message;
+ }
+}
+
+/**
+ * Abstract class containing common code for attribute exchange
+ * messages.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX_Message extends Auth_OpenID_Extension {
+ /**
+ * ns_alias: The preferred namespace alias for attribute exchange
+ * messages
+ */
+ var $ns_alias = 'ax';
+
+ /**
+ * mode: The type of this attribute exchange message. This must be
+ * overridden in subclasses.
+ */
+ var $mode = null;
+
+ var $ns_uri = Auth_OpenID_AX_NS_URI;
+
+ /**
+ * Return Auth_OpenID_AX_Error if the mode in the attribute
+ * exchange arguments does not match what is expected for this
+ * class; true otherwise.
+ *
+ * @access private
+ */
+ function _checkMode($ax_args)
+ {
+ $mode = Auth_OpenID::arrayGet($ax_args, 'mode');
+ if ($mode != $this->mode) {
+ return new Auth_OpenID_AX_Error(
+ sprintf(
+ "Expected mode '%s'; got '%s'",
+ $this->mode, $mode));
+ }
+
+ return true;
+ }
+
+ /**
+ * Return a set of attribute exchange arguments containing the
+ * basic information that must be in every attribute exchange
+ * message.
+ *
+ * @access private
+ */
+ function _newArgs()
+ {
+ return array('mode' => $this->mode);
+ }
+}
+
+/**
+ * Represents a single attribute in an attribute exchange
+ * request. This should be added to an AXRequest object in order to
+ * request the attribute.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX_AttrInfo {
+ /**
+ * Construct an attribute information object. Do not call this
+ * directly; call make(...) instead.
+ *
+ * @param string $type_uri The type URI for this attribute.
+ *
+ * @param int $count The number of values of this type to request.
+ *
+ * @param bool $required Whether the attribute will be marked as
+ * required in the request.
+ *
+ * @param string $alias The name that should be given to this
+ * attribute in the request.
+ */
+ function Auth_OpenID_AX_AttrInfo($type_uri, $count, $required,
+ $alias)
+ {
+ /**
+ * required: Whether the attribute will be marked as required
+ * when presented to the subject of the attribute exchange
+ * request.
+ */
+ $this->required = $required;
+
+ /**
+ * count: How many values of this type to request from the
+ * subject. Defaults to one.
+ */
+ $this->count = $count;
+
+ /**
+ * type_uri: The identifier that determines what the attribute
+ * represents and how it is serialized. For example, one type
+ * URI representing dates could represent a Unix timestamp in
+ * base 10 and another could represent a human-readable
+ * string.
+ */
+ $this->type_uri = $type_uri;
+
+ /**
+ * alias: The name that should be given to this attribute in
+ * the request. If it is not supplied, a generic name will be
+ * assigned. For example, if you want to call a Unix timestamp
+ * value 'tstamp', set its alias to that value. If two
+ * attributes in the same message request to use the same
+ * alias, the request will fail to be generated.
+ */
+ $this->alias = $alias;
+ }
+
+ /**
+ * Construct an attribute information object. For parameter
+ * details, see the constructor.
+ */
+ static function make($type_uri, $count=1, $required=false,
+ $alias=null)
+ {
+ if ($alias !== null) {
+ $result = Auth_OpenID_AX_checkAlias($alias);
+
+ if (Auth_OpenID_AX::isError($result)) {
+ return $result;
+ }
+ }
+
+ return new Auth_OpenID_AX_AttrInfo($type_uri, $count, $required,
+ $alias);
+ }
+
+ /**
+ * When processing a request for this attribute, the OP should
+ * call this method to determine whether all available attribute
+ * values were requested. If self.count == UNLIMITED_VALUES, this
+ * returns True. Otherwise this returns False, in which case
+ * self.count is an integer.
+ */
+ function wantsUnlimitedValues()
+ {
+ return $this->count === Auth_OpenID_AX_UNLIMITED_VALUES;
+ }
+}
+
+/**
+ * Given a namespace mapping and a string containing a comma-separated
+ * list of namespace aliases, return a list of type URIs that
+ * correspond to those aliases.
+ *
+ * @param $namespace_map The mapping from namespace URI to alias
+ * @param $alias_list_s The string containing the comma-separated
+ * list of aliases. May also be None for convenience.
+ *
+ * @return $seq The list of namespace URIs that corresponds to the
+ * supplied list of aliases. If the string was zero-length or None, an
+ * empty list will be returned.
+ *
+ * return null If an alias is present in the list of aliases but
+ * is not present in the namespace map.
+ */
+function Auth_OpenID_AX_toTypeURIs($namespace_map, $alias_list_s)
+{
+ $uris = array();
+
+ if ($alias_list_s) {
+ foreach (explode(',', $alias_list_s) as $alias) {
+ $type_uri = $namespace_map->getNamespaceURI($alias);
+ if ($type_uri === null) {
+ // raise KeyError(
+ // 'No type is defined for attribute name %r' % (alias,))
+ return new Auth_OpenID_AX_Error(
+ sprintf('No type is defined for attribute name %s',
+ $alias)
+ );
+ } else {
+ $uris[] = $type_uri;
+ }
+ }
+ }
+
+ return $uris;
+}
+
+/**
+ * An attribute exchange 'fetch_request' message. This message is sent
+ * by a relying party when it wishes to obtain attributes about the
+ * subject of an OpenID authentication request.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX_FetchRequest extends Auth_OpenID_AX_Message {
+
+ var $mode = 'fetch_request';
+
+ function Auth_OpenID_AX_FetchRequest($update_url=null)
+ {
+ /**
+ * requested_attributes: The attributes that have been
+ * requested thus far, indexed by the type URI.
+ */
+ $this->requested_attributes = array();
+
+ /**
+ * update_url: A URL that will accept responses for this
+ * attribute exchange request, even in the absence of the user
+ * who made this request.
+ */
+ $this->update_url = $update_url;
+ }
+
+ /**
+ * Add an attribute to this attribute exchange request.
+ *
+ * @param attribute: The attribute that is being requested
+ * @return true on success, false when the requested attribute is
+ * already present in this fetch request.
+ */
+ function add($attribute)
+ {
+ if ($this->contains($attribute->type_uri)) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("The attribute %s has already been requested",
+ $attribute->type_uri));
+ }
+
+ $this->requested_attributes[$attribute->type_uri] = $attribute;
+
+ return true;
+ }
+
+ /**
+ * Get the serialized form of this attribute fetch request.
+ *
+ * @returns Auth_OpenID_AX_FetchRequest The fetch request message parameters
+ */
+ function getExtensionArgs()
+ {
+ $aliases = new Auth_OpenID_NamespaceMap();
+
+ $required = array();
+ $if_available = array();
+
+ $ax_args = $this->_newArgs();
+
+ foreach ($this->requested_attributes as $type_uri => $attribute) {
+ if ($attribute->alias === null) {
+ $alias = $aliases->add($type_uri);
+ } else {
+ $alias = $aliases->addAlias($type_uri, $attribute->alias);
+
+ if ($alias === null) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Could not add alias %s for URI %s",
+ $attribute->alias, $type_uri
+ ));
+ }
+ }
+
+ if ($attribute->required) {
+ $required[] = $alias;
+ } else {
+ $if_available[] = $alias;
+ }
+
+ if ($attribute->count != 1) {
+ $ax_args['count.' . $alias] = strval($attribute->count);
+ }
+
+ $ax_args['type.' . $alias] = $type_uri;
+ }
+
+ if ($required) {
+ $ax_args['required'] = implode(',', $required);
+ }
+
+ if ($if_available) {
+ $ax_args['if_available'] = implode(',', $if_available);
+ }
+
+ return $ax_args;
+ }
+
+ /**
+ * Get the type URIs for all attributes that have been marked as
+ * required.
+ *
+ * @return A list of the type URIs for attributes that have been
+ * marked as required.
+ */
+ function getRequiredAttrs()
+ {
+ $required = array();
+ foreach ($this->requested_attributes as $type_uri => $attribute) {
+ if ($attribute->required) {
+ $required[] = $type_uri;
+ }
+ }
+
+ return $required;
+ }
+
+ /**
+ * Extract a FetchRequest from an OpenID message
+ *
+ * @param request: The OpenID request containing the attribute
+ * fetch request
+ *
+ * @returns mixed An Auth_OpenID_AX_Error or the
+ * Auth_OpenID_AX_FetchRequest extracted from the request message if
+ * successful
+ */
+ static function fromOpenIDRequest($request)
+ {
+ $m = $request->message;
+ $obj = new Auth_OpenID_AX_FetchRequest();
+ $ax_args = $m->getArgs($obj->ns_uri);
+
+ $result = $obj->parseExtensionArgs($ax_args);
+
+ if (Auth_OpenID_AX::isError($result)) {
+ return $result;
+ }
+
+ if ($obj->update_url) {
+ // Update URL must match the openid.realm of the
+ // underlying OpenID 2 message.
+ $realm = $m->getArg(Auth_OpenID_OPENID_NS, 'realm',
+ $m->getArg(
+ Auth_OpenID_OPENID_NS,
+ 'return_to'));
+
+ if (!$realm) {
+ $obj = new Auth_OpenID_AX_Error(
+ sprintf("Cannot validate update_url %s " .
+ "against absent realm", $obj->update_url));
+ } else if (!Auth_OpenID_TrustRoot::match($realm,
+ $obj->update_url)) {
+ $obj = new Auth_OpenID_AX_Error(
+ sprintf("Update URL %s failed validation against realm %s",
+ $obj->update_url, $realm));
+ }
+ }
+
+ return $obj;
+ }
+
+ /**
+ * Given attribute exchange arguments, populate this FetchRequest.
+ *
+ * @return $result Auth_OpenID_AX_Error if the data to be parsed
+ * does not follow the attribute exchange specification. At least
+ * when 'if_available' or 'required' is not specified for a
+ * particular attribute type. Returns true otherwise.
+ */
+ function parseExtensionArgs($ax_args)
+ {
+ $result = $this->_checkMode($ax_args);
+ if (Auth_OpenID_AX::isError($result)) {
+ return $result;
+ }
+
+ $aliases = new Auth_OpenID_NamespaceMap();
+
+ foreach ($ax_args as $key => $value) {
+ if (strpos($key, 'type.') === 0) {
+ $alias = substr($key, 5);
+ $type_uri = $value;
+
+ $alias = $aliases->addAlias($type_uri, $alias);
+
+ if ($alias === null) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Could not add alias %s for URI %s",
+ $alias, $type_uri)
+ );
+ }
+
+ $count_s = Auth_OpenID::arrayGet($ax_args, 'count.' . $alias);
+ if ($count_s) {
+ $count = Auth_OpenID::intval($count_s);
+ if (($count === false) &&
+ ($count_s === Auth_OpenID_AX_UNLIMITED_VALUES)) {
+ $count = $count_s;
+ }
+ } else {
+ $count = 1;
+ }
+
+ if ($count === false) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Integer value expected for %s, got %s",
+ 'count.' . $alias, $count_s));
+ }
+
+ $attrinfo = Auth_OpenID_AX_AttrInfo::make($type_uri, $count,
+ false, $alias);
+
+ if (Auth_OpenID_AX::isError($attrinfo)) {
+ return $attrinfo;
+ }
+
+ $this->add($attrinfo);
+ }
+ }
+
+ $required = Auth_OpenID_AX_toTypeURIs($aliases,
+ Auth_OpenID::arrayGet($ax_args, 'required'));
+
+ foreach ($required as $type_uri) {
+ $attrib = $this->requested_attributes[$type_uri];
+ $attrib->required = true;
+ }
+
+ $if_available = Auth_OpenID_AX_toTypeURIs($aliases,
+ Auth_OpenID::arrayGet($ax_args, 'if_available'));
+
+ $all_type_uris = array_merge($required, $if_available);
+
+ foreach ($aliases->iterNamespaceURIs() as $type_uri) {
+ if (!in_array($type_uri, $all_type_uris)) {
+ return new Auth_OpenID_AX_Error(
+ sprintf('Type URI %s was in the request but not ' .
+ 'present in "required" or "if_available"',
+ $type_uri));
+
+ }
+ }
+
+ $this->update_url = Auth_OpenID::arrayGet($ax_args, 'update_url');
+
+ return true;
+ }
+
+ /**
+ * Iterate over the AttrInfo objects that are contained in this
+ * fetch_request.
+ */
+ function iterAttrs()
+ {
+ return array_values($this->requested_attributes);
+ }
+
+ function iterTypes()
+ {
+ return array_keys($this->requested_attributes);
+ }
+
+ /**
+ * Is the given type URI present in this fetch_request?
+ */
+ function contains($type_uri)
+ {
+ return in_array($type_uri, $this->iterTypes());
+ }
+}
+
+/**
+ * An abstract class that implements a message that has attribute keys
+ * and values. It contains the common code between fetch_response and
+ * store_request.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX_KeyValueMessage extends Auth_OpenID_AX_Message {
+
+ function Auth_OpenID_AX_KeyValueMessage()
+ {
+ $this->data = array();
+ }
+
+ /**
+ * Add a single value for the given attribute type to the
+ * message. If there are already values specified for this type,
+ * this value will be sent in addition to the values already
+ * specified.
+ *
+ * @param type_uri: The URI for the attribute
+ * @param value: The value to add to the response to the relying
+ * party for this attribute
+ * @return null
+ */
+ function addValue($type_uri, $value)
+ {
+ if (!array_key_exists($type_uri, $this->data)) {
+ $this->data[$type_uri] = array();
+ }
+
+ $values =& $this->data[$type_uri];
+ $values[] = $value;
+ }
+
+ /**
+ * Set the values for the given attribute type. This replaces any
+ * values that have already been set for this attribute.
+ *
+ * @param type_uri: The URI for the attribute
+ * @param values: A list of values to send for this attribute.
+ */
+ function setValues($type_uri, &$values)
+ {
+ $this->data[$type_uri] =& $values;
+ }
+
+ /**
+ * Get the extension arguments for the key/value pairs contained
+ * in this message.
+ *
+ * @param aliases: An alias mapping. Set to None if you don't care
+ * about the aliases for this request.
+ *
+ * @access private
+ */
+ function _getExtensionKVArgs($aliases)
+ {
+ if ($aliases === null) {
+ $aliases = new Auth_OpenID_NamespaceMap();
+ }
+
+ $ax_args = array();
+
+ foreach ($this->data as $type_uri => $values) {
+ $alias = $aliases->add($type_uri);
+
+ $ax_args['type.' . $alias] = $type_uri;
+ $ax_args['count.' . $alias] = strval(count($values));
+
+ foreach ($values as $i => $value) {
+ $key = sprintf('value.%s.%d', $alias, $i + 1);
+ $ax_args[$key] = $value;
+ }
+ }
+
+ return $ax_args;
+ }
+
+ /**
+ * Parse attribute exchange key/value arguments into this object.
+ *
+ * @param ax_args: The attribute exchange fetch_response
+ * arguments, with namespacing removed.
+ *
+ * @return Auth_OpenID_AX_Error or true
+ */
+ function parseExtensionArgs($ax_args)
+ {
+ $result = $this->_checkMode($ax_args);
+ if (Auth_OpenID_AX::isError($result)) {
+ return $result;
+ }
+
+ $aliases = new Auth_OpenID_NamespaceMap();
+
+ foreach ($ax_args as $key => $value) {
+ if (strpos($key, 'type.') === 0) {
+ $type_uri = $value;
+ $alias = substr($key, 5);
+
+ $result = Auth_OpenID_AX_checkAlias($alias);
+
+ if (Auth_OpenID_AX::isError($result)) {
+ return $result;
+ }
+
+ $alias = $aliases->addAlias($type_uri, $alias);
+
+ if ($alias === null) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Could not add alias %s for URI %s",
+ $alias, $type_uri)
+ );
+ }
+ }
+ }
+
+ foreach ($aliases->iteritems() as $pair) {
+ list($type_uri, $alias) = $pair;
+
+ if (array_key_exists('count.' . $alias, $ax_args) && ($ax_args['count.' . $alias] !== Auth_OpenID_AX_UNLIMITED_VALUES)) {
+
+ $count_key = 'count.' . $alias;
+ $count_s = $ax_args[$count_key];
+
+ $count = Auth_OpenID::intval($count_s);
+
+ if ($count === false) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Integer value expected for %s, got %s",
+ 'count. %s' . $alias, $count_s,
+ Auth_OpenID_AX_UNLIMITED_VALUES)
+ );
+ }
+
+ $values = array();
+ for ($i = 1; $i < $count + 1; $i++) {
+ $value_key = sprintf('value.%s.%d', $alias, $i);
+
+ if (!array_key_exists($value_key, $ax_args)) {
+ return new Auth_OpenID_AX_Error(
+ sprintf(
+ "No value found for key %s",
+ $value_key));
+ }
+
+ $value = $ax_args[$value_key];
+ $values[] = $value;
+ }
+ } else {
+ $key = 'value.' . $alias;
+
+ if (!array_key_exists($key, $ax_args)) {
+ return new Auth_OpenID_AX_Error(
+ sprintf(
+ "No value found for key %s",
+ $key));
+ }
+
+ $value = $ax_args['value.' . $alias];
+
+ if ($value == '') {
+ $values = array();
+ } else {
+ $values = array($value);
+ }
+ }
+
+ $this->data[$type_uri] = $values;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get a single value for an attribute. If no value was sent for
+ * this attribute, use the supplied default. If there is more than
+ * one value for this attribute, this method will fail.
+ *
+ * @param type_uri: The URI for the attribute
+ * @param default: The value to return if the attribute was not
+ * sent in the fetch_response.
+ *
+ * @return $value Auth_OpenID_AX_Error on failure or the value of
+ * the attribute in the fetch_response message, or the default
+ * supplied
+ */
+ function getSingle($type_uri, $default=null)
+ {
+ $values = Auth_OpenID::arrayGet($this->data, $type_uri);
+ if (!$values) {
+ return $default;
+ } else if (count($values) == 1) {
+ return $values[0];
+ } else {
+ return new Auth_OpenID_AX_Error(
+ sprintf('More than one value present for %s',
+ $type_uri)
+ );
+ }
+ }
+
+ /**
+ * Get the list of values for this attribute in the
+ * fetch_response.
+ *
+ * XXX: what to do if the values are not present? default
+ * parameter? this is funny because it's always supposed to return
+ * a list, so the default may break that, though it's provided by
+ * the user's code, so it might be okay. If no default is
+ * supplied, should the return be None or []?
+ *
+ * @param type_uri: The URI of the attribute
+ *
+ * @return $values The list of values for this attribute in the
+ * response. May be an empty list. If the attribute was not sent
+ * in the response, returns Auth_OpenID_AX_Error.
+ */
+ function get($type_uri)
+ {
+ if (array_key_exists($type_uri, $this->data)) {
+ return $this->data[$type_uri];
+ } else {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Type URI %s not found in response",
+ $type_uri)
+ );
+ }
+ }
+
+ /**
+ * Get the number of responses for a particular attribute in this
+ * fetch_response message.
+ *
+ * @param type_uri: The URI of the attribute
+ *
+ * @returns int The number of values sent for this attribute. If
+ * the attribute was not sent in the response, returns
+ * Auth_OpenID_AX_Error.
+ */
+ function count($type_uri)
+ {
+ if (array_key_exists($type_uri, $this->data)) {
+ return count($this->get($type_uri));
+ } else {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Type URI %s not found in response",
+ $type_uri)
+ );
+ }
+ }
+}
+
+/**
+ * A fetch_response attribute exchange message.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX_FetchResponse extends Auth_OpenID_AX_KeyValueMessage {
+ var $mode = 'fetch_response';
+
+ function Auth_OpenID_AX_FetchResponse($update_url=null)
+ {
+ $this->Auth_OpenID_AX_KeyValueMessage();
+ $this->update_url = $update_url;
+ }
+
+ /**
+ * Serialize this object into arguments in the attribute exchange
+ * namespace
+ *
+ * @return $args The dictionary of unqualified attribute exchange
+ * arguments that represent this fetch_response, or
+ * Auth_OpenID_AX_Error on error.
+ */
+ function getExtensionArgs($request=null)
+ {
+ $aliases = new Auth_OpenID_NamespaceMap();
+
+ $zero_value_types = array();
+
+ if ($request !== null) {
+ // Validate the data in the context of the request (the
+ // same attributes should be present in each, and the
+ // counts in the response must be no more than the counts
+ // in the request)
+
+ foreach ($this->data as $type_uri => $unused) {
+ if (!$request->contains($type_uri)) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Response attribute not present in request: %s",
+ $type_uri)
+ );
+ }
+ }
+
+ foreach ($request->iterAttrs() as $attr_info) {
+ // Copy the aliases from the request so that reading
+ // the response in light of the request is easier
+ if ($attr_info->alias === null) {
+ $aliases->add($attr_info->type_uri);
+ } else {
+ $alias = $aliases->addAlias($attr_info->type_uri,
+ $attr_info->alias);
+
+ if ($alias === null) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("Could not add alias %s for URI %s",
+ $attr_info->alias, $attr_info->type_uri)
+ );
+ }
+ }
+
+ if (array_key_exists($attr_info->type_uri, $this->data)) {
+ $values = $this->data[$attr_info->type_uri];
+ } else {
+ $values = array();
+ $zero_value_types[] = $attr_info;
+ }
+
+ if (($attr_info->count != Auth_OpenID_AX_UNLIMITED_VALUES) &&
+ ($attr_info->count < count($values))) {
+ return new Auth_OpenID_AX_Error(
+ sprintf("More than the number of requested values " .
+ "were specified for %s",
+ $attr_info->type_uri)
+ );
+ }
+ }
+ }
+
+ $kv_args = $this->_getExtensionKVArgs($aliases);
+
+ // Add the KV args into the response with the args that are
+ // unique to the fetch_response
+ $ax_args = $this->_newArgs();
+
+ // For each requested attribute, put its type/alias and count
+ // into the response even if no data were returned.
+ foreach ($zero_value_types as $attr_info) {
+ $alias = $aliases->getAlias($attr_info->type_uri);
+ $kv_args['type.' . $alias] = $attr_info->type_uri;
+ $kv_args['count.' . $alias] = '0';
+ }
+
+ $update_url = null;
+ if ($request) {
+ $update_url = $request->update_url;
+ } else {
+ $update_url = $this->update_url;
+ }
+
+ if ($update_url) {
+ $ax_args['update_url'] = $update_url;
+ }
+
+ Auth_OpenID::update($ax_args, $kv_args);
+
+ return $ax_args;
+ }
+
+ /**
+ * @return $result Auth_OpenID_AX_Error on failure or true on
+ * success.
+ */
+ function parseExtensionArgs($ax_args)
+ {
+ $result = parent::parseExtensionArgs($ax_args);
+
+ if (Auth_OpenID_AX::isError($result)) {
+ return $result;
+ }
+
+ $this->update_url = Auth_OpenID::arrayGet($ax_args, 'update_url');
+
+ return true;
+ }
+
+ /**
+ * Construct a FetchResponse object from an OpenID library
+ * SuccessResponse object.
+ *
+ * @param success_response: A successful id_res response object
+ *
+ * @param signed: Whether non-signed args should be processsed. If
+ * True (the default), only signed arguments will be processsed.
+ *
+ * @return $response A FetchResponse containing the data from the
+ * OpenID message
+ */
+ static function fromSuccessResponse($success_response, $signed=true)
+ {
+ $obj = new Auth_OpenID_AX_FetchResponse();
+ if ($signed) {
+ $ax_args = $success_response->getSignedNS($obj->ns_uri);
+ } else {
+ $ax_args = $success_response->message->getArgs($obj->ns_uri);
+ }
+ if ($ax_args === null || Auth_OpenID::isFailure($ax_args) ||
+ sizeof($ax_args) == 0) {
+ return null;
+ }
+
+ $result = $obj->parseExtensionArgs($ax_args);
+ if (Auth_OpenID_AX::isError($result)) {
+ #XXX log me
+ return null;
+ }
+ return $obj;
+ }
+}
+
+/**
+ * A store request attribute exchange message representation.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX_StoreRequest extends Auth_OpenID_AX_KeyValueMessage {
+ var $mode = 'store_request';
+
+ /**
+ * @param array $aliases The namespace aliases to use when making
+ * this store response. Leave as None to use defaults.
+ */
+ function getExtensionArgs($aliases=null)
+ {
+ $ax_args = $this->_newArgs();
+ $kv_args = $this->_getExtensionKVArgs($aliases);
+ Auth_OpenID::update($ax_args, $kv_args);
+ return $ax_args;
+ }
+}
+
+/**
+ * An indication that the store request was processed along with this
+ * OpenID transaction. Use make(), NOT the constructor, to create
+ * response objects.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AX_StoreResponse extends Auth_OpenID_AX_Message {
+ var $SUCCESS_MODE = 'store_response_success';
+ var $FAILURE_MODE = 'store_response_failure';
+
+ /**
+ * Returns Auth_OpenID_AX_Error on error or an
+ * Auth_OpenID_AX_StoreResponse object on success.
+ */
+ function make($succeeded=true, $error_message=null)
+ {
+ if (($succeeded) && ($error_message !== null)) {
+ return new Auth_OpenID_AX_Error('An error message may only be '.
+ 'included in a failing fetch response');
+ }
+
+ return new Auth_OpenID_AX_StoreResponse($succeeded, $error_message);
+ }
+
+ function Auth_OpenID_AX_StoreResponse($succeeded=true, $error_message=null)
+ {
+ if ($succeeded) {
+ $this->mode = $this->SUCCESS_MODE;
+ } else {
+ $this->mode = $this->FAILURE_MODE;
+ }
+
+ $this->error_message = $error_message;
+ }
+
+ /**
+ * Was this response a success response?
+ */
+ function succeeded()
+ {
+ return $this->mode == $this->SUCCESS_MODE;
+ }
+
+ function getExtensionArgs()
+ {
+ $ax_args = $this->_newArgs();
+ if ((!$this->succeeded()) && $this->error_message) {
+ $ax_args['error'] = $this->error_message;
+ }
+
+ return $ax_args;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/Association.php b/plugins/openid/lib/Auth/OpenID/Association.php
new file mode 100644
index 00000000..2729138e
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Association.php
@@ -0,0 +1,610 @@
+<?php
+
+/**
+ * This module contains code for dealing with associations between
+ * consumers and servers.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/CryptUtil.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/KVForm.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/HMAC.php';
+
+/**
+ * This class represents an association between a server and a
+ * consumer. In general, users of this library will never see
+ * instances of this object. The only exception is if you implement a
+ * custom {@link Auth_OpenID_OpenIDStore}.
+ *
+ * If you do implement such a store, it will need to store the values
+ * of the handle, secret, issued, lifetime, and assoc_type instance
+ * variables.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Association {
+
+ /**
+ * This is a HMAC-SHA1 specific value.
+ *
+ * @access private
+ */
+ var $SIG_LENGTH = 20;
+
+ /**
+ * The ordering and name of keys as stored by serialize.
+ *
+ * @access private
+ */
+ var $assoc_keys = array(
+ 'version',
+ 'handle',
+ 'secret',
+ 'issued',
+ 'lifetime',
+ 'assoc_type'
+ );
+
+ var $_macs = array(
+ 'HMAC-SHA1' => 'Auth_OpenID_HMACSHA1',
+ 'HMAC-SHA256' => 'Auth_OpenID_HMACSHA256'
+ );
+
+ /**
+ * This is an alternate constructor (factory method) used by the
+ * OpenID consumer library to create associations. OpenID store
+ * implementations shouldn't use this constructor.
+ *
+ * @access private
+ *
+ * @param integer $expires_in This is the amount of time this
+ * association is good for, measured in seconds since the
+ * association was issued.
+ *
+ * @param string $handle This is the handle the server gave this
+ * association.
+ *
+ * @param string secret This is the shared secret the server
+ * generated for this association.
+ *
+ * @param assoc_type This is the type of association this
+ * instance represents. The only valid values of this field at
+ * this time is 'HMAC-SHA1' and 'HMAC-SHA256', but new types may
+ * be defined in the future.
+ *
+ * @return association An {@link Auth_OpenID_Association}
+ * instance.
+ */
+ static function fromExpiresIn($expires_in, $handle, $secret, $assoc_type)
+ {
+ $issued = time();
+ $lifetime = $expires_in;
+ return new Auth_OpenID_Association($handle, $secret,
+ $issued, $lifetime, $assoc_type);
+ }
+
+ /**
+ * This is the standard constructor for creating an association.
+ * The library should create all of the necessary associations, so
+ * this constructor is not part of the external API.
+ *
+ * @access private
+ *
+ * @param string $handle This is the handle the server gave this
+ * association.
+ *
+ * @param string $secret This is the shared secret the server
+ * generated for this association.
+ *
+ * @param integer $issued This is the time this association was
+ * issued, in seconds since 00:00 GMT, January 1, 1970. (ie, a
+ * unix timestamp)
+ *
+ * @param integer $lifetime This is the amount of time this
+ * association is good for, measured in seconds since the
+ * association was issued.
+ *
+ * @param string $assoc_type This is the type of association this
+ * instance represents. The only valid values of this field at
+ * this time is 'HMAC-SHA1' and 'HMAC-SHA256', but new types may
+ * be defined in the future.
+ */
+ function Auth_OpenID_Association(
+ $handle, $secret, $issued, $lifetime, $assoc_type)
+ {
+ if (!in_array($assoc_type,
+ Auth_OpenID_getSupportedAssociationTypes(), true)) {
+ $fmt = 'Unsupported association type (%s)';
+ trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR);
+ }
+
+ $this->handle = $handle;
+ $this->secret = $secret;
+ $this->issued = $issued;
+ $this->lifetime = $lifetime;
+ $this->assoc_type = $assoc_type;
+ }
+
+ /**
+ * This returns the number of seconds this association is still
+ * valid for, or 0 if the association is no longer valid.
+ *
+ * @return integer $seconds The number of seconds this association
+ * is still valid for, or 0 if the association is no longer valid.
+ */
+ function getExpiresIn($now = null)
+ {
+ if ($now == null) {
+ $now = time();
+ }
+
+ return max(0, $this->issued + $this->lifetime - $now);
+ }
+
+ /**
+ * This checks to see if two {@link Auth_OpenID_Association}
+ * instances represent the same association.
+ *
+ * @return bool $result true if the two instances represent the
+ * same association, false otherwise.
+ */
+ function equal($other)
+ {
+ return ((gettype($this) == gettype($other))
+ && ($this->handle == $other->handle)
+ && ($this->secret == $other->secret)
+ && ($this->issued == $other->issued)
+ && ($this->lifetime == $other->lifetime)
+ && ($this->assoc_type == $other->assoc_type));
+ }
+
+ /**
+ * Convert an association to KV form.
+ *
+ * @return string $result String in KV form suitable for
+ * deserialization by deserialize.
+ */
+ function serialize()
+ {
+ $data = array(
+ 'version' => '2',
+ 'handle' => $this->handle,
+ 'secret' => base64_encode($this->secret),
+ 'issued' => strval(intval($this->issued)),
+ 'lifetime' => strval(intval($this->lifetime)),
+ 'assoc_type' => $this->assoc_type
+ );
+
+ assert(array_keys($data) == $this->assoc_keys);
+
+ return Auth_OpenID_KVForm::fromArray($data, $strict = true);
+ }
+
+ /**
+ * Parse an association as stored by serialize(). This is the
+ * inverse of serialize.
+ *
+ * @param string $assoc_s Association as serialized by serialize()
+ * @return Auth_OpenID_Association $result instance of this class
+ */
+ static function deserialize($class_name, $assoc_s)
+ {
+ $pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true);
+ $keys = array();
+ $values = array();
+ foreach ($pairs as $key => $value) {
+ if (is_array($value)) {
+ list($key, $value) = $value;
+ }
+ $keys[] = $key;
+ $values[] = $value;
+ }
+
+ $class_vars = get_class_vars($class_name);
+ $class_assoc_keys = $class_vars['assoc_keys'];
+
+ sort($keys);
+ sort($class_assoc_keys);
+
+ if ($keys != $class_assoc_keys) {
+ trigger_error('Unexpected key values: ' . var_export($keys, true),
+ E_USER_WARNING);
+ return null;
+ }
+
+ $version = $pairs['version'];
+ $handle = $pairs['handle'];
+ $secret = $pairs['secret'];
+ $issued = $pairs['issued'];
+ $lifetime = $pairs['lifetime'];
+ $assoc_type = $pairs['assoc_type'];
+
+ if ($version != '2') {
+ trigger_error('Unknown version: ' . $version, E_USER_WARNING);
+ return null;
+ }
+
+ $issued = intval($issued);
+ $lifetime = intval($lifetime);
+ $secret = base64_decode($secret);
+
+ return new $class_name(
+ $handle, $secret, $issued, $lifetime, $assoc_type);
+ }
+
+ /**
+ * Generate a signature for a sequence of (key, value) pairs
+ *
+ * @access private
+ * @param array $pairs The pairs to sign, in order. This is an
+ * array of two-tuples.
+ * @return string $signature The binary signature of this sequence
+ * of pairs
+ */
+ function sign($pairs)
+ {
+ $kv = Auth_OpenID_KVForm::fromArray($pairs);
+
+ /* Invalid association types should be caught at constructor */
+ $callback = $this->_macs[$this->assoc_type];
+
+ return call_user_func_array($callback, array($this->secret, $kv));
+ }
+
+ /**
+ * Generate a signature for some fields in a dictionary
+ *
+ * @access private
+ * @param array $fields The fields to sign, in order; this is an
+ * array of strings.
+ * @param array $data Dictionary of values to sign (an array of
+ * string => string pairs).
+ * @return string $signature The signature, base64 encoded
+ */
+ function signMessage($message)
+ {
+ if ($message->hasKey(Auth_OpenID_OPENID_NS, 'sig') ||
+ $message->hasKey(Auth_OpenID_OPENID_NS, 'signed')) {
+ // Already has a sig
+ return null;
+ }
+
+ $extant_handle = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'assoc_handle');
+
+ if ($extant_handle && ($extant_handle != $this->handle)) {
+ // raise ValueError("Message has a different association handle")
+ return null;
+ }
+
+ $signed_message = $message;
+ $signed_message->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle',
+ $this->handle);
+
+ $message_keys = array_keys($signed_message->toPostArgs());
+ $signed_list = array();
+ $signed_prefix = 'openid.';
+
+ foreach ($message_keys as $k) {
+ if (strpos($k, $signed_prefix) === 0) {
+ $signed_list[] = substr($k, strlen($signed_prefix));
+ }
+ }
+
+ $signed_list[] = 'signed';
+ sort($signed_list);
+
+ $signed_message->setArg(Auth_OpenID_OPENID_NS, 'signed',
+ implode(',', $signed_list));
+ $sig = $this->getMessageSignature($signed_message);
+ $signed_message->setArg(Auth_OpenID_OPENID_NS, 'sig', $sig);
+ return $signed_message;
+ }
+
+ /**
+ * Given a {@link Auth_OpenID_Message}, return the key/value pairs
+ * to be signed according to the signed list in the message. If
+ * the message lacks a signed list, return null.
+ *
+ * @access private
+ */
+ function _makePairs($message)
+ {
+ $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
+ if (!$signed || Auth_OpenID::isFailure($signed)) {
+ // raise ValueError('Message has no signed list: %s' % (message,))
+ return null;
+ }
+
+ $signed_list = explode(',', $signed);
+ $pairs = array();
+ $data = $message->toPostArgs();
+ foreach ($signed_list as $field) {
+ $pairs[] = array($field, Auth_OpenID::arrayGet($data,
+ 'openid.' .
+ $field, ''));
+ }
+ return $pairs;
+ }
+
+ /**
+ * Given an {@link Auth_OpenID_Message}, return the signature for
+ * the signed list in the message.
+ *
+ * @access private
+ */
+ function getMessageSignature($message)
+ {
+ $pairs = $this->_makePairs($message);
+ return base64_encode($this->sign($pairs));
+ }
+
+ /**
+ * Confirm that the signature of these fields matches the
+ * signature contained in the data.
+ *
+ * @access private
+ */
+ function checkMessageSignature($message)
+ {
+ $sig = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'sig');
+
+ if (!$sig || Auth_OpenID::isFailure($sig)) {
+ return false;
+ }
+
+ $calculated_sig = $this->getMessageSignature($message);
+ return Auth_OpenID_CryptUtil::constEq($calculated_sig, $sig);
+ }
+}
+
+function Auth_OpenID_getSecretSize($assoc_type)
+{
+ if ($assoc_type == 'HMAC-SHA1') {
+ return 20;
+ } else if ($assoc_type == 'HMAC-SHA256') {
+ return 32;
+ } else {
+ return null;
+ }
+}
+
+function Auth_OpenID_getAllAssociationTypes()
+{
+ return array('HMAC-SHA1', 'HMAC-SHA256');
+}
+
+function Auth_OpenID_getSupportedAssociationTypes()
+{
+ $a = array('HMAC-SHA1');
+
+ if (Auth_OpenID_HMACSHA256_SUPPORTED) {
+ $a[] = 'HMAC-SHA256';
+ }
+
+ return $a;
+}
+
+function Auth_OpenID_getSessionTypes($assoc_type)
+{
+ $assoc_to_session = array(
+ 'HMAC-SHA1' => array('DH-SHA1', 'no-encryption'));
+
+ if (Auth_OpenID_HMACSHA256_SUPPORTED) {
+ $assoc_to_session['HMAC-SHA256'] =
+ array('DH-SHA256', 'no-encryption');
+ }
+
+ return Auth_OpenID::arrayGet($assoc_to_session, $assoc_type, array());
+}
+
+function Auth_OpenID_checkSessionType($assoc_type, $session_type)
+{
+ if (!in_array($session_type,
+ Auth_OpenID_getSessionTypes($assoc_type))) {
+ return false;
+ }
+
+ return true;
+}
+
+function Auth_OpenID_getDefaultAssociationOrder()
+{
+ $order = array();
+
+ if (!Auth_OpenID_noMathSupport()) {
+ $order[] = array('HMAC-SHA1', 'DH-SHA1');
+
+ if (Auth_OpenID_HMACSHA256_SUPPORTED) {
+ $order[] = array('HMAC-SHA256', 'DH-SHA256');
+ }
+ }
+
+ $order[] = array('HMAC-SHA1', 'no-encryption');
+
+ if (Auth_OpenID_HMACSHA256_SUPPORTED) {
+ $order[] = array('HMAC-SHA256', 'no-encryption');
+ }
+
+ return $order;
+}
+
+function Auth_OpenID_getOnlyEncryptedOrder()
+{
+ $result = array();
+
+ foreach (Auth_OpenID_getDefaultAssociationOrder() as $pair) {
+ list($assoc, $session) = $pair;
+
+ if ($session != 'no-encryption') {
+ if (Auth_OpenID_HMACSHA256_SUPPORTED &&
+ ($assoc == 'HMAC-SHA256')) {
+ $result[] = $pair;
+ } else if ($assoc != 'HMAC-SHA256') {
+ $result[] = $pair;
+ }
+ }
+ }
+
+ return $result;
+}
+
+function Auth_OpenID_getDefaultNegotiator()
+{
+ return new Auth_OpenID_SessionNegotiator(
+ Auth_OpenID_getDefaultAssociationOrder());
+}
+
+function Auth_OpenID_getEncryptedNegotiator()
+{
+ return new Auth_OpenID_SessionNegotiator(
+ Auth_OpenID_getOnlyEncryptedOrder());
+}
+
+/**
+ * A session negotiator controls the allowed and preferred association
+ * types and association session types. Both the {@link
+ * Auth_OpenID_Consumer} and {@link Auth_OpenID_Server} use
+ * negotiators when creating associations.
+ *
+ * You can create and use negotiators if you:
+
+ * - Do not want to do Diffie-Hellman key exchange because you use
+ * transport-layer encryption (e.g. SSL)
+ *
+ * - Want to use only SHA-256 associations
+ *
+ * - Do not want to support plain-text associations over a non-secure
+ * channel
+ *
+ * It is up to you to set a policy for what kinds of associations to
+ * accept. By default, the library will make any kind of association
+ * that is allowed in the OpenID 2.0 specification.
+ *
+ * Use of negotiators in the library
+ * =================================
+ *
+ * When a consumer makes an association request, it calls {@link
+ * getAllowedType} to get the preferred association type and
+ * association session type.
+ *
+ * The server gets a request for a particular association/session type
+ * and calls {@link isAllowed} to determine if it should create an
+ * association. If it is supported, negotiation is complete. If it is
+ * not, the server calls {@link getAllowedType} to get an allowed
+ * association type to return to the consumer.
+ *
+ * If the consumer gets an error response indicating that the
+ * requested association/session type is not supported by the server
+ * that contains an assocation/session type to try, it calls {@link
+ * isAllowed} to determine if it should try again with the given
+ * combination of association/session type.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SessionNegotiator {
+ function Auth_OpenID_SessionNegotiator($allowed_types)
+ {
+ $this->allowed_types = array();
+ $this->setAllowedTypes($allowed_types);
+ }
+
+ /**
+ * Set the allowed association types, checking to make sure each
+ * combination is valid.
+ *
+ * @access private
+ */
+ function setAllowedTypes($allowed_types)
+ {
+ foreach ($allowed_types as $pair) {
+ list($assoc_type, $session_type) = $pair;
+ if (!Auth_OpenID_checkSessionType($assoc_type, $session_type)) {
+ return false;
+ }
+ }
+
+ $this->allowed_types = $allowed_types;
+ return true;
+ }
+
+ /**
+ * Add an association type and session type to the allowed types
+ * list. The assocation/session pairs are tried in the order that
+ * they are added.
+ *
+ * @access private
+ */
+ function addAllowedType($assoc_type, $session_type = null)
+ {
+ if ($this->allowed_types === null) {
+ $this->allowed_types = array();
+ }
+
+ if ($session_type === null) {
+ $available = Auth_OpenID_getSessionTypes($assoc_type);
+
+ if (!$available) {
+ return false;
+ }
+
+ foreach ($available as $session_type) {
+ $this->addAllowedType($assoc_type, $session_type);
+ }
+ } else {
+ if (Auth_OpenID_checkSessionType($assoc_type, $session_type)) {
+ $this->allowed_types[] = array($assoc_type, $session_type);
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // Is this combination of association type and session type allowed?
+ function isAllowed($assoc_type, $session_type)
+ {
+ $assoc_good = in_array(array($assoc_type, $session_type),
+ $this->allowed_types);
+
+ $matches = in_array($session_type,
+ Auth_OpenID_getSessionTypes($assoc_type));
+
+ return ($assoc_good && $matches);
+ }
+
+ /**
+ * Get a pair of assocation type and session type that are
+ * supported.
+ */
+ function getAllowedType()
+ {
+ if (!$this->allowed_types) {
+ return array(null, null);
+ }
+
+ return $this->allowed_types[0];
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/BigMath.php b/plugins/openid/lib/Auth/OpenID/BigMath.php
new file mode 100644
index 00000000..58b46bf2
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/BigMath.php
@@ -0,0 +1,451 @@
+<?php
+
+/**
+ * BigMath: A math library wrapper that abstracts out the underlying
+ * long integer library.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @access private
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Needed for random number generation
+ */
+require_once 'Auth/OpenID/CryptUtil.php';
+
+/**
+ * Need Auth_OpenID::bytes().
+ */
+require_once 'Auth/OpenID.php';
+
+/**
+ * The superclass of all big-integer math implementations
+ * @access private
+ * @package OpenID
+ */
+class Auth_OpenID_MathLibrary {
+ /**
+ * Given a long integer, returns the number converted to a binary
+ * string. This function accepts long integer values of arbitrary
+ * magnitude and uses the local large-number math library when
+ * available.
+ *
+ * @param integer $long The long number (can be a normal PHP
+ * integer or a number created by one of the available long number
+ * libraries)
+ * @return string $binary The binary version of $long
+ */
+ function longToBinary($long)
+ {
+ $cmp = $this->cmp($long, 0);
+ if ($cmp < 0) {
+ $msg = __FUNCTION__ . " takes only positive integers.";
+ trigger_error($msg, E_USER_ERROR);
+ return null;
+ }
+
+ if ($cmp == 0) {
+ return "\x00";
+ }
+
+ $bytes = array();
+
+ while ($this->cmp($long, 0) > 0) {
+ array_unshift($bytes, $this->mod($long, 256));
+ $long = $this->div($long, pow(2, 8));
+ }
+
+ if ($bytes && ($bytes[0] > 127)) {
+ array_unshift($bytes, 0);
+ }
+
+ $string = '';
+ foreach ($bytes as $byte) {
+ $string .= pack('C', $byte);
+ }
+
+ return $string;
+ }
+
+ /**
+ * Given a binary string, returns the binary string converted to a
+ * long number.
+ *
+ * @param string $binary The binary version of a long number,
+ * probably as a result of calling longToBinary
+ * @return integer $long The long number equivalent of the binary
+ * string $str
+ */
+ function binaryToLong($str)
+ {
+ if ($str === null) {
+ return null;
+ }
+
+ // Use array_merge to return a zero-indexed array instead of a
+ // one-indexed array.
+ $bytes = array_merge(unpack('C*', $str));
+
+ $n = $this->init(0);
+
+ if ($bytes && ($bytes[0] > 127)) {
+ trigger_error("bytesToNum works only for positive integers.",
+ E_USER_WARNING);
+ return null;
+ }
+
+ foreach ($bytes as $byte) {
+ $n = $this->mul($n, pow(2, 8));
+ $n = $this->add($n, $byte);
+ }
+
+ return $n;
+ }
+
+ function base64ToLong($str)
+ {
+ $b64 = base64_decode($str);
+
+ if ($b64 === false) {
+ return false;
+ }
+
+ return $this->binaryToLong($b64);
+ }
+
+ function longToBase64($str)
+ {
+ return base64_encode($this->longToBinary($str));
+ }
+
+ /**
+ * Returns a random number in the specified range. This function
+ * accepts $start, $stop, and $step values of arbitrary magnitude
+ * and will utilize the local large-number math library when
+ * available.
+ *
+ * @param integer $start The start of the range, or the minimum
+ * random number to return
+ * @param integer $stop The end of the range, or the maximum
+ * random number to return
+ * @param integer $step The step size, such that $result - ($step
+ * * N) = $start for some N
+ * @return integer $result The resulting randomly-generated number
+ */
+ function rand($stop)
+ {
+ static $duplicate_cache = array();
+
+ // Used as the key for the duplicate cache
+ $rbytes = $this->longToBinary($stop);
+
+ if (array_key_exists($rbytes, $duplicate_cache)) {
+ list($duplicate, $nbytes) = $duplicate_cache[$rbytes];
+ } else {
+ if ($rbytes[0] == "\x00") {
+ $nbytes = Auth_OpenID::bytes($rbytes) - 1;
+ } else {
+ $nbytes = Auth_OpenID::bytes($rbytes);
+ }
+
+ $mxrand = $this->pow(256, $nbytes);
+
+ // If we get a number less than this, then it is in the
+ // duplicated range.
+ $duplicate = $this->mod($mxrand, $stop);
+
+ if (count($duplicate_cache) > 10) {
+ $duplicate_cache = array();
+ }
+
+ $duplicate_cache[$rbytes] = array($duplicate, $nbytes);
+ }
+
+ do {
+ $bytes = "\x00" . Auth_OpenID_CryptUtil::getBytes($nbytes);
+ $n = $this->binaryToLong($bytes);
+ // Keep looping if this value is in the low duplicated range
+ } while ($this->cmp($n, $duplicate) < 0);
+
+ return $this->mod($n, $stop);
+ }
+}
+
+/**
+ * Exposes BCmath math library functionality.
+ *
+ * {@link Auth_OpenID_BcMathWrapper} wraps the functionality provided
+ * by the BCMath extension.
+ *
+ * @access private
+ * @package OpenID
+ */
+class Auth_OpenID_BcMathWrapper extends Auth_OpenID_MathLibrary{
+ var $type = 'bcmath';
+
+ function add($x, $y)
+ {
+ return bcadd($x, $y);
+ }
+
+ function sub($x, $y)
+ {
+ return bcsub($x, $y);
+ }
+
+ function pow($base, $exponent)
+ {
+ return bcpow($base, $exponent);
+ }
+
+ function cmp($x, $y)
+ {
+ return bccomp($x, $y);
+ }
+
+ function init($number, $base = 10)
+ {
+ return $number;
+ }
+
+ function mod($base, $modulus)
+ {
+ return bcmod($base, $modulus);
+ }
+
+ function mul($x, $y)
+ {
+ return bcmul($x, $y);
+ }
+
+ function div($x, $y)
+ {
+ return bcdiv($x, $y);
+ }
+
+ /**
+ * Same as bcpowmod when bcpowmod is missing
+ *
+ * @access private
+ */
+ function _powmod($base, $exponent, $modulus)
+ {
+ $square = $this->mod($base, $modulus);
+ $result = 1;
+ while($this->cmp($exponent, 0) > 0) {
+ if ($this->mod($exponent, 2)) {
+ $result = $this->mod($this->mul($result, $square), $modulus);
+ }
+ $square = $this->mod($this->mul($square, $square), $modulus);
+ $exponent = $this->div($exponent, 2);
+ }
+ return $result;
+ }
+
+ function powmod($base, $exponent, $modulus)
+ {
+ if (function_exists('bcpowmod')) {
+ return bcpowmod($base, $exponent, $modulus);
+ } else {
+ return $this->_powmod($base, $exponent, $modulus);
+ }
+ }
+
+ function toString($num)
+ {
+ return $num;
+ }
+}
+
+/**
+ * Exposes GMP math library functionality.
+ *
+ * {@link Auth_OpenID_GmpMathWrapper} wraps the functionality provided
+ * by the GMP extension.
+ *
+ * @access private
+ * @package OpenID
+ */
+class Auth_OpenID_GmpMathWrapper extends Auth_OpenID_MathLibrary{
+ var $type = 'gmp';
+
+ function add($x, $y)
+ {
+ return gmp_add($x, $y);
+ }
+
+ function sub($x, $y)
+ {
+ return gmp_sub($x, $y);
+ }
+
+ function pow($base, $exponent)
+ {
+ return gmp_pow($base, $exponent);
+ }
+
+ function cmp($x, $y)
+ {
+ return gmp_cmp($x, $y);
+ }
+
+ function init($number, $base = 10)
+ {
+ return gmp_init($number, $base);
+ }
+
+ function mod($base, $modulus)
+ {
+ return gmp_mod($base, $modulus);
+ }
+
+ function mul($x, $y)
+ {
+ return gmp_mul($x, $y);
+ }
+
+ function div($x, $y)
+ {
+ return gmp_div_q($x, $y);
+ }
+
+ function powmod($base, $exponent, $modulus)
+ {
+ return gmp_powm($base, $exponent, $modulus);
+ }
+
+ function toString($num)
+ {
+ return gmp_strval($num);
+ }
+}
+
+/**
+ * Define the supported extensions. An extension array has keys
+ * 'modules', 'extension', and 'class'. 'modules' is an array of PHP
+ * module names which the loading code will attempt to load. These
+ * values will be suffixed with a library file extension (e.g. ".so").
+ * 'extension' is the name of a PHP extension which will be tested
+ * before 'modules' are loaded. 'class' is the string name of a
+ * {@link Auth_OpenID_MathWrapper} subclass which should be
+ * instantiated if a given extension is present.
+ *
+ * You can define new math library implementations and add them to
+ * this array.
+ */
+function Auth_OpenID_math_extensions()
+{
+ $result = array();
+
+ if (!defined('Auth_OpenID_BUGGY_GMP')) {
+ $result[] =
+ array('modules' => array('gmp', 'php_gmp'),
+ 'extension' => 'gmp',
+ 'class' => 'Auth_OpenID_GmpMathWrapper');
+ }
+
+ $result[] = array('modules' => array('bcmath', 'php_bcmath'),
+ 'extension' => 'bcmath',
+ 'class' => 'Auth_OpenID_BcMathWrapper');
+
+ return $result;
+}
+
+/**
+ * Detect which (if any) math library is available
+ */
+function Auth_OpenID_detectMathLibrary($exts)
+{
+ $loaded = false;
+
+ foreach ($exts as $extension) {
+ if (extension_loaded($extension['extension'])) {
+ return $extension;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * {@link Auth_OpenID_getMathLib} checks for the presence of long
+ * number extension modules and returns an instance of
+ * {@link Auth_OpenID_MathWrapper} which exposes the module's
+ * functionality.
+ *
+ * Checks for the existence of an extension module described by the
+ * result of {@link Auth_OpenID_math_extensions()} and returns an
+ * instance of a wrapper for that extension module. If no extension
+ * module is found, an instance of {@link Auth_OpenID_MathWrapper} is
+ * returned, which wraps the native PHP integer implementation. The
+ * proper calling convention for this method is $lib =
+ * Auth_OpenID_getMathLib().
+ *
+ * This function checks for the existence of specific long number
+ * implementations in the following order: GMP followed by BCmath.
+ *
+ * @return Auth_OpenID_MathWrapper $instance An instance of
+ * {@link Auth_OpenID_MathWrapper} or one of its subclasses
+ *
+ * @package OpenID
+ */
+function Auth_OpenID_getMathLib()
+{
+ // The instance of Auth_OpenID_MathWrapper that we choose to
+ // supply will be stored here, so that subseqent calls to this
+ // method will return a reference to the same object.
+ static $lib = null;
+
+ if (isset($lib)) {
+ return $lib;
+ }
+
+ if (Auth_OpenID_noMathSupport()) {
+ $null = null;
+ return $null;
+ }
+
+ // If this method has not been called before, look at
+ // Auth_OpenID_math_extensions and try to find an extension that
+ // works.
+ $ext = Auth_OpenID_detectMathLibrary(Auth_OpenID_math_extensions());
+ if ($ext === false) {
+ $tried = array();
+ foreach (Auth_OpenID_math_extensions() as $extinfo) {
+ $tried[] = $extinfo['extension'];
+ }
+ $triedstr = implode(", ", $tried);
+
+ Auth_OpenID_setNoMathSupport();
+
+ $result = null;
+ return $result;
+ }
+
+ // Instantiate a new wrapper
+ $class = $ext['class'];
+ $lib = new $class();
+
+ return $lib;
+}
+
+function Auth_OpenID_setNoMathSupport()
+{
+ if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
+ define('Auth_OpenID_NO_MATH_SUPPORT', true);
+ }
+}
+
+function Auth_OpenID_noMathSupport()
+{
+ return defined('Auth_OpenID_NO_MATH_SUPPORT');
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/Consumer.php b/plugins/openid/lib/Auth/OpenID/Consumer.php
new file mode 100644
index 00000000..d562e33f
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Consumer.php
@@ -0,0 +1,2236 @@
+<?php
+
+/**
+ * This module documents the main interface with the OpenID consumer
+ * library. The only part of the library which has to be used and
+ * isn't documented in full here is the store required to create an
+ * Auth_OpenID_Consumer instance. More on the abstract store type and
+ * concrete implementations of it that are provided in the
+ * documentation for the Auth_OpenID_Consumer constructor.
+ *
+ * OVERVIEW
+ *
+ * The OpenID identity verification process most commonly uses the
+ * following steps, as visible to the user of this library:
+ *
+ * 1. The user enters their OpenID into a field on the consumer's
+ * site, and hits a login button.
+ * 2. The consumer site discovers the user's OpenID server using the
+ * YADIS protocol.
+ * 3. The consumer site sends the browser a redirect to the identity
+ * server. This is the authentication request as described in
+ * the OpenID specification.
+ * 4. The identity server's site sends the browser a redirect back
+ * to the consumer site. This redirect contains the server's
+ * response to the authentication request.
+ *
+ * The most important part of the flow to note is the consumer's site
+ * must handle two separate HTTP requests in order to perform the full
+ * identity check.
+ *
+ * LIBRARY DESIGN
+ *
+ * This consumer library is designed with that flow in mind. The goal
+ * is to make it as easy as possible to perform the above steps
+ * securely.
+ *
+ * At a high level, there are two important parts in the consumer
+ * library. The first important part is this module, which contains
+ * the interface to actually use this library. The second is the
+ * Auth_OpenID_Interface class, which describes the interface to use
+ * if you need to create a custom method for storing the state this
+ * library needs to maintain between requests.
+ *
+ * In general, the second part is less important for users of the
+ * library to know about, as several implementations are provided
+ * which cover a wide variety of situations in which consumers may use
+ * the library.
+ *
+ * This module contains a class, Auth_OpenID_Consumer, with methods
+ * corresponding to the actions necessary in each of steps 2, 3, and 4
+ * described in the overview. Use of this library should be as easy
+ * as creating an Auth_OpenID_Consumer instance and calling the
+ * methods appropriate for the action the site wants to take.
+ *
+ * STORES AND DUMB MODE
+ *
+ * OpenID is a protocol that works best when the consumer site is able
+ * to store some state. This is the normal mode of operation for the
+ * protocol, and is sometimes referred to as smart mode. There is
+ * also a fallback mode, known as dumb mode, which is available when
+ * the consumer site is not able to store state. This mode should be
+ * avoided when possible, as it leaves the implementation more
+ * vulnerable to replay attacks.
+ *
+ * The mode the library works in for normal operation is determined by
+ * the store that it is given. The store is an abstraction that
+ * handles the data that the consumer needs to manage between http
+ * requests in order to operate efficiently and securely.
+ *
+ * Several store implementation are provided, and the interface is
+ * fully documented so that custom stores can be used as well. See
+ * the documentation for the Auth_OpenID_Consumer class for more
+ * information on the interface for stores. The implementations that
+ * are provided allow the consumer site to store the necessary data in
+ * several different ways, including several SQL databases and normal
+ * files on disk.
+ *
+ * There is an additional concrete store provided that puts the system
+ * in dumb mode. This is not recommended, as it removes the library's
+ * ability to stop replay attacks reliably. It still uses time-based
+ * checking to make replay attacks only possible within a small
+ * window, but they remain possible within that window. This store
+ * should only be used if the consumer site has no way to retain data
+ * between requests at all.
+ *
+ * IMMEDIATE MODE
+ *
+ * In the flow described above, the user may need to confirm to the
+ * lidentity server that it's ok to authorize his or her identity.
+ * The server may draw pages asking for information from the user
+ * before it redirects the browser back to the consumer's site. This
+ * is generally transparent to the consumer site, so it is typically
+ * ignored as an implementation detail.
+ *
+ * There can be times, however, where the consumer site wants to get a
+ * response immediately. When this is the case, the consumer can put
+ * the library in immediate mode. In immediate mode, there is an
+ * extra response possible from the server, which is essentially the
+ * server reporting that it doesn't have enough information to answer
+ * the question yet.
+ *
+ * USING THIS LIBRARY
+ *
+ * Integrating this library into an application is usually a
+ * relatively straightforward process. The process should basically
+ * follow this plan:
+ *
+ * Add an OpenID login field somewhere on your site. When an OpenID
+ * is entered in that field and the form is submitted, it should make
+ * a request to the your site which includes that OpenID URL.
+ *
+ * First, the application should instantiate the Auth_OpenID_Consumer
+ * class using the store of choice (Auth_OpenID_FileStore or one of
+ * the SQL-based stores). If the application has a custom
+ * session-management implementation, an object implementing the
+ * {@link Auth_Yadis_PHPSession} interface should be passed as the
+ * second parameter. Otherwise, the default uses $_SESSION.
+ *
+ * Next, the application should call the Auth_OpenID_Consumer object's
+ * 'begin' method. This method takes the OpenID URL. The 'begin'
+ * method returns an Auth_OpenID_AuthRequest object.
+ *
+ * Next, the application should call the 'redirectURL' method of the
+ * Auth_OpenID_AuthRequest object. The 'return_to' URL parameter is
+ * the URL that the OpenID server will send the user back to after
+ * attempting to verify his or her identity. The 'trust_root' is the
+ * URL (or URL pattern) that identifies your web site to the user when
+ * he or she is authorizing it. Send a redirect to the resulting URL
+ * to the user's browser.
+ *
+ * That's the first half of the authentication process. The second
+ * half of the process is done after the user's ID server sends the
+ * user's browser a redirect back to your site to complete their
+ * login.
+ *
+ * When that happens, the user will contact your site at the URL given
+ * as the 'return_to' URL to the Auth_OpenID_AuthRequest::redirectURL
+ * call made above. The request will have several query parameters
+ * added to the URL by the identity server as the information
+ * necessary to finish the request.
+ *
+ * Lastly, instantiate an Auth_OpenID_Consumer instance as above and
+ * call its 'complete' method, passing in all the received query
+ * arguments.
+ *
+ * There are multiple possible return types possible from that
+ * method. These indicate the whether or not the login was successful,
+ * and include any additional information appropriate for their type.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Require utility classes and functions for the consumer.
+ */
+require_once "Auth/OpenID.php";
+require_once "Auth/OpenID/Message.php";
+require_once "Auth/OpenID/HMAC.php";
+require_once "Auth/OpenID/Association.php";
+require_once "Auth/OpenID/CryptUtil.php";
+require_once "Auth/OpenID/DiffieHellman.php";
+require_once "Auth/OpenID/KVForm.php";
+require_once "Auth/OpenID/Nonce.php";
+require_once "Auth/OpenID/Discover.php";
+require_once "Auth/OpenID/URINorm.php";
+require_once "Auth/Yadis/Manager.php";
+require_once "Auth/Yadis/XRI.php";
+
+/**
+ * This is the status code returned when the complete method returns
+ * successfully.
+ */
+define('Auth_OpenID_SUCCESS', 'success');
+
+/**
+ * Status to indicate cancellation of OpenID authentication.
+ */
+define('Auth_OpenID_CANCEL', 'cancel');
+
+/**
+ * This is the status code completeAuth returns when the value it
+ * received indicated an invalid login.
+ */
+define('Auth_OpenID_FAILURE', 'failure');
+
+/**
+ * This is the status code completeAuth returns when the
+ * {@link Auth_OpenID_Consumer} instance is in immediate mode, and the
+ * identity server sends back a URL to send the user to to complete his
+ * or her login.
+ */
+define('Auth_OpenID_SETUP_NEEDED', 'setup needed');
+
+/**
+ * This is the status code beginAuth returns when the page fetched
+ * from the entered OpenID URL doesn't contain the necessary link tags
+ * to function as an identity page.
+ */
+define('Auth_OpenID_PARSE_ERROR', 'parse error');
+
+/**
+ * An OpenID consumer implementation that performs discovery and does
+ * session management. See the Consumer.php file documentation for
+ * more information.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Consumer {
+
+ /**
+ * @access private
+ */
+ var $discoverMethod = 'Auth_OpenID_discover';
+
+ /**
+ * @access private
+ */
+ var $session_key_prefix = "_openid_consumer_";
+
+ /**
+ * @access private
+ */
+ var $_token_suffix = "last_token";
+
+ /**
+ * Initialize a Consumer instance.
+ *
+ * You should create a new instance of the Consumer object with
+ * every HTTP request that handles OpenID transactions.
+ *
+ * @param Auth_OpenID_OpenIDStore $store This must be an object
+ * that implements the interface in {@link
+ * Auth_OpenID_OpenIDStore}. Several concrete implementations are
+ * provided, to cover most common use cases. For stores backed by
+ * MySQL, PostgreSQL, or SQLite, see the {@link
+ * Auth_OpenID_SQLStore} class and its sublcasses. For a
+ * filesystem-backed store, see the {@link Auth_OpenID_FileStore}
+ * module. As a last resort, if it isn't possible for the server
+ * to store state at all, an instance of {@link
+ * Auth_OpenID_DumbStore} can be used.
+ *
+ * @param mixed $session An object which implements the interface
+ * of the {@link Auth_Yadis_PHPSession} class. Particularly, this
+ * object is expected to have these methods: get($key), set($key),
+ * $value), and del($key). This defaults to a session object
+ * which wraps PHP's native session machinery. You should only
+ * need to pass something here if you have your own sessioning
+ * implementation.
+ *
+ * @param str $consumer_cls The name of the class to instantiate
+ * when creating the internal consumer object. This is used for
+ * testing.
+ */
+ function Auth_OpenID_Consumer($store, $session = null,
+ $consumer_cls = null)
+ {
+ if ($session === null) {
+ $session = new Auth_Yadis_PHPSession();
+ }
+
+ $this->session = $session;
+
+ if ($consumer_cls !== null) {
+ $this->consumer = new $consumer_cls($store);
+ } else {
+ $this->consumer = new Auth_OpenID_GenericConsumer($store);
+ }
+
+ $this->_token_key = $this->session_key_prefix . $this->_token_suffix;
+ }
+
+ /**
+ * Used in testing to define the discovery mechanism.
+ *
+ * @access private
+ */
+ function getDiscoveryObject($session, $openid_url,
+ $session_key_prefix)
+ {
+ return new Auth_Yadis_Discovery($session, $openid_url,
+ $session_key_prefix);
+ }
+
+ /**
+ * Start the OpenID authentication process. See steps 1-2 in the
+ * overview at the top of this file.
+ *
+ * @param string $user_url Identity URL given by the user. This
+ * method performs a textual transformation of the URL to try and
+ * make sure it is normalized. For example, a user_url of
+ * example.com will be normalized to http://example.com/
+ * normalizing and resolving any redirects the server might issue.
+ *
+ * @param bool $anonymous True if the OpenID request is to be sent
+ * to the server without any identifier information. Use this
+ * when you want to transport data but don't want to do OpenID
+ * authentication with identifiers.
+ *
+ * @return Auth_OpenID_AuthRequest $auth_request An object
+ * containing the discovered information will be returned, with a
+ * method for building a redirect URL to the server, as described
+ * in step 3 of the overview. This object may also be used to add
+ * extension arguments to the request, using its 'addExtensionArg'
+ * method.
+ */
+ function begin($user_url, $anonymous=false)
+ {
+ $openid_url = $user_url;
+
+ $disco = $this->getDiscoveryObject($this->session,
+ $openid_url,
+ $this->session_key_prefix);
+
+ // Set the 'stale' attribute of the manager. If discovery
+ // fails in a fatal way, the stale flag will cause the manager
+ // to be cleaned up next time discovery is attempted.
+
+ $m = $disco->getManager();
+ $loader = new Auth_Yadis_ManagerLoader();
+
+ if ($m) {
+ if ($m->stale) {
+ $disco->destroyManager();
+ } else {
+ $m->stale = true;
+ $disco->session->set($disco->session_key,
+ serialize($loader->toSession($m)));
+ }
+ }
+
+ $endpoint = $disco->getNextService($this->discoverMethod,
+ $this->consumer->fetcher);
+
+ // Reset the 'stale' attribute of the manager.
+ $m = $disco->getManager();
+ if ($m) {
+ $m->stale = false;
+ $disco->session->set($disco->session_key,
+ serialize($loader->toSession($m)));
+ }
+
+ if ($endpoint === null) {
+ return null;
+ } else {
+ return $this->beginWithoutDiscovery($endpoint,
+ $anonymous);
+ }
+ }
+
+ /**
+ * Start OpenID verification without doing OpenID server
+ * discovery. This method is used internally by Consumer.begin
+ * after discovery is performed, and exists to provide an
+ * interface for library users needing to perform their own
+ * discovery.
+ *
+ * @param Auth_OpenID_ServiceEndpoint $endpoint an OpenID service
+ * endpoint descriptor.
+ *
+ * @param bool anonymous Set to true if you want to perform OpenID
+ * without identifiers.
+ *
+ * @return Auth_OpenID_AuthRequest $auth_request An OpenID
+ * authentication request object.
+ */
+ function beginWithoutDiscovery($endpoint, $anonymous=false)
+ {
+ $loader = new Auth_OpenID_ServiceEndpointLoader();
+ $auth_req = $this->consumer->begin($endpoint);
+ $this->session->set($this->_token_key,
+ $loader->toSession($auth_req->endpoint));
+ if (!$auth_req->setAnonymous($anonymous)) {
+ return new Auth_OpenID_FailureResponse(null,
+ "OpenID 1 requests MUST include the identifier " .
+ "in the request.");
+ }
+ return $auth_req;
+ }
+
+ /**
+ * Called to interpret the server's response to an OpenID
+ * request. It is called in step 4 of the flow described in the
+ * consumer overview.
+ *
+ * @param string $current_url The URL used to invoke the application.
+ * Extract the URL from your application's web
+ * request framework and specify it here to have it checked
+ * against the openid.current_url value in the response. If
+ * the current_url URL check fails, the status of the
+ * completion will be FAILURE.
+ *
+ * @param array $query An array of the query parameters (key =>
+ * value pairs) for this HTTP request. Defaults to null. If
+ * null, the GET or POST data are automatically gotten from the
+ * PHP environment. It is only useful to override $query for
+ * testing.
+ *
+ * @return Auth_OpenID_ConsumerResponse $response A instance of an
+ * Auth_OpenID_ConsumerResponse subclass. The type of response is
+ * indicated by the status attribute, which will be one of
+ * SUCCESS, CANCEL, FAILURE, or SETUP_NEEDED.
+ */
+ function complete($current_url, $query=null)
+ {
+ if ($current_url && !is_string($current_url)) {
+ // This is ugly, but we need to complain loudly when
+ // someone uses the API incorrectly.
+ trigger_error("current_url must be a string; see NEWS file " .
+ "for upgrading notes.",
+ E_USER_ERROR);
+ }
+
+ if ($query === null) {
+ $query = Auth_OpenID::getQuery();
+ }
+
+ $loader = new Auth_OpenID_ServiceEndpointLoader();
+ $endpoint_data = $this->session->get($this->_token_key);
+ $endpoint =
+ $loader->fromSession($endpoint_data);
+
+ $message = Auth_OpenID_Message::fromPostArgs($query);
+ $response = $this->consumer->complete($message, $endpoint,
+ $current_url);
+ $this->session->del($this->_token_key);
+
+ if (in_array($response->status, array(Auth_OpenID_SUCCESS,
+ Auth_OpenID_CANCEL))) {
+ if ($response->identity_url !== null) {
+ $disco = $this->getDiscoveryObject($this->session,
+ $response->identity_url,
+ $this->session_key_prefix);
+ $disco->cleanup(true);
+ }
+ }
+
+ return $response;
+ }
+}
+
+/**
+ * A class implementing HMAC/DH-SHA1 consumer sessions.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_DiffieHellmanSHA1ConsumerSession {
+ var $session_type = 'DH-SHA1';
+ var $hash_func = 'Auth_OpenID_SHA1';
+ var $secret_size = 20;
+ var $allowed_assoc_types = array('HMAC-SHA1');
+
+ function Auth_OpenID_DiffieHellmanSHA1ConsumerSession($dh = null)
+ {
+ if ($dh === null) {
+ $dh = new Auth_OpenID_DiffieHellman();
+ }
+
+ $this->dh = $dh;
+ }
+
+ function getRequest()
+ {
+ $math = Auth_OpenID_getMathLib();
+
+ $cpub = $math->longToBase64($this->dh->public);
+
+ $args = array('dh_consumer_public' => $cpub);
+
+ if (!$this->dh->usingDefaultValues()) {
+ $args = array_merge($args, array(
+ 'dh_modulus' =>
+ $math->longToBase64($this->dh->mod),
+ 'dh_gen' =>
+ $math->longToBase64($this->dh->gen)));
+ }
+
+ return $args;
+ }
+
+ function extractSecret($response)
+ {
+ if (!$response->hasKey(Auth_OpenID_OPENID_NS,
+ 'dh_server_public')) {
+ return null;
+ }
+
+ if (!$response->hasKey(Auth_OpenID_OPENID_NS,
+ 'enc_mac_key')) {
+ return null;
+ }
+
+ $math = Auth_OpenID_getMathLib();
+
+ $spub = $math->base64ToLong($response->getArg(Auth_OpenID_OPENID_NS,
+ 'dh_server_public'));
+ $enc_mac_key = base64_decode($response->getArg(Auth_OpenID_OPENID_NS,
+ 'enc_mac_key'));
+
+ return $this->dh->xorSecret($spub, $enc_mac_key, $this->hash_func);
+ }
+}
+
+/**
+ * A class implementing HMAC/DH-SHA256 consumer sessions.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_DiffieHellmanSHA256ConsumerSession extends
+ Auth_OpenID_DiffieHellmanSHA1ConsumerSession {
+ var $session_type = 'DH-SHA256';
+ var $hash_func = 'Auth_OpenID_SHA256';
+ var $secret_size = 32;
+ var $allowed_assoc_types = array('HMAC-SHA256');
+}
+
+/**
+ * A class implementing plaintext consumer sessions.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_PlainTextConsumerSession {
+ var $session_type = 'no-encryption';
+ var $allowed_assoc_types = array('HMAC-SHA1', 'HMAC-SHA256');
+
+ function getRequest()
+ {
+ return array();
+ }
+
+ function extractSecret($response)
+ {
+ if (!$response->hasKey(Auth_OpenID_OPENID_NS, 'mac_key')) {
+ return null;
+ }
+
+ return base64_decode($response->getArg(Auth_OpenID_OPENID_NS,
+ 'mac_key'));
+ }
+}
+
+/**
+ * Returns available session types.
+ */
+function Auth_OpenID_getAvailableSessionTypes()
+{
+ $types = array(
+ 'no-encryption' => 'Auth_OpenID_PlainTextConsumerSession',
+ 'DH-SHA1' => 'Auth_OpenID_DiffieHellmanSHA1ConsumerSession',
+ 'DH-SHA256' => 'Auth_OpenID_DiffieHellmanSHA256ConsumerSession');
+
+ return $types;
+}
+
+/**
+ * This class is the interface to the OpenID consumer logic.
+ * Instances of it maintain no per-request state, so they can be
+ * reused (or even used by multiple threads concurrently) as needed.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_GenericConsumer {
+ /**
+ * @access private
+ */
+ var $discoverMethod = 'Auth_OpenID_discover';
+
+ /**
+ * This consumer's store object.
+ */
+ var $store;
+
+ /**
+ * @access private
+ */
+ var $_use_assocs;
+
+ /**
+ * @access private
+ */
+ var $openid1_nonce_query_arg_name = 'janrain_nonce';
+
+ /**
+ * Another query parameter that gets added to the return_to for
+ * OpenID 1; if the user's session state is lost, use this claimed
+ * identifier to do discovery when verifying the response.
+ */
+ var $openid1_return_to_identifier_name = 'openid1_claimed_id';
+
+ /**
+ * This method initializes a new {@link Auth_OpenID_Consumer}
+ * instance to access the library.
+ *
+ * @param Auth_OpenID_OpenIDStore $store This must be an object
+ * that implements the interface in {@link Auth_OpenID_OpenIDStore}.
+ * Several concrete implementations are provided, to cover most common use
+ * cases. For stores backed by MySQL, PostgreSQL, or SQLite, see
+ * the {@link Auth_OpenID_SQLStore} class and its sublcasses. For a
+ * filesystem-backed store, see the {@link Auth_OpenID_FileStore} module.
+ * As a last resort, if it isn't possible for the server to store
+ * state at all, an instance of {@link Auth_OpenID_DumbStore} can be used.
+ *
+ * @param bool $immediate This is an optional boolean value. It
+ * controls whether the library uses immediate mode, as explained
+ * in the module description. The default value is False, which
+ * disables immediate mode.
+ */
+ function Auth_OpenID_GenericConsumer($store)
+ {
+ $this->store = $store;
+ $this->negotiator = Auth_OpenID_getDefaultNegotiator();
+ $this->_use_assocs = (is_null($this->store) ? false : true);
+
+ $this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
+
+ $this->session_types = Auth_OpenID_getAvailableSessionTypes();
+ }
+
+ /**
+ * Called to begin OpenID authentication using the specified
+ * {@link Auth_OpenID_ServiceEndpoint}.
+ *
+ * @access private
+ */
+ function begin($service_endpoint)
+ {
+ $assoc = $this->_getAssociation($service_endpoint);
+ $r = new Auth_OpenID_AuthRequest($service_endpoint, $assoc);
+ $r->return_to_args[$this->openid1_nonce_query_arg_name] =
+ Auth_OpenID_mkNonce();
+
+ if ($r->message->isOpenID1()) {
+ $r->return_to_args[$this->openid1_return_to_identifier_name] =
+ $r->endpoint->claimed_id;
+ }
+
+ return $r;
+ }
+
+ /**
+ * Given an {@link Auth_OpenID_Message}, {@link
+ * Auth_OpenID_ServiceEndpoint} and optional return_to URL,
+ * complete OpenID authentication.
+ *
+ * @access private
+ */
+ function complete($message, $endpoint, $return_to)
+ {
+ $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode',
+ '<no mode set>');
+
+ $mode_methods = array(
+ 'cancel' => '_complete_cancel',
+ 'error' => '_complete_error',
+ 'setup_needed' => '_complete_setup_needed',
+ 'id_res' => '_complete_id_res',
+ );
+
+ $method = Auth_OpenID::arrayGet($mode_methods, $mode,
+ '_completeInvalid');
+
+ return call_user_func_array(array($this, $method),
+ array($message, &$endpoint, $return_to));
+ }
+
+ /**
+ * @access private
+ */
+ function _completeInvalid($message, $endpoint, $unused)
+ {
+ $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode',
+ '<No mode set>');
+
+ return new Auth_OpenID_FailureResponse($endpoint,
+ sprintf("Invalid openid.mode '%s'", $mode));
+ }
+
+ /**
+ * @access private
+ */
+ function _complete_cancel($message, $endpoint, $unused)
+ {
+ return new Auth_OpenID_CancelResponse($endpoint);
+ }
+
+ /**
+ * @access private
+ */
+ function _complete_error($message, $endpoint, $unused)
+ {
+ $error = $message->getArg(Auth_OpenID_OPENID_NS, 'error');
+ $contact = $message->getArg(Auth_OpenID_OPENID_NS, 'contact');
+ $reference = $message->getArg(Auth_OpenID_OPENID_NS, 'reference');
+
+ return new Auth_OpenID_FailureResponse($endpoint, $error,
+ $contact, $reference);
+ }
+
+ /**
+ * @access private
+ */
+ function _complete_setup_needed($message, $endpoint, $unused)
+ {
+ if (!$message->isOpenID2()) {
+ return $this->_completeInvalid($message, $endpoint);
+ }
+
+ $user_setup_url = $message->getArg(Auth_OpenID_OPENID2_NS,
+ 'user_setup_url');
+ return new Auth_OpenID_SetupNeededResponse($endpoint, $user_setup_url);
+ }
+
+ /**
+ * @access private
+ */
+ function _complete_id_res($message, $endpoint, $return_to)
+ {
+ $user_setup_url = $message->getArg(Auth_OpenID_OPENID1_NS,
+ 'user_setup_url');
+
+ if ($this->_checkSetupNeeded($message)) {
+ return new Auth_OpenID_SetupNeededResponse(
+ $endpoint, $user_setup_url);
+ } else {
+ return $this->_doIdRes($message, $endpoint, $return_to);
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _checkSetupNeeded($message)
+ {
+ // In OpenID 1, we check to see if this is a cancel from
+ // immediate mode by the presence of the user_setup_url
+ // parameter.
+ if ($message->isOpenID1()) {
+ $user_setup_url = $message->getArg(Auth_OpenID_OPENID1_NS,
+ 'user_setup_url');
+ if ($user_setup_url !== null) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @access private
+ */
+ function _doIdRes($message, $endpoint, $return_to)
+ {
+ // Checks for presence of appropriate fields (and checks
+ // signed list fields)
+ $result = $this->_idResCheckForFields($message);
+
+ if (Auth_OpenID::isFailure($result)) {
+ return $result;
+ }
+
+ if (!$this->_checkReturnTo($message, $return_to)) {
+ return new Auth_OpenID_FailureResponse(null,
+ sprintf("return_to does not match return URL. Expected %s, got %s",
+ $return_to,
+ $message->getArg(Auth_OpenID_OPENID_NS, 'return_to')));
+ }
+
+ // Verify discovery information:
+ $result = $this->_verifyDiscoveryResults($message, $endpoint);
+
+ if (Auth_OpenID::isFailure($result)) {
+ return $result;
+ }
+
+ $endpoint = $result;
+
+ $result = $this->_idResCheckSignature($message,
+ $endpoint->server_url);
+
+ if (Auth_OpenID::isFailure($result)) {
+ return $result;
+ }
+
+ $result = $this->_idResCheckNonce($message, $endpoint);
+
+ if (Auth_OpenID::isFailure($result)) {
+ return $result;
+ }
+
+ $signed_list_str = $message->getArg(Auth_OpenID_OPENID_NS, 'signed',
+ Auth_OpenID_NO_DEFAULT);
+ if (Auth_OpenID::isFailure($signed_list_str)) {
+ return $signed_list_str;
+ }
+ $signed_list = explode(',', $signed_list_str);
+
+ $signed_fields = Auth_OpenID::addPrefix($signed_list, "openid.");
+
+ return new Auth_OpenID_SuccessResponse($endpoint, $message,
+ $signed_fields);
+
+ }
+
+ /**
+ * @access private
+ */
+ function _checkReturnTo($message, $return_to)
+ {
+ // Check an OpenID message and its openid.return_to value
+ // against a return_to URL from an application. Return True
+ // on success, False on failure.
+
+ // Check the openid.return_to args against args in the
+ // original message.
+ $result = Auth_OpenID_GenericConsumer::_verifyReturnToArgs(
+ $message->toPostArgs());
+ if (Auth_OpenID::isFailure($result)) {
+ return false;
+ }
+
+ // Check the return_to base URL against the one in the
+ // message.
+ $msg_return_to = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'return_to');
+ if (Auth_OpenID::isFailure($return_to)) {
+ // XXX log me
+ return false;
+ }
+
+ $return_to_parts = parse_url(Auth_OpenID_urinorm($return_to));
+ $msg_return_to_parts = parse_url(Auth_OpenID_urinorm($msg_return_to));
+
+ // If port is absent from both, add it so it's equal in the
+ // check below.
+ if ((!array_key_exists('port', $return_to_parts)) &&
+ (!array_key_exists('port', $msg_return_to_parts))) {
+ $return_to_parts['port'] = null;
+ $msg_return_to_parts['port'] = null;
+ }
+
+ // If path is absent from both, add it so it's equal in the
+ // check below.
+ if ((!array_key_exists('path', $return_to_parts)) &&
+ (!array_key_exists('path', $msg_return_to_parts))) {
+ $return_to_parts['path'] = null;
+ $msg_return_to_parts['path'] = null;
+ }
+
+ // The URL scheme, authority, and path MUST be the same
+ // between the two URLs.
+ foreach (array('scheme', 'host', 'port', 'path') as $component) {
+ // If the url component is absent in either URL, fail.
+ // There should always be a scheme, host, port, and path.
+ if (!array_key_exists($component, $return_to_parts)) {
+ return false;
+ }
+
+ if (!array_key_exists($component, $msg_return_to_parts)) {
+ return false;
+ }
+
+ if (Auth_OpenID::arrayGet($return_to_parts, $component) !==
+ Auth_OpenID::arrayGet($msg_return_to_parts, $component)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @access private
+ */
+ function _verifyReturnToArgs($query)
+ {
+ // Verify that the arguments in the return_to URL are present in this
+ // response.
+
+ $message = Auth_OpenID_Message::fromPostArgs($query);
+ $return_to = $message->getArg(Auth_OpenID_OPENID_NS, 'return_to');
+
+ if (Auth_OpenID::isFailure($return_to)) {
+ return $return_to;
+ }
+ // XXX: this should be checked by _idResCheckForFields
+ if (!$return_to) {
+ return new Auth_OpenID_FailureResponse(null,
+ "Response has no return_to");
+ }
+
+ $parsed_url = parse_url($return_to);
+
+ $q = array();
+ if (array_key_exists('query', $parsed_url)) {
+ $rt_query = $parsed_url['query'];
+ $q = Auth_OpenID::parse_str($rt_query);
+ }
+
+ foreach ($q as $rt_key => $rt_value) {
+ if (!array_key_exists($rt_key, $query)) {
+ return new Auth_OpenID_FailureResponse(null,
+ sprintf("return_to parameter %s absent from query", $rt_key));
+ } else {
+ $value = $query[$rt_key];
+ if ($rt_value != $value) {
+ return new Auth_OpenID_FailureResponse(null,
+ sprintf("parameter %s value %s does not match " .
+ "return_to value %s", $rt_key,
+ $value, $rt_value));
+ }
+ }
+ }
+
+ // Make sure all non-OpenID arguments in the response are also
+ // in the signed return_to.
+ $bare_args = $message->getArgs(Auth_OpenID_BARE_NS);
+ foreach ($bare_args as $key => $value) {
+ if (Auth_OpenID::arrayGet($q, $key) != $value) {
+ return new Auth_OpenID_FailureResponse(null,
+ sprintf("Parameter %s = %s not in return_to URL",
+ $key, $value));
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @access private
+ */
+ function _idResCheckSignature($message, $server_url)
+ {
+ $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'assoc_handle');
+ if (Auth_OpenID::isFailure($assoc_handle)) {
+ return $assoc_handle;
+ }
+
+ $assoc = $this->store->getAssociation($server_url, $assoc_handle);
+
+ if ($assoc) {
+ if ($assoc->getExpiresIn() <= 0) {
+ // XXX: It might be a good idea sometimes to re-start
+ // the authentication with a new association. Doing it
+ // automatically opens the possibility for
+ // denial-of-service by a server that just returns
+ // expired associations (or really short-lived
+ // associations)
+ return new Auth_OpenID_FailureResponse(null,
+ 'Association with ' . $server_url . ' expired');
+ }
+
+ if (!$assoc->checkMessageSignature($message)) {
+ // If we get a "bad signature" here, it means that the association
+ // is unrecoverabley corrupted in some way. Any futher attempts
+ // to login with this association is likely to fail. Drop it.
+ $this->store->removeAssociation($server_url, $assoc_handle);
+ return new Auth_OpenID_FailureResponse(null,
+ "Bad signature");
+ }
+ } else {
+ // It's not an association we know about. Stateless mode
+ // is our only possible path for recovery. XXX - async
+ // framework will not want to block on this call to
+ // _checkAuth.
+ if (!$this->_checkAuth($message, $server_url)) {
+ return new Auth_OpenID_FailureResponse(null,
+ "Server denied check_authentication");
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @access private
+ */
+ function _verifyDiscoveryResults($message, $endpoint=null)
+ {
+ if ($message->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS) {
+ return $this->_verifyDiscoveryResultsOpenID2($message,
+ $endpoint);
+ } else {
+ return $this->_verifyDiscoveryResultsOpenID1($message,
+ $endpoint);
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _verifyDiscoveryResultsOpenID1($message, $endpoint)
+ {
+ $claimed_id = $message->getArg(Auth_OpenID_BARE_NS,
+ $this->openid1_return_to_identifier_name);
+
+ if (($endpoint === null) && ($claimed_id === null)) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ 'When using OpenID 1, the claimed ID must be supplied, ' .
+ 'either by passing it through as a return_to parameter ' .
+ 'or by using a session, and supplied to the GenericConsumer ' .
+ 'as the argument to complete()');
+ } else if (($endpoint !== null) && ($claimed_id === null)) {
+ $claimed_id = $endpoint->claimed_id;
+ }
+
+ $to_match = new Auth_OpenID_ServiceEndpoint();
+ $to_match->type_uris = array(Auth_OpenID_TYPE_1_1);
+ $to_match->local_id = $message->getArg(Auth_OpenID_OPENID1_NS,
+ 'identity');
+
+ // Restore delegate information from the initiation phase
+ $to_match->claimed_id = $claimed_id;
+
+ if ($to_match->local_id === null) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ "Missing required field openid.identity");
+ }
+
+ $to_match_1_0 = $to_match->copy();
+ $to_match_1_0->type_uris = array(Auth_OpenID_TYPE_1_0);
+
+ if ($endpoint !== null) {
+ $result = $this->_verifyDiscoverySingle($endpoint, $to_match);
+
+ if (is_a($result, 'Auth_OpenID_TypeURIMismatch')) {
+ $result = $this->_verifyDiscoverySingle($endpoint,
+ $to_match_1_0);
+ }
+
+ if (Auth_OpenID::isFailure($result)) {
+ // oidutil.log("Error attempting to use stored
+ // discovery information: " + str(e))
+ // oidutil.log("Attempting discovery to
+ // verify endpoint")
+ } else {
+ return $endpoint;
+ }
+ }
+
+ // Endpoint is either bad (failed verification) or None
+ return $this->_discoverAndVerify($to_match->claimed_id,
+ array($to_match, $to_match_1_0));
+ }
+
+ /**
+ * @access private
+ */
+ function _verifyDiscoverySingle($endpoint, $to_match)
+ {
+ // Every type URI that's in the to_match endpoint has to be
+ // present in the discovered endpoint.
+ foreach ($to_match->type_uris as $type_uri) {
+ if (!$endpoint->usesExtension($type_uri)) {
+ return new Auth_OpenID_TypeURIMismatch($endpoint,
+ "Required type ".$type_uri." not present");
+ }
+ }
+
+ // Fragments do not influence discovery, so we can't compare a
+ // claimed identifier with a fragment to discovered
+ // information.
+ list($defragged_claimed_id, $_) =
+ Auth_OpenID::urldefrag($to_match->claimed_id);
+
+ if ($defragged_claimed_id != $endpoint->claimed_id) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ sprintf('Claimed ID does not match (different subjects!), ' .
+ 'Expected %s, got %s', $defragged_claimed_id,
+ $endpoint->claimed_id));
+ }
+
+ if ($to_match->getLocalID() != $endpoint->getLocalID()) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ sprintf('local_id mismatch. Expected %s, got %s',
+ $to_match->getLocalID(), $endpoint->getLocalID()));
+ }
+
+ // If the server URL is None, this must be an OpenID 1
+ // response, because op_endpoint is a required parameter in
+ // OpenID 2. In that case, we don't actually care what the
+ // discovered server_url is, because signature checking or
+ // check_auth should take care of that check for us.
+ if ($to_match->server_url === null) {
+ if ($to_match->preferredNamespace() != Auth_OpenID_OPENID1_NS) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ "Preferred namespace mismatch (bug)");
+ }
+ } else if ($to_match->server_url != $endpoint->server_url) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ sprintf('OP Endpoint mismatch. Expected %s, got %s',
+ $to_match->server_url, $endpoint->server_url));
+ }
+
+ return null;
+ }
+
+ /**
+ * @access private
+ */
+ function _verifyDiscoveryResultsOpenID2($message, $endpoint)
+ {
+ $to_match = new Auth_OpenID_ServiceEndpoint();
+ $to_match->type_uris = array(Auth_OpenID_TYPE_2_0);
+ $to_match->claimed_id = $message->getArg(Auth_OpenID_OPENID2_NS,
+ 'claimed_id');
+
+ $to_match->local_id = $message->getArg(Auth_OpenID_OPENID2_NS,
+ 'identity');
+
+ $to_match->server_url = $message->getArg(Auth_OpenID_OPENID2_NS,
+ 'op_endpoint');
+
+ if ($to_match->server_url === null) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ "OP Endpoint URL missing");
+ }
+
+ // claimed_id and identifier must both be present or both be
+ // absent
+ if (($to_match->claimed_id === null) &&
+ ($to_match->local_id !== null)) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ 'openid.identity is present without openid.claimed_id');
+ }
+
+ if (($to_match->claimed_id !== null) &&
+ ($to_match->local_id === null)) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ 'openid.claimed_id is present without openid.identity');
+ }
+
+ if ($to_match->claimed_id === null) {
+ // This is a response without identifiers, so there's
+ // really no checking that we can do, so return an
+ // endpoint that's for the specified `openid.op_endpoint'
+ return Auth_OpenID_ServiceEndpoint::fromOPEndpointURL(
+ $to_match->server_url);
+ }
+
+ if (!$endpoint) {
+ // The claimed ID doesn't match, so we have to do
+ // discovery again. This covers not using sessions, OP
+ // identifier endpoints and responses that didn't match
+ // the original request.
+ // oidutil.log('No pre-discovered information supplied.')
+ return $this->_discoverAndVerify($to_match->claimed_id,
+ array($to_match));
+ } else {
+
+ // The claimed ID matches, so we use the endpoint that we
+ // discovered in initiation. This should be the most
+ // common case.
+ $result = $this->_verifyDiscoverySingle($endpoint, $to_match);
+
+ if (Auth_OpenID::isFailure($result)) {
+ $endpoint = $this->_discoverAndVerify($to_match->claimed_id,
+ array($to_match));
+ if (Auth_OpenID::isFailure($endpoint)) {
+ return $endpoint;
+ }
+ }
+ }
+
+ // The endpoint we return should have the claimed ID from the
+ // message we just verified, fragment and all.
+ if ($endpoint->claimed_id != $to_match->claimed_id) {
+ $endpoint->claimed_id = $to_match->claimed_id;
+ }
+
+ return $endpoint;
+ }
+
+ /**
+ * @access private
+ */
+ function _discoverAndVerify($claimed_id, $to_match_endpoints)
+ {
+ // oidutil.log('Performing discovery on %s' % (claimed_id,))
+ list($unused, $services) = call_user_func_array($this->discoverMethod,
+ array(
+ $claimed_id,
+ &$this->fetcher,
+ ));
+
+ if (!$services) {
+ return new Auth_OpenID_FailureResponse(null,
+ sprintf("No OpenID information found at %s",
+ $claimed_id));
+ }
+
+ return $this->_verifyDiscoveryServices($claimed_id, $services,
+ $to_match_endpoints);
+ }
+
+ /**
+ * @access private
+ */
+ function _verifyDiscoveryServices($claimed_id,
+ $services, $to_match_endpoints)
+ {
+ // Search the services resulting from discovery to find one
+ // that matches the information from the assertion
+
+ foreach ($services as $endpoint) {
+ foreach ($to_match_endpoints as $to_match_endpoint) {
+ $result = $this->_verifyDiscoverySingle($endpoint,
+ $to_match_endpoint);
+
+ if (!Auth_OpenID::isFailure($result)) {
+ // It matches, so discover verification has
+ // succeeded. Return this endpoint.
+ return $endpoint;
+ }
+ }
+ }
+
+ return new Auth_OpenID_FailureResponse(null,
+ sprintf('No matching endpoint found after discovering %s: %s',
+ $claimed_id, $result->message));
+ }
+
+ /**
+ * Extract the nonce from an OpenID 1 response. Return the nonce
+ * from the BARE_NS since we independently check the return_to
+ * arguments are the same as those in the response message.
+ *
+ * See the openid1_nonce_query_arg_name class variable
+ *
+ * @returns $nonce The nonce as a string or null
+ *
+ * @access private
+ */
+ function _idResGetNonceOpenID1($message, $endpoint)
+ {
+ return $message->getArg(Auth_OpenID_BARE_NS,
+ $this->openid1_nonce_query_arg_name);
+ }
+
+ /**
+ * @access private
+ */
+ function _idResCheckNonce($message, $endpoint)
+ {
+ if ($message->isOpenID1()) {
+ // This indicates that the nonce was generated by the consumer
+ $nonce = $this->_idResGetNonceOpenID1($message, $endpoint);
+ $server_url = '';
+ } else {
+ $nonce = $message->getArg(Auth_OpenID_OPENID2_NS,
+ 'response_nonce');
+
+ $server_url = $endpoint->server_url;
+ }
+
+ if ($nonce === null) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ "Nonce missing from response");
+ }
+
+ $parts = Auth_OpenID_splitNonce($nonce);
+
+ if ($parts === null) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ "Malformed nonce in response");
+ }
+
+ list($timestamp, $salt) = $parts;
+
+ if (!$this->store->useNonce($server_url, $timestamp, $salt)) {
+ return new Auth_OpenID_FailureResponse($endpoint,
+ "Nonce already used or out of range");
+ }
+
+ return null;
+ }
+
+ /**
+ * @access private
+ */
+ function _idResCheckForFields($message)
+ {
+ $basic_fields = array('return_to', 'assoc_handle', 'sig', 'signed');
+ $basic_sig_fields = array('return_to', 'identity');
+
+ $require_fields = array(
+ Auth_OpenID_OPENID2_NS => array_merge($basic_fields,
+ array('op_endpoint')),
+
+ Auth_OpenID_OPENID1_NS => array_merge($basic_fields,
+ array('identity'))
+ );
+
+ $require_sigs = array(
+ Auth_OpenID_OPENID2_NS => array_merge($basic_sig_fields,
+ array('response_nonce',
+ 'claimed_id',
+ 'assoc_handle',
+ 'op_endpoint')),
+ Auth_OpenID_OPENID1_NS => array_merge($basic_sig_fields,
+ array('nonce'))
+ );
+
+ foreach ($require_fields[$message->getOpenIDNamespace()] as $field) {
+ if (!$message->hasKey(Auth_OpenID_OPENID_NS, $field)) {
+ return new Auth_OpenID_FailureResponse(null,
+ "Missing required field '".$field."'");
+ }
+ }
+
+ $signed_list_str = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'signed',
+ Auth_OpenID_NO_DEFAULT);
+ if (Auth_OpenID::isFailure($signed_list_str)) {
+ return $signed_list_str;
+ }
+ $signed_list = explode(',', $signed_list_str);
+
+ foreach ($require_sigs[$message->getOpenIDNamespace()] as $field) {
+ // Field is present and not in signed list
+ if ($message->hasKey(Auth_OpenID_OPENID_NS, $field) &&
+ (!in_array($field, $signed_list))) {
+ return new Auth_OpenID_FailureResponse(null,
+ "'".$field."' not signed");
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @access private
+ */
+ function _checkAuth($message, $server_url)
+ {
+ $request = $this->_createCheckAuthRequest($message);
+ if ($request === null) {
+ return false;
+ }
+
+ $resp_message = $this->_makeKVPost($request, $server_url);
+ if (($resp_message === null) ||
+ (is_a($resp_message, 'Auth_OpenID_ServerErrorContainer'))) {
+ return false;
+ }
+
+ return $this->_processCheckAuthResponse($resp_message, $server_url);
+ }
+
+ /**
+ * @access private
+ */
+ function _createCheckAuthRequest($message)
+ {
+ $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
+ if ($signed) {
+ foreach (explode(',', $signed) as $k) {
+ $value = $message->getAliasedArg($k);
+ if ($value === null) {
+ return null;
+ }
+ }
+ }
+ $ca_message = $message->copy();
+ $ca_message->setArg(Auth_OpenID_OPENID_NS, 'mode',
+ 'check_authentication');
+ return $ca_message;
+ }
+
+ /**
+ * @access private
+ */
+ function _processCheckAuthResponse($response, $server_url)
+ {
+ $is_valid = $response->getArg(Auth_OpenID_OPENID_NS, 'is_valid',
+ 'false');
+
+ $invalidate_handle = $response->getArg(Auth_OpenID_OPENID_NS,
+ 'invalidate_handle');
+
+ if ($invalidate_handle !== null) {
+ $this->store->removeAssociation($server_url,
+ $invalidate_handle);
+ }
+
+ if ($is_valid == 'true') {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Adapt a POST response to a Message.
+ *
+ * @param $response Result of a POST to an OpenID endpoint.
+ *
+ * @access private
+ */
+ static function _httpResponseToMessage($response, $server_url)
+ {
+ // Should this function be named Message.fromHTTPResponse instead?
+ $response_message = Auth_OpenID_Message::fromKVForm($response->body);
+
+ if ($response->status == 400) {
+ return Auth_OpenID_ServerErrorContainer::fromMessage(
+ $response_message);
+ } else if ($response->status != 200 and $response->status != 206) {
+ return null;
+ }
+
+ return $response_message;
+ }
+
+ /**
+ * @access private
+ */
+ function _makeKVPost($message, $server_url)
+ {
+ $body = $message->toURLEncoded();
+ $resp = $this->fetcher->post($server_url, $body);
+
+ if ($resp === null) {
+ return null;
+ }
+
+ return $this->_httpResponseToMessage($resp, $server_url);
+ }
+
+ /**
+ * @access private
+ */
+ function _getAssociation($endpoint)
+ {
+ if (!$this->_use_assocs) {
+ return null;
+ }
+
+ $assoc = $this->store->getAssociation($endpoint->server_url);
+
+ if (($assoc === null) ||
+ ($assoc->getExpiresIn() <= 0)) {
+
+ $assoc = $this->_negotiateAssociation($endpoint);
+
+ if ($assoc !== null) {
+ $this->store->storeAssociation($endpoint->server_url,
+ $assoc);
+ }
+ }
+
+ return $assoc;
+ }
+
+ /**
+ * Handle ServerErrors resulting from association requests.
+ *
+ * @return $result If server replied with an C{unsupported-type}
+ * error, return a tuple of supported C{association_type},
+ * C{session_type}. Otherwise logs the error and returns null.
+ *
+ * @access private
+ */
+ function _extractSupportedAssociationType($server_error, $endpoint,
+ $assoc_type)
+ {
+ // Any error message whose code is not 'unsupported-type'
+ // should be considered a total failure.
+ if (($server_error->error_code != 'unsupported-type') ||
+ ($server_error->message->isOpenID1())) {
+ return null;
+ }
+
+ // The server didn't like the association/session type that we
+ // sent, and it sent us back a message that might tell us how
+ // to handle it.
+
+ // Extract the session_type and assoc_type from the error
+ // message
+ $assoc_type = $server_error->message->getArg(Auth_OpenID_OPENID_NS,
+ 'assoc_type');
+
+ $session_type = $server_error->message->getArg(Auth_OpenID_OPENID_NS,
+ 'session_type');
+
+ if (($assoc_type === null) || ($session_type === null)) {
+ return null;
+ } else if (!$this->negotiator->isAllowed($assoc_type,
+ $session_type)) {
+ return null;
+ } else {
+ return array($assoc_type, $session_type);
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _negotiateAssociation($endpoint)
+ {
+ // Get our preferred session/association type from the negotiatior.
+ list($assoc_type, $session_type) = $this->negotiator->getAllowedType();
+
+ $assoc = $this->_requestAssociation(
+ $endpoint, $assoc_type, $session_type);
+
+ if (Auth_OpenID::isFailure($assoc)) {
+ return null;
+ }
+
+ if (is_a($assoc, 'Auth_OpenID_ServerErrorContainer')) {
+ $why = $assoc;
+
+ $supportedTypes = $this->_extractSupportedAssociationType(
+ $why, $endpoint, $assoc_type);
+
+ if ($supportedTypes !== null) {
+ list($assoc_type, $session_type) = $supportedTypes;
+
+ // Attempt to create an association from the assoc_type
+ // and session_type that the server told us it
+ // supported.
+ $assoc = $this->_requestAssociation(
+ $endpoint, $assoc_type, $session_type);
+
+ if (is_a($assoc, 'Auth_OpenID_ServerErrorContainer')) {
+ // Do not keep trying, since it rejected the
+ // association type that it told us to use.
+ // oidutil.log('Server %s refused its suggested association
+ // 'type: session_type=%s, assoc_type=%s'
+ // % (endpoint.server_url, session_type,
+ // assoc_type))
+ return null;
+ } else {
+ return $assoc;
+ }
+ } else {
+ return null;
+ }
+ } else {
+ return $assoc;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _requestAssociation($endpoint, $assoc_type, $session_type)
+ {
+ list($assoc_session, $args) = $this->_createAssociateRequest(
+ $endpoint, $assoc_type, $session_type);
+
+ $response_message = $this->_makeKVPost($args, $endpoint->server_url);
+
+ if ($response_message === null) {
+ // oidutil.log('openid.associate request failed: %s' % (why[0],))
+ return null;
+ } else if (is_a($response_message,
+ 'Auth_OpenID_ServerErrorContainer')) {
+ return $response_message;
+ }
+
+ return $this->_extractAssociation($response_message, $assoc_session);
+ }
+
+ /**
+ * @access private
+ */
+ function _extractAssociation($assoc_response, $assoc_session)
+ {
+ // Extract the common fields from the response, raising an
+ // exception if they are not found
+ $assoc_type = $assoc_response->getArg(
+ Auth_OpenID_OPENID_NS, 'assoc_type',
+ Auth_OpenID_NO_DEFAULT);
+
+ if (Auth_OpenID::isFailure($assoc_type)) {
+ return $assoc_type;
+ }
+
+ $assoc_handle = $assoc_response->getArg(
+ Auth_OpenID_OPENID_NS, 'assoc_handle',
+ Auth_OpenID_NO_DEFAULT);
+
+ if (Auth_OpenID::isFailure($assoc_handle)) {
+ return $assoc_handle;
+ }
+
+ // expires_in is a base-10 string. The Python parsing will
+ // accept literals that have whitespace around them and will
+ // accept negative values. Neither of these are really in-spec,
+ // but we think it's OK to accept them.
+ $expires_in_str = $assoc_response->getArg(
+ Auth_OpenID_OPENID_NS, 'expires_in',
+ Auth_OpenID_NO_DEFAULT);
+
+ if (Auth_OpenID::isFailure($expires_in_str)) {
+ return $expires_in_str;
+ }
+
+ $expires_in = Auth_OpenID::intval($expires_in_str);
+ if ($expires_in === false) {
+
+ $err = sprintf("Could not parse expires_in from association ".
+ "response %s", print_r($assoc_response, true));
+ return new Auth_OpenID_FailureResponse(null, $err);
+ }
+
+ // OpenID 1 has funny association session behaviour.
+ if ($assoc_response->isOpenID1()) {
+ $session_type = $this->_getOpenID1SessionType($assoc_response);
+ } else {
+ $session_type = $assoc_response->getArg(
+ Auth_OpenID_OPENID2_NS, 'session_type',
+ Auth_OpenID_NO_DEFAULT);
+
+ if (Auth_OpenID::isFailure($session_type)) {
+ return $session_type;
+ }
+ }
+
+ // Session type mismatch
+ if ($assoc_session->session_type != $session_type) {
+ if ($assoc_response->isOpenID1() &&
+ ($session_type == 'no-encryption')) {
+ // In OpenID 1, any association request can result in
+ // a 'no-encryption' association response. Setting
+ // assoc_session to a new no-encryption session should
+ // make the rest of this function work properly for
+ // that case.
+ $assoc_session = new Auth_OpenID_PlainTextConsumerSession();
+ } else {
+ // Any other mismatch, regardless of protocol version
+ // results in the failure of the association session
+ // altogether.
+ return null;
+ }
+ }
+
+ // Make sure assoc_type is valid for session_type
+ if (!in_array($assoc_type, $assoc_session->allowed_assoc_types)) {
+ return null;
+ }
+
+ // Delegate to the association session to extract the secret
+ // from the response, however is appropriate for that session
+ // type.
+ $secret = $assoc_session->extractSecret($assoc_response);
+
+ if ($secret === null) {
+ return null;
+ }
+
+ return Auth_OpenID_Association::fromExpiresIn(
+ $expires_in, $assoc_handle, $secret, $assoc_type);
+ }
+
+ /**
+ * @access private
+ */
+ function _createAssociateRequest($endpoint, $assoc_type, $session_type)
+ {
+ if (array_key_exists($session_type, $this->session_types)) {
+ $session_type_class = $this->session_types[$session_type];
+
+ if (is_callable($session_type_class)) {
+ $assoc_session = $session_type_class();
+ } else {
+ $assoc_session = new $session_type_class();
+ }
+ } else {
+ return null;
+ }
+
+ $args = array(
+ 'mode' => 'associate',
+ 'assoc_type' => $assoc_type);
+
+ if (!$endpoint->compatibilityMode()) {
+ $args['ns'] = Auth_OpenID_OPENID2_NS;
+ }
+
+ // Leave out the session type if we're in compatibility mode
+ // *and* it's no-encryption.
+ if ((!$endpoint->compatibilityMode()) ||
+ ($assoc_session->session_type != 'no-encryption')) {
+ $args['session_type'] = $assoc_session->session_type;
+ }
+
+ $args = array_merge($args, $assoc_session->getRequest());
+ $message = Auth_OpenID_Message::fromOpenIDArgs($args);
+ return array($assoc_session, $message);
+ }
+
+ /**
+ * Given an association response message, extract the OpenID 1.X
+ * session type.
+ *
+ * This function mostly takes care of the 'no-encryption' default
+ * behavior in OpenID 1.
+ *
+ * If the association type is plain-text, this function will
+ * return 'no-encryption'
+ *
+ * @access private
+ * @return $typ The association type for this message
+ */
+ function _getOpenID1SessionType($assoc_response)
+ {
+ // If it's an OpenID 1 message, allow session_type to default
+ // to None (which signifies "no-encryption")
+ $session_type = $assoc_response->getArg(Auth_OpenID_OPENID1_NS,
+ 'session_type');
+
+ // Handle the differences between no-encryption association
+ // respones in OpenID 1 and 2:
+
+ // no-encryption is not really a valid session type for OpenID
+ // 1, but we'll accept it anyway, while issuing a warning.
+ if ($session_type == 'no-encryption') {
+ // oidutil.log('WARNING: OpenID server sent "no-encryption"'
+ // 'for OpenID 1.X')
+ } else if (($session_type == '') || ($session_type === null)) {
+ // Missing or empty session type is the way to flag a
+ // 'no-encryption' response. Change the session type to
+ // 'no-encryption' so that it can be handled in the same
+ // way as OpenID 2 'no-encryption' respones.
+ $session_type = 'no-encryption';
+ }
+
+ return $session_type;
+ }
+}
+
+/**
+ * This class represents an authentication request from a consumer to
+ * an OpenID server.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AuthRequest {
+
+ /**
+ * Initialize an authentication request with the specified token,
+ * association, and endpoint.
+ *
+ * Users of this library should not create instances of this
+ * class. Instances of this class are created by the library when
+ * needed.
+ */
+ function Auth_OpenID_AuthRequest($endpoint, $assoc)
+ {
+ $this->assoc = $assoc;
+ $this->endpoint = $endpoint;
+ $this->return_to_args = array();
+ $this->message = new Auth_OpenID_Message(
+ $endpoint->preferredNamespace());
+ $this->_anonymous = false;
+ }
+
+ /**
+ * Add an extension to this checkid request.
+ *
+ * $extension_request: An object that implements the extension
+ * request interface for adding arguments to an OpenID message.
+ */
+ function addExtension($extension_request)
+ {
+ $extension_request->toMessage($this->message);
+ }
+
+ /**
+ * Add an extension argument to this OpenID authentication
+ * request.
+ *
+ * Use caution when adding arguments, because they will be
+ * URL-escaped and appended to the redirect URL, which can easily
+ * get quite long.
+ *
+ * @param string $namespace The namespace for the extension. For
+ * example, the simple registration extension uses the namespace
+ * 'sreg'.
+ *
+ * @param string $key The key within the extension namespace. For
+ * example, the nickname field in the simple registration
+ * extension's key is 'nickname'.
+ *
+ * @param string $value The value to provide to the server for
+ * this argument.
+ */
+ function addExtensionArg($namespace, $key, $value)
+ {
+ return $this->message->setArg($namespace, $key, $value);
+ }
+
+ /**
+ * Set whether this request should be made anonymously. If a
+ * request is anonymous, the identifier will not be sent in the
+ * request. This is only useful if you are making another kind of
+ * request with an extension in this request.
+ *
+ * Anonymous requests are not allowed when the request is made
+ * with OpenID 1.
+ */
+ function setAnonymous($is_anonymous)
+ {
+ if ($is_anonymous && $this->message->isOpenID1()) {
+ return false;
+ } else {
+ $this->_anonymous = $is_anonymous;
+ return true;
+ }
+ }
+
+ /**
+ * Produce a {@link Auth_OpenID_Message} representing this
+ * request.
+ *
+ * @param string $realm The URL (or URL pattern) that identifies
+ * your web site to the user when she is authorizing it.
+ *
+ * @param string $return_to The URL that the OpenID provider will
+ * send the user back to after attempting to verify her identity.
+ *
+ * Not specifying a return_to URL means that the user will not be
+ * returned to the site issuing the request upon its completion.
+ *
+ * @param bool $immediate If true, the OpenID provider is to send
+ * back a response immediately, useful for behind-the-scenes
+ * authentication attempts. Otherwise the OpenID provider may
+ * engage the user before providing a response. This is the
+ * default case, as the user may need to provide credentials or
+ * approve the request before a positive response can be sent.
+ */
+ function getMessage($realm, $return_to=null, $immediate=false)
+ {
+ if ($return_to) {
+ $return_to = Auth_OpenID::appendArgs($return_to,
+ $this->return_to_args);
+ } else if ($immediate) {
+ // raise ValueError(
+ // '"return_to" is mandatory when
+ //using "checkid_immediate"')
+ return new Auth_OpenID_FailureResponse(null,
+ "'return_to' is mandatory when using checkid_immediate");
+ } else if ($this->message->isOpenID1()) {
+ // raise ValueError('"return_to" is
+ // mandatory for OpenID 1 requests')
+ return new Auth_OpenID_FailureResponse(null,
+ "'return_to' is mandatory for OpenID 1 requests");
+ } else if ($this->return_to_args) {
+ // raise ValueError('extra "return_to" arguments
+ // were specified, but no return_to was specified')
+ return new Auth_OpenID_FailureResponse(null,
+ "extra 'return_to' arguments where specified, " .
+ "but no return_to was specified");
+ }
+
+ if ($immediate) {
+ $mode = 'checkid_immediate';
+ } else {
+ $mode = 'checkid_setup';
+ }
+
+ $message = $this->message->copy();
+ if ($message->isOpenID1()) {
+ $realm_key = 'trust_root';
+ } else {
+ $realm_key = 'realm';
+ }
+
+ $message->updateArgs(Auth_OpenID_OPENID_NS,
+ array(
+ $realm_key => $realm,
+ 'mode' => $mode,
+ 'return_to' => $return_to));
+
+ if (!$this->_anonymous) {
+ if ($this->endpoint->isOPIdentifier()) {
+ // This will never happen when we're in compatibility
+ // mode, as long as isOPIdentifier() returns False
+ // whenever preferredNamespace() returns OPENID1_NS.
+ $claimed_id = $request_identity =
+ Auth_OpenID_IDENTIFIER_SELECT;
+ } else {
+ $request_identity = $this->endpoint->getLocalID();
+ $claimed_id = $this->endpoint->claimed_id;
+ }
+
+ // This is true for both OpenID 1 and 2
+ $message->setArg(Auth_OpenID_OPENID_NS, 'identity',
+ $request_identity);
+
+ if ($message->isOpenID2()) {
+ $message->setArg(Auth_OpenID_OPENID2_NS, 'claimed_id',
+ $claimed_id);
+ }
+ }
+
+ if ($this->assoc) {
+ $message->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle',
+ $this->assoc->handle);
+ }
+
+ return $message;
+ }
+
+ function redirectURL($realm, $return_to = null,
+ $immediate = false)
+ {
+ $message = $this->getMessage($realm, $return_to, $immediate);
+
+ if (Auth_OpenID::isFailure($message)) {
+ return $message;
+ }
+
+ return $message->toURL($this->endpoint->server_url);
+ }
+
+ /**
+ * Get html for a form to submit this request to the IDP.
+ *
+ * form_tag_attrs: An array of attributes to be added to the form
+ * tag. 'accept-charset' and 'enctype' have defaults that can be
+ * overridden. If a value is supplied for 'action' or 'method', it
+ * will be replaced.
+ */
+ function formMarkup($realm, $return_to=null, $immediate=false,
+ $form_tag_attrs=null)
+ {
+ $message = $this->getMessage($realm, $return_to, $immediate);
+
+ if (Auth_OpenID::isFailure($message)) {
+ return $message;
+ }
+
+ return $message->toFormMarkup($this->endpoint->server_url,
+ $form_tag_attrs);
+ }
+
+ /**
+ * Get a complete html document that will autosubmit the request
+ * to the IDP.
+ *
+ * Wraps formMarkup. See the documentation for that function.
+ */
+ function htmlMarkup($realm, $return_to=null, $immediate=false,
+ $form_tag_attrs=null)
+ {
+ $form = $this->formMarkup($realm, $return_to, $immediate,
+ $form_tag_attrs);
+
+ if (Auth_OpenID::isFailure($form)) {
+ return $form;
+ }
+ return Auth_OpenID::autoSubmitHTML($form);
+ }
+
+ function shouldSendRedirect()
+ {
+ return $this->endpoint->compatibilityMode();
+ }
+}
+
+/**
+ * The base class for responses from the Auth_OpenID_Consumer.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_ConsumerResponse {
+ var $status = null;
+
+ function setEndpoint($endpoint)
+ {
+ $this->endpoint = $endpoint;
+ if ($endpoint === null) {
+ $this->identity_url = null;
+ } else {
+ $this->identity_url = $endpoint->claimed_id;
+ }
+ }
+
+ /**
+ * Return the display identifier for this response.
+ *
+ * The display identifier is related to the Claimed Identifier, but the
+ * two are not always identical. The display identifier is something the
+ * user should recognize as what they entered, whereas the response's
+ * claimed identifier (in the identity_url attribute) may have extra
+ * information for better persistence.
+ *
+ * URLs will be stripped of their fragments for display. XRIs will
+ * display the human-readable identifier (i-name) instead of the
+ * persistent identifier (i-number).
+ *
+ * Use the display identifier in your user interface. Use
+ * identity_url for querying your database or authorization server.
+ *
+ */
+ function getDisplayIdentifier()
+ {
+ if ($this->endpoint !== null) {
+ return $this->endpoint->getDisplayIdentifier();
+ }
+ return null;
+ }
+}
+
+/**
+ * A response with a status of Auth_OpenID_SUCCESS. Indicates that
+ * this request is a successful acknowledgement from the OpenID server
+ * that the supplied URL is, indeed controlled by the requesting
+ * agent. This has three relevant attributes:
+ *
+ * claimed_id - The identity URL that has been authenticated
+ *
+ * signed_args - The arguments in the server's response that were
+ * signed and verified.
+ *
+ * status - Auth_OpenID_SUCCESS.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SuccessResponse extends Auth_OpenID_ConsumerResponse {
+ var $status = Auth_OpenID_SUCCESS;
+
+ /**
+ * @access private
+ */
+ function Auth_OpenID_SuccessResponse($endpoint, $message, $signed_args=null)
+ {
+ $this->endpoint = $endpoint;
+ $this->identity_url = $endpoint->claimed_id;
+ $this->signed_args = $signed_args;
+ $this->message = $message;
+
+ if ($this->signed_args === null) {
+ $this->signed_args = array();
+ }
+ }
+
+ /**
+ * Extract signed extension data from the server's response.
+ *
+ * @param string $prefix The extension namespace from which to
+ * extract the extension data.
+ */
+ function extensionResponse($namespace_uri, $require_signed)
+ {
+ if ($require_signed) {
+ return $this->getSignedNS($namespace_uri);
+ } else {
+ return $this->message->getArgs($namespace_uri);
+ }
+ }
+
+ function isOpenID1()
+ {
+ return $this->message->isOpenID1();
+ }
+
+ function isSigned($ns_uri, $ns_key)
+ {
+ // Return whether a particular key is signed, regardless of
+ // its namespace alias
+ return in_array($this->message->getKey($ns_uri, $ns_key),
+ $this->signed_args);
+ }
+
+ function getSigned($ns_uri, $ns_key, $default = null)
+ {
+ // Return the specified signed field if available, otherwise
+ // return default
+ if ($this->isSigned($ns_uri, $ns_key)) {
+ return $this->message->getArg($ns_uri, $ns_key, $default);
+ } else {
+ return $default;
+ }
+ }
+
+ function getSignedNS($ns_uri)
+ {
+ $args = array();
+
+ $msg_args = $this->message->getArgs($ns_uri);
+ if (Auth_OpenID::isFailure($msg_args)) {
+ return null;
+ }
+
+ foreach ($msg_args as $key => $value) {
+ if (!$this->isSigned($ns_uri, $key)) {
+ unset($msg_args[$key]);
+ }
+ }
+
+ return $msg_args;
+ }
+
+ /**
+ * Get the openid.return_to argument from this response.
+ *
+ * This is useful for verifying that this request was initiated by
+ * this consumer.
+ *
+ * @return string $return_to The return_to URL supplied to the
+ * server on the initial request, or null if the response did not
+ * contain an 'openid.return_to' argument.
+ */
+ function getReturnTo()
+ {
+ return $this->getSigned(Auth_OpenID_OPENID_NS, 'return_to');
+ }
+}
+
+/**
+ * A response with a status of Auth_OpenID_FAILURE. Indicates that the
+ * OpenID protocol has failed. This could be locally or remotely
+ * triggered. This has three relevant attributes:
+ *
+ * claimed_id - The identity URL for which authentication was
+ * attempted, if it can be determined. Otherwise, null.
+ *
+ * message - A message indicating why the request failed, if one is
+ * supplied. Otherwise, null.
+ *
+ * status - Auth_OpenID_FAILURE.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_FailureResponse extends Auth_OpenID_ConsumerResponse {
+ var $status = Auth_OpenID_FAILURE;
+
+ function Auth_OpenID_FailureResponse($endpoint, $message = null,
+ $contact = null, $reference = null)
+ {
+ $this->setEndpoint($endpoint);
+ $this->message = $message;
+ $this->contact = $contact;
+ $this->reference = $reference;
+ }
+}
+
+/**
+ * A specific, internal failure used to detect type URI mismatch.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_TypeURIMismatch extends Auth_OpenID_FailureResponse {
+}
+
+/**
+ * Exception that is raised when the server returns a 400 response
+ * code to a direct request.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_ServerErrorContainer {
+ function Auth_OpenID_ServerErrorContainer($error_text,
+ $error_code,
+ $message)
+ {
+ $this->error_text = $error_text;
+ $this->error_code = $error_code;
+ $this->message = $message;
+ }
+
+ /**
+ * @access private
+ */
+ static function fromMessage($message)
+ {
+ $error_text = $message->getArg(
+ Auth_OpenID_OPENID_NS, 'error', '<no error message supplied>');
+ $error_code = $message->getArg(Auth_OpenID_OPENID_NS, 'error_code');
+ return new Auth_OpenID_ServerErrorContainer($error_text,
+ $error_code,
+ $message);
+ }
+}
+
+/**
+ * A response with a status of Auth_OpenID_CANCEL. Indicates that the
+ * user cancelled the OpenID authentication request. This has two
+ * relevant attributes:
+ *
+ * claimed_id - The identity URL for which authentication was
+ * attempted, if it can be determined. Otherwise, null.
+ *
+ * status - Auth_OpenID_SUCCESS.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_CancelResponse extends Auth_OpenID_ConsumerResponse {
+ var $status = Auth_OpenID_CANCEL;
+
+ function Auth_OpenID_CancelResponse($endpoint)
+ {
+ $this->setEndpoint($endpoint);
+ }
+}
+
+/**
+ * A response with a status of Auth_OpenID_SETUP_NEEDED. Indicates
+ * that the request was in immediate mode, and the server is unable to
+ * authenticate the user without further interaction.
+ *
+ * claimed_id - The identity URL for which authentication was
+ * attempted.
+ *
+ * setup_url - A URL that can be used to send the user to the server
+ * to set up for authentication. The user should be redirected in to
+ * the setup_url, either in the current window or in a new browser
+ * window. Null in OpenID 2.
+ *
+ * status - Auth_OpenID_SETUP_NEEDED.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SetupNeededResponse extends Auth_OpenID_ConsumerResponse {
+ var $status = Auth_OpenID_SETUP_NEEDED;
+
+ function Auth_OpenID_SetupNeededResponse($endpoint,
+ $setup_url = null)
+ {
+ $this->setEndpoint($endpoint);
+ $this->setup_url = $setup_url;
+ }
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/CryptUtil.php b/plugins/openid/lib/Auth/OpenID/CryptUtil.php
new file mode 100644
index 00000000..3c60cea1
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/CryptUtil.php
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * CryptUtil: A suite of wrapper utility functions for the OpenID
+ * library.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @access private
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+if (!defined('Auth_OpenID_RAND_SOURCE')) {
+ /**
+ * The filename for a source of random bytes. Define this yourself
+ * if you have a different source of randomness.
+ */
+ define('Auth_OpenID_RAND_SOURCE', '/dev/urandom');
+}
+
+class Auth_OpenID_CryptUtil {
+ /**
+ * Get the specified number of random bytes.
+ *
+ * Attempts to use a cryptographically secure (not predictable)
+ * source of randomness if available. If there is no high-entropy
+ * randomness source available, it will fail. As a last resort,
+ * for non-critical systems, define
+ * <code>Auth_OpenID_RAND_SOURCE</code> as <code>null</code>, and
+ * the code will fall back on a pseudo-random number generator.
+ *
+ * @param int $num_bytes The length of the return value
+ * @return string $bytes random bytes
+ */
+ static function getBytes($num_bytes)
+ {
+ static $f = null;
+ $bytes = '';
+ if ($f === null) {
+ if (Auth_OpenID_RAND_SOURCE === null) {
+ $f = false;
+ } else {
+ $f = @fopen(Auth_OpenID_RAND_SOURCE, "r");
+ if ($f === false) {
+ $msg = 'Define Auth_OpenID_RAND_SOURCE as null to ' .
+ ' continue with an insecure random number generator.';
+ trigger_error($msg, E_USER_ERROR);
+ }
+ }
+ }
+ if ($f === false) {
+ // pseudorandom used
+ $bytes = '';
+ for ($i = 0; $i < $num_bytes; $i += 4) {
+ $bytes .= pack('L', mt_rand());
+ }
+ $bytes = substr($bytes, 0, $num_bytes);
+ } else {
+ $bytes = fread($f, $num_bytes);
+ }
+ return $bytes;
+ }
+
+ /**
+ * Produce a string of length random bytes, chosen from chrs. If
+ * $chrs is null, the resulting string may contain any characters.
+ *
+ * @param integer $length The length of the resulting
+ * randomly-generated string
+ * @param string $chrs A string of characters from which to choose
+ * to build the new string
+ * @return string $result A string of randomly-chosen characters
+ * from $chrs
+ */
+ static function randomString($length, $population = null)
+ {
+ if ($population === null) {
+ return Auth_OpenID_CryptUtil::getBytes($length);
+ }
+
+ $popsize = strlen($population);
+
+ if ($popsize > 256) {
+ $msg = 'More than 256 characters supplied to ' . __FUNCTION__;
+ trigger_error($msg, E_USER_ERROR);
+ }
+
+ $duplicate = 256 % $popsize;
+
+ $str = "";
+ for ($i = 0; $i < $length; $i++) {
+ do {
+ $n = ord(Auth_OpenID_CryptUtil::getBytes(1));
+ } while ($n < $duplicate);
+
+ $n %= $popsize;
+ $str .= $population[$n];
+ }
+
+ return $str;
+ }
+
+ static function constEq($s1, $s2)
+ {
+ if (strlen($s1) != strlen($s2)) {
+ return false;
+ }
+
+ $result = true;
+ $length = strlen($s1);
+ for ($i = 0; $i < $length; $i++) {
+ $result &= ($s1[$i] == $s2[$i]);
+ }
+ return $result;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/DatabaseConnection.php b/plugins/openid/lib/Auth/OpenID/DatabaseConnection.php
new file mode 100644
index 00000000..0c7d08f9
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/DatabaseConnection.php
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * The Auth_OpenID_DatabaseConnection class, which is used to emulate
+ * a PEAR database connection.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * An empty base class intended to emulate PEAR connection
+ * functionality in applications that supply their own database
+ * abstraction mechanisms. See {@link Auth_OpenID_SQLStore} for more
+ * information. You should subclass this class if you need to create
+ * an SQL store that needs to access its database using an
+ * application's database abstraction layer instead of a PEAR database
+ * connection. Any subclass of Auth_OpenID_DatabaseConnection MUST
+ * adhere to the interface specified here.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_DatabaseConnection {
+ /**
+ * Sets auto-commit mode on this database connection.
+ *
+ * @param bool $mode True if auto-commit is to be used; false if
+ * not.
+ */
+ function autoCommit($mode)
+ {
+ }
+
+ /**
+ * Run an SQL query with the specified parameters, if any.
+ *
+ * @param string $sql An SQL string with placeholders. The
+ * placeholders are assumed to be specific to the database engine
+ * for this connection.
+ *
+ * @param array $params An array of parameters to insert into the
+ * SQL string using this connection's escaping mechanism.
+ *
+ * @return mixed $result The result of calling this connection's
+ * internal query function. The type of result depends on the
+ * underlying database engine. This method is usually used when
+ * the result of a query is not important, like a DDL query.
+ */
+ function query($sql, $params = array())
+ {
+ }
+
+ /**
+ * Starts a transaction on this connection, if supported.
+ */
+ function begin()
+ {
+ }
+
+ /**
+ * Commits a transaction on this connection, if supported.
+ */
+ function commit()
+ {
+ }
+
+ /**
+ * Performs a rollback on this connection, if supported.
+ */
+ function rollback()
+ {
+ }
+
+ /**
+ * Run an SQL query and return the first column of the first row
+ * of the result set, if any.
+ *
+ * @param string $sql An SQL string with placeholders. The
+ * placeholders are assumed to be specific to the database engine
+ * for this connection.
+ *
+ * @param array $params An array of parameters to insert into the
+ * SQL string using this connection's escaping mechanism.
+ *
+ * @return mixed $result The value of the first column of the
+ * first row of the result set. False if no such result was
+ * found.
+ */
+ function getOne($sql, $params = array())
+ {
+ }
+
+ /**
+ * Run an SQL query and return the first row of the result set, if
+ * any.
+ *
+ * @param string $sql An SQL string with placeholders. The
+ * placeholders are assumed to be specific to the database engine
+ * for this connection.
+ *
+ * @param array $params An array of parameters to insert into the
+ * SQL string using this connection's escaping mechanism.
+ *
+ * @return array $result The first row of the result set, if any,
+ * keyed on column name. False if no such result was found.
+ */
+ function getRow($sql, $params = array())
+ {
+ }
+
+ /**
+ * Run an SQL query with the specified parameters, if any.
+ *
+ * @param string $sql An SQL string with placeholders. The
+ * placeholders are assumed to be specific to the database engine
+ * for this connection.
+ *
+ * @param array $params An array of parameters to insert into the
+ * SQL string using this connection's escaping mechanism.
+ *
+ * @return array $result An array of arrays representing the
+ * result of the query; each array is keyed on column name.
+ */
+ function getAll($sql, $params = array())
+ {
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/DiffieHellman.php b/plugins/openid/lib/Auth/OpenID/DiffieHellman.php
new file mode 100644
index 00000000..3e25b7db
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/DiffieHellman.php
@@ -0,0 +1,113 @@
+<?php
+
+/**
+ * The OpenID library's Diffie-Hellman implementation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @access private
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+require_once 'Auth/OpenID.php';
+require_once 'Auth/OpenID/BigMath.php';
+
+function Auth_OpenID_getDefaultMod()
+{
+ return '155172898181473697471232257763715539915724801'.
+ '966915404479707795314057629378541917580651227423'.
+ '698188993727816152646631438561595825688188889951'.
+ '272158842675419950341258706556549803580104870537'.
+ '681476726513255747040765857479291291572334510643'.
+ '245094715007229621094194349783925984760375594985'.
+ '848253359305585439638443';
+}
+
+function Auth_OpenID_getDefaultGen()
+{
+ return '2';
+}
+
+/**
+ * The Diffie-Hellman key exchange class. This class relies on
+ * {@link Auth_OpenID_MathLibrary} to perform large number operations.
+ *
+ * @access private
+ * @package OpenID
+ */
+class Auth_OpenID_DiffieHellman {
+
+ var $mod;
+ var $gen;
+ var $private;
+ var $lib = null;
+
+ function Auth_OpenID_DiffieHellman($mod = null, $gen = null,
+ $private = null, $lib = null)
+ {
+ if ($lib === null) {
+ $this->lib = Auth_OpenID_getMathLib();
+ } else {
+ $this->lib = $lib;
+ }
+
+ if ($mod === null) {
+ $this->mod = $this->lib->init(Auth_OpenID_getDefaultMod());
+ } else {
+ $this->mod = $mod;
+ }
+
+ if ($gen === null) {
+ $this->gen = $this->lib->init(Auth_OpenID_getDefaultGen());
+ } else {
+ $this->gen = $gen;
+ }
+
+ if ($private === null) {
+ $r = $this->lib->rand($this->mod);
+ $this->private = $this->lib->add($r, 1);
+ } else {
+ $this->private = $private;
+ }
+
+ $this->public = $this->lib->powmod($this->gen, $this->private,
+ $this->mod);
+ }
+
+ function getSharedSecret($composite)
+ {
+ return $this->lib->powmod($composite, $this->private, $this->mod);
+ }
+
+ function getPublicKey()
+ {
+ return $this->public;
+ }
+
+ function usingDefaultValues()
+ {
+ return ($this->mod == Auth_OpenID_getDefaultMod() &&
+ $this->gen == Auth_OpenID_getDefaultGen());
+ }
+
+ function xorSecret($composite, $secret, $hash_func)
+ {
+ $dh_shared = $this->getSharedSecret($composite);
+ $dh_shared_str = $this->lib->longToBinary($dh_shared);
+ $hash_dh_shared = $hash_func($dh_shared_str);
+
+ $xsecret = "";
+ for ($i = 0; $i < Auth_OpenID::bytes($secret); $i++) {
+ $xsecret .= chr(ord($secret[$i]) ^ ord($hash_dh_shared[$i]));
+ }
+
+ return $xsecret;
+ }
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/Discover.php b/plugins/openid/lib/Auth/OpenID/Discover.php
new file mode 100644
index 00000000..7b0c640c
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Discover.php
@@ -0,0 +1,606 @@
+<?php
+
+/**
+ * The OpenID and Yadis discovery implementation for OpenID 1.2.
+ */
+
+require_once "Auth/OpenID.php";
+require_once "Auth/OpenID/Parse.php";
+require_once "Auth/OpenID/Message.php";
+require_once "Auth/Yadis/XRIRes.php";
+require_once "Auth/Yadis/Yadis.php";
+
+// XML namespace value
+define('Auth_OpenID_XMLNS_1_0', 'http://openid.net/xmlns/1.0');
+
+// Yadis service types
+define('Auth_OpenID_TYPE_1_2', 'http://openid.net/signon/1.2');
+define('Auth_OpenID_TYPE_1_1', 'http://openid.net/signon/1.1');
+define('Auth_OpenID_TYPE_1_0', 'http://openid.net/signon/1.0');
+define('Auth_OpenID_TYPE_2_0_IDP', 'http://specs.openid.net/auth/2.0/server');
+define('Auth_OpenID_TYPE_2_0', 'http://specs.openid.net/auth/2.0/signon');
+define('Auth_OpenID_RP_RETURN_TO_URL_TYPE',
+ 'http://specs.openid.net/auth/2.0/return_to');
+
+function Auth_OpenID_getOpenIDTypeURIs()
+{
+ return array(Auth_OpenID_TYPE_2_0_IDP,
+ Auth_OpenID_TYPE_2_0,
+ Auth_OpenID_TYPE_1_2,
+ Auth_OpenID_TYPE_1_1,
+ Auth_OpenID_TYPE_1_0);
+}
+
+function Auth_OpenID_getOpenIDConsumerTypeURIs()
+{
+ return array(Auth_OpenID_RP_RETURN_TO_URL_TYPE);
+}
+
+
+/*
+ * Provides a user-readable interpretation of a type uri.
+ * Useful for error messages.
+ */
+function Auth_OpenID_getOpenIDTypeName($type_uri) {
+ switch ($type_uri) {
+ case Auth_OpenID_TYPE_2_0_IDP:
+ return 'OpenID 2.0 IDP';
+ case Auth_OpenID_TYPE_2_0:
+ return 'OpenID 2.0';
+ case Auth_OpenID_TYPE_1_2:
+ return 'OpenID 1.2';
+ case Auth_OpenID_TYPE_1_1:
+ return 'OpenID 1.1';
+ case Auth_OpenID_TYPE_1_0:
+ return 'OpenID 1.0';
+ case Auth_OpenID_RP_RETURN_TO_URL_TYPE:
+ return 'OpenID relying party';
+ }
+}
+
+/**
+ * Object representing an OpenID service endpoint.
+ */
+class Auth_OpenID_ServiceEndpoint {
+ function Auth_OpenID_ServiceEndpoint()
+ {
+ $this->claimed_id = null;
+ $this->server_url = null;
+ $this->type_uris = array();
+ $this->local_id = null;
+ $this->canonicalID = null;
+ $this->used_yadis = false; // whether this came from an XRDS
+ $this->display_identifier = null;
+ }
+
+ function getDisplayIdentifier()
+ {
+ if ($this->display_identifier) {
+ return $this->display_identifier;
+ }
+ if (! $this->claimed_id) {
+ return $this->claimed_id;
+ }
+ $parsed = parse_url($this->claimed_id);
+ $scheme = $parsed['scheme'];
+ $host = $parsed['host'];
+ $path = $parsed['path'];
+ if (array_key_exists('query', $parsed)) {
+ $query = $parsed['query'];
+ $no_frag = "$scheme://$host$path?$query";
+ } else {
+ $no_frag = "$scheme://$host$path";
+ }
+ return $no_frag;
+ }
+
+ function usesExtension($extension_uri)
+ {
+ return in_array($extension_uri, $this->type_uris);
+ }
+
+ function preferredNamespace()
+ {
+ if (in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris) ||
+ in_array(Auth_OpenID_TYPE_2_0, $this->type_uris)) {
+ return Auth_OpenID_OPENID2_NS;
+ } else {
+ return Auth_OpenID_OPENID1_NS;
+ }
+ }
+
+ /*
+ * Query this endpoint to see if it has any of the given type
+ * URIs. This is useful for implementing other endpoint classes
+ * that e.g. need to check for the presence of multiple versions
+ * of a single protocol.
+ *
+ * @param $type_uris The URIs that you wish to check
+ *
+ * @return all types that are in both in type_uris and
+ * $this->type_uris
+ */
+ function matchTypes($type_uris)
+ {
+ $result = array();
+ foreach ($type_uris as $test_uri) {
+ if ($this->supportsType($test_uri)) {
+ $result[] = $test_uri;
+ }
+ }
+
+ return $result;
+ }
+
+ function supportsType($type_uri)
+ {
+ // Does this endpoint support this type?
+ return ((in_array($type_uri, $this->type_uris)) ||
+ (($type_uri == Auth_OpenID_TYPE_2_0) &&
+ $this->isOPIdentifier()));
+ }
+
+ function compatibilityMode()
+ {
+ return $this->preferredNamespace() != Auth_OpenID_OPENID2_NS;
+ }
+
+ function isOPIdentifier()
+ {
+ return in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris);
+ }
+
+ static function fromOPEndpointURL($op_endpoint_url)
+ {
+ // Construct an OP-Identifier OpenIDServiceEndpoint object for
+ // a given OP Endpoint URL
+ $obj = new Auth_OpenID_ServiceEndpoint();
+ $obj->server_url = $op_endpoint_url;
+ $obj->type_uris = array(Auth_OpenID_TYPE_2_0_IDP);
+ return $obj;
+ }
+
+ function parseService($yadis_url, $uri, $type_uris, $service_element)
+ {
+ // Set the state of this object based on the contents of the
+ // service element. Return true if successful, false if not
+ // (if findOPLocalIdentifier returns false).
+ $this->type_uris = $type_uris;
+ $this->server_url = $uri;
+ $this->used_yadis = true;
+
+ if (!$this->isOPIdentifier()) {
+ $this->claimed_id = $yadis_url;
+ $this->local_id = Auth_OpenID_findOPLocalIdentifier(
+ $service_element,
+ $this->type_uris);
+ if ($this->local_id === false) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function getLocalID()
+ {
+ // Return the identifier that should be sent as the
+ // openid.identity_url parameter to the server.
+ if ($this->local_id === null && $this->canonicalID === null) {
+ return $this->claimed_id;
+ } else {
+ if ($this->local_id) {
+ return $this->local_id;
+ } else {
+ return $this->canonicalID;
+ }
+ }
+ }
+
+ /*
+ * Parse the given document as XRDS looking for OpenID consumer services.
+ *
+ * @return array of Auth_OpenID_ServiceEndpoint or null if the
+ * document cannot be parsed.
+ */
+ function consumerFromXRDS($uri, $xrds_text)
+ {
+ $xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text);
+
+ if ($xrds) {
+ $yadis_services =
+ $xrds->services(array('filter_MatchesAnyOpenIDConsumerType'));
+ return Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services);
+ }
+
+ return null;
+ }
+
+ /*
+ * Parse the given document as XRDS looking for OpenID services.
+ *
+ * @return array of Auth_OpenID_ServiceEndpoint or null if the
+ * document cannot be parsed.
+ */
+ static function fromXRDS($uri, $xrds_text)
+ {
+ $xrds = Auth_Yadis_XRDS::parseXRDS($xrds_text);
+
+ if ($xrds) {
+ $yadis_services =
+ $xrds->services(array('filter_MatchesAnyOpenIDType'));
+ return Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services);
+ }
+
+ return null;
+ }
+
+ /*
+ * Create endpoints from a DiscoveryResult.
+ *
+ * @param discoveryResult Auth_Yadis_DiscoveryResult
+ * @return array of Auth_OpenID_ServiceEndpoint or null if
+ * endpoints cannot be created.
+ */
+ static function fromDiscoveryResult($discoveryResult)
+ {
+ if ($discoveryResult->isXRDS()) {
+ return Auth_OpenID_ServiceEndpoint::fromXRDS(
+ $discoveryResult->normalized_uri,
+ $discoveryResult->response_text);
+ } else {
+ return Auth_OpenID_ServiceEndpoint::fromHTML(
+ $discoveryResult->normalized_uri,
+ $discoveryResult->response_text);
+ }
+ }
+
+ static function fromHTML($uri, $html)
+ {
+ $discovery_types = array(
+ array(Auth_OpenID_TYPE_2_0,
+ 'openid2.provider', 'openid2.local_id'),
+ array(Auth_OpenID_TYPE_1_1,
+ 'openid.server', 'openid.delegate')
+ );
+
+ $services = array();
+
+ foreach ($discovery_types as $triple) {
+ list($type_uri, $server_rel, $delegate_rel) = $triple;
+
+ $urls = Auth_OpenID_legacy_discover($html, $server_rel,
+ $delegate_rel);
+
+ if ($urls === false) {
+ continue;
+ }
+
+ list($delegate_url, $server_url) = $urls;
+
+ $service = new Auth_OpenID_ServiceEndpoint();
+ $service->claimed_id = $uri;
+ $service->local_id = $delegate_url;
+ $service->server_url = $server_url;
+ $service->type_uris = array($type_uri);
+
+ $services[] = $service;
+ }
+
+ return $services;
+ }
+
+ function copy()
+ {
+ $x = new Auth_OpenID_ServiceEndpoint();
+
+ $x->claimed_id = $this->claimed_id;
+ $x->server_url = $this->server_url;
+ $x->type_uris = $this->type_uris;
+ $x->local_id = $this->local_id;
+ $x->canonicalID = $this->canonicalID;
+ $x->used_yadis = $this->used_yadis;
+
+ return $x;
+ }
+}
+
+function Auth_OpenID_findOPLocalIdentifier($service, $type_uris)
+{
+ // Extract a openid:Delegate value from a Yadis Service element.
+ // If no delegate is found, returns null. Returns false on
+ // discovery failure (when multiple delegate/localID tags have
+ // different values).
+
+ $service->parser->registerNamespace('openid',
+ Auth_OpenID_XMLNS_1_0);
+
+ $service->parser->registerNamespace('xrd',
+ Auth_Yadis_XMLNS_XRD_2_0);
+
+ $parser = $service->parser;
+
+ $permitted_tags = array();
+
+ if (in_array(Auth_OpenID_TYPE_1_1, $type_uris) ||
+ in_array(Auth_OpenID_TYPE_1_0, $type_uris)) {
+ $permitted_tags[] = 'openid:Delegate';
+ }
+
+ if (in_array(Auth_OpenID_TYPE_2_0, $type_uris)) {
+ $permitted_tags[] = 'xrd:LocalID';
+ }
+
+ $local_id = null;
+
+ foreach ($permitted_tags as $tag_name) {
+ $tags = $service->getElements($tag_name);
+
+ foreach ($tags as $tag) {
+ $content = $parser->content($tag);
+
+ if ($local_id === null) {
+ $local_id = $content;
+ } else if ($local_id != $content) {
+ return false;
+ }
+ }
+ }
+
+ return $local_id;
+}
+
+function filter_MatchesAnyOpenIDType($service)
+{
+ $uris = $service->getTypes();
+
+ foreach ($uris as $uri) {
+ if (in_array($uri, Auth_OpenID_getOpenIDTypeURIs())) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function filter_MatchesAnyOpenIDConsumerType(&$service)
+{
+ $uris = $service->getTypes();
+
+ foreach ($uris as $uri) {
+ if (in_array($uri, Auth_OpenID_getOpenIDConsumerTypeURIs())) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function Auth_OpenID_bestMatchingService($service, $preferred_types)
+{
+ // Return the index of the first matching type, or something
+ // higher if no type matches.
+ //
+ // This provides an ordering in which service elements that
+ // contain a type that comes earlier in the preferred types list
+ // come before service elements that come later. If a service
+ // element has more than one type, the most preferred one wins.
+
+ foreach ($preferred_types as $index => $typ) {
+ if (in_array($typ, $service->type_uris)) {
+ return $index;
+ }
+ }
+
+ return count($preferred_types);
+}
+
+function Auth_OpenID_arrangeByType($service_list, $preferred_types)
+{
+ // Rearrange service_list in a new list so services are ordered by
+ // types listed in preferred_types. Return the new list.
+
+ // Build a list with the service elements in tuples whose
+ // comparison will prefer the one with the best matching service
+ $prio_services = array();
+ foreach ($service_list as $index => $service) {
+ $prio_services[] = array(Auth_OpenID_bestMatchingService($service,
+ $preferred_types),
+ $index, $service);
+ }
+
+ sort($prio_services);
+
+ // Now that the services are sorted by priority, remove the sort
+ // keys from the list.
+ foreach ($prio_services as $index => $s) {
+ $prio_services[$index] = $prio_services[$index][2];
+ }
+
+ return $prio_services;
+}
+
+// Extract OP Identifier services. If none found, return the rest,
+// sorted with most preferred first according to
+// OpenIDServiceEndpoint.openid_type_uris.
+//
+// openid_services is a list of OpenIDServiceEndpoint objects.
+//
+// Returns a list of OpenIDServiceEndpoint objects."""
+function Auth_OpenID_getOPOrUserServices($openid_services)
+{
+ $op_services = Auth_OpenID_arrangeByType($openid_services,
+ array(Auth_OpenID_TYPE_2_0_IDP));
+
+ $openid_services = Auth_OpenID_arrangeByType($openid_services,
+ Auth_OpenID_getOpenIDTypeURIs());
+
+ if ($op_services) {
+ return $op_services;
+ } else {
+ return $openid_services;
+ }
+}
+
+function Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services)
+{
+ $s = array();
+
+ if (!$yadis_services) {
+ return $s;
+ }
+
+ foreach ($yadis_services as $service) {
+ $type_uris = $service->getTypes();
+ $uris = $service->getURIs();
+
+ // If any Type URIs match and there is an endpoint URI
+ // specified, then this is an OpenID endpoint
+ if ($type_uris &&
+ $uris) {
+ foreach ($uris as $service_uri) {
+ $openid_endpoint = new Auth_OpenID_ServiceEndpoint();
+ if ($openid_endpoint->parseService($uri,
+ $service_uri,
+ $type_uris,
+ $service)) {
+ $s[] = $openid_endpoint;
+ }
+ }
+ }
+ }
+
+ return $s;
+}
+
+function Auth_OpenID_discoverWithYadis($uri, $fetcher,
+ $endpoint_filter='Auth_OpenID_getOPOrUserServices',
+ $discover_function=null)
+{
+ // Discover OpenID services for a URI. Tries Yadis and falls back
+ // on old-style <link rel='...'> discovery if Yadis fails.
+
+ // Might raise a yadis.discover.DiscoveryFailure if no document
+ // came back for that URI at all. I don't think falling back to
+ // OpenID 1.0 discovery on the same URL will help, so don't bother
+ // to catch it.
+ if ($discover_function === null) {
+ $discover_function = array('Auth_Yadis_Yadis', 'discover');
+ }
+
+ $openid_services = array();
+
+ $response = call_user_func_array($discover_function,
+ array($uri, $fetcher));
+
+ $yadis_url = $response->normalized_uri;
+ $yadis_services = array();
+
+ if ($response->isFailure() && !$response->isXRDS()) {
+ return array($uri, array());
+ }
+
+ $openid_services = Auth_OpenID_ServiceEndpoint::fromXRDS(
+ $yadis_url,
+ $response->response_text);
+
+ if (!$openid_services) {
+ if ($response->isXRDS()) {
+ return Auth_OpenID_discoverWithoutYadis($uri,
+ $fetcher);
+ }
+
+ // Try to parse the response as HTML to get OpenID 1.0/1.1
+ // <link rel="...">
+ $openid_services = Auth_OpenID_ServiceEndpoint::fromHTML(
+ $yadis_url,
+ $response->response_text);
+ }
+
+ $openid_services = call_user_func_array($endpoint_filter,
+ array($openid_services));
+
+ return array($yadis_url, $openid_services);
+}
+
+function Auth_OpenID_discoverURI($uri, $fetcher)
+{
+ $uri = Auth_OpenID::normalizeUrl($uri);
+ return Auth_OpenID_discoverWithYadis($uri, $fetcher);
+}
+
+function Auth_OpenID_discoverWithoutYadis($uri, $fetcher)
+{
+ $http_resp = @$fetcher->get($uri);
+
+ if ($http_resp->status != 200 and $http_resp->status != 206) {
+ return array($uri, array());
+ }
+
+ $identity_url = $http_resp->final_url;
+
+ // Try to parse the response as HTML to get OpenID 1.0/1.1 <link
+ // rel="...">
+ $openid_services = Auth_OpenID_ServiceEndpoint::fromHTML(
+ $identity_url,
+ $http_resp->body);
+
+ return array($identity_url, $openid_services);
+}
+
+function Auth_OpenID_discoverXRI($iname, $fetcher)
+{
+ $resolver = new Auth_Yadis_ProxyResolver($fetcher);
+ list($canonicalID, $yadis_services) =
+ $resolver->query($iname,
+ Auth_OpenID_getOpenIDTypeURIs(),
+ array('filter_MatchesAnyOpenIDType'));
+
+ $openid_services = Auth_OpenID_makeOpenIDEndpoints($iname,
+ $yadis_services);
+
+ $openid_services = Auth_OpenID_getOPOrUserServices($openid_services);
+
+ for ($i = 0; $i < count($openid_services); $i++) {
+ $openid_services[$i]->canonicalID = $canonicalID;
+ $openid_services[$i]->claimed_id = $canonicalID;
+ $openid_services[$i]->display_identifier = $iname;
+ }
+
+ // FIXME: returned xri should probably be in some normal form
+ return array($iname, $openid_services);
+}
+
+function Auth_OpenID_discover($uri, $fetcher)
+{
+ // If the fetcher (i.e., PHP) doesn't support SSL, we can't do
+ // discovery on an HTTPS URL.
+ if ($fetcher->isHTTPS($uri) && !$fetcher->supportsSSL()) {
+ return array($uri, array());
+ }
+
+ if (Auth_Yadis_identifierScheme($uri) == 'XRI') {
+ $result = Auth_OpenID_discoverXRI($uri, $fetcher);
+ } else {
+ $result = Auth_OpenID_discoverURI($uri, $fetcher);
+ }
+
+ // If the fetcher doesn't support SSL, we can't interact with
+ // HTTPS server URLs; remove those endpoints from the list.
+ if (!$fetcher->supportsSSL()) {
+ $http_endpoints = array();
+ list($new_uri, $endpoints) = $result;
+
+ foreach ($endpoints as $e) {
+ if (!$fetcher->isHTTPS($e->server_url)) {
+ $http_endpoints[] = $e;
+ }
+ }
+
+ $result = array($new_uri, $http_endpoints);
+ }
+
+ return $result;
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/DumbStore.php b/plugins/openid/lib/Auth/OpenID/DumbStore.php
new file mode 100644
index 00000000..e8f29ace
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/DumbStore.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * This file supplies a dumb store backend for OpenID servers and
+ * consumers.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Import the interface for creating a new store class.
+ */
+require_once 'Auth/OpenID/Interface.php';
+require_once 'Auth/OpenID/HMAC.php';
+
+/**
+ * This is a store for use in the worst case, when you have no way of
+ * saving state on the consumer site. Using this store makes the
+ * consumer vulnerable to replay attacks, as it's unable to use
+ * nonces. Avoid using this store if it is at all possible.
+ *
+ * Most of the methods of this class are implementation details.
+ * Users of this class need to worry only about the constructor.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_DumbStore extends Auth_OpenID_OpenIDStore {
+
+ /**
+ * Creates a new {@link Auth_OpenID_DumbStore} instance. For the security
+ * of the tokens generated by the library, this class attempts to
+ * at least have a secure implementation of getAuthKey.
+ *
+ * When you create an instance of this class, pass in a secret
+ * phrase. The phrase is hashed with sha1 to make it the correct
+ * length and form for an auth key. That allows you to use a long
+ * string as the secret phrase, which means you can make it very
+ * difficult to guess.
+ *
+ * Each {@link Auth_OpenID_DumbStore} instance that is created for use by
+ * your consumer site needs to use the same $secret_phrase.
+ *
+ * @param string secret_phrase The phrase used to create the auth
+ * key returned by getAuthKey
+ */
+ function Auth_OpenID_DumbStore($secret_phrase)
+ {
+ $this->auth_key = Auth_OpenID_SHA1($secret_phrase);
+ }
+
+ /**
+ * This implementation does nothing.
+ */
+ function storeAssociation($server_url, $association)
+ {
+ }
+
+ /**
+ * This implementation always returns null.
+ */
+ function getAssociation($server_url, $handle = null)
+ {
+ return null;
+ }
+
+ /**
+ * This implementation always returns false.
+ */
+ function removeAssociation($server_url, $handle)
+ {
+ return false;
+ }
+
+ /**
+ * In a system truly limited to dumb mode, nonces must all be
+ * accepted. This therefore always returns true, which makes
+ * replay attacks feasible.
+ */
+ function useNonce($server_url, $timestamp, $salt)
+ {
+ return true;
+ }
+
+ /**
+ * This method returns the auth key generated by the constructor.
+ */
+ function getAuthKey()
+ {
+ return $this->auth_key;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/Extension.php b/plugins/openid/lib/Auth/OpenID/Extension.php
new file mode 100644
index 00000000..c4e38c03
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Extension.php
@@ -0,0 +1,61 @@
+<?php
+
+/**
+ * An interface for OpenID extensions.
+ *
+ * @package OpenID
+ */
+
+/**
+ * Require the Message implementation.
+ */
+require_once 'Auth/OpenID/Message.php';
+
+/**
+ * A base class for accessing extension request and response data for
+ * the OpenID 2 protocol.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Extension {
+ /**
+ * ns_uri: The namespace to which to add the arguments for this
+ * extension
+ */
+ var $ns_uri = null;
+ var $ns_alias = null;
+
+ /**
+ * Get the string arguments that should be added to an OpenID
+ * message for this extension.
+ */
+ function getExtensionArgs()
+ {
+ return null;
+ }
+
+ /**
+ * Add the arguments from this extension to the provided message.
+ *
+ * Returns the message with the extension arguments added.
+ */
+ function toMessage($message)
+ {
+ $implicit = $message->isOpenID1();
+ $added = $message->namespaces->addAlias($this->ns_uri,
+ $this->ns_alias,
+ $implicit);
+
+ if ($added === null) {
+ if ($message->namespaces->getAlias($this->ns_uri) !=
+ $this->ns_alias) {
+ return null;
+ }
+ }
+
+ $message->updateArgs($this->ns_uri,
+ $this->getExtensionArgs());
+ return $message;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/FileStore.php b/plugins/openid/lib/Auth/OpenID/FileStore.php
new file mode 100644
index 00000000..074421a0
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/FileStore.php
@@ -0,0 +1,618 @@
+<?php
+
+/**
+ * This file supplies a Memcached store backend for OpenID servers and
+ * consumers.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Require base class for creating a new interface.
+ */
+require_once 'Auth/OpenID.php';
+require_once 'Auth/OpenID/Interface.php';
+require_once 'Auth/OpenID/HMAC.php';
+require_once 'Auth/OpenID/Nonce.php';
+
+/**
+ * This is a filesystem-based store for OpenID associations and
+ * nonces. This store should be safe for use in concurrent systems on
+ * both windows and unix (excluding NFS filesystems). There are a
+ * couple race conditions in the system, but those failure cases have
+ * been set up in such a way that the worst-case behavior is someone
+ * having to try to log in a second time.
+ *
+ * Most of the methods of this class are implementation details.
+ * People wishing to just use this store need only pay attention to
+ * the constructor.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore {
+
+ /**
+ * Initializes a new {@link Auth_OpenID_FileStore}. This
+ * initializes the nonce and association directories, which are
+ * subdirectories of the directory passed in.
+ *
+ * @param string $directory This is the directory to put the store
+ * directories in.
+ */
+ function Auth_OpenID_FileStore($directory)
+ {
+ if (!Auth_OpenID::ensureDir($directory)) {
+ trigger_error('Not a directory and failed to create: '
+ . $directory, E_USER_ERROR);
+ }
+ $directory = realpath($directory);
+
+ $this->directory = $directory;
+ $this->active = true;
+
+ $this->nonce_dir = $directory . DIRECTORY_SEPARATOR . 'nonces';
+
+ $this->association_dir = $directory . DIRECTORY_SEPARATOR .
+ 'associations';
+
+ // Temp dir must be on the same filesystem as the assciations
+ // $directory.
+ $this->temp_dir = $directory . DIRECTORY_SEPARATOR . 'temp';
+
+ $this->max_nonce_age = 6 * 60 * 60; // Six hours, in seconds
+
+ if (!$this->_setup()) {
+ trigger_error('Failed to initialize OpenID file store in ' .
+ $directory, E_USER_ERROR);
+ }
+ }
+
+ function destroy()
+ {
+ Auth_OpenID_FileStore::_rmtree($this->directory);
+ $this->active = false;
+ }
+
+ /**
+ * Make sure that the directories in which we store our data
+ * exist.
+ *
+ * @access private
+ */
+ function _setup()
+ {
+ return (Auth_OpenID::ensureDir($this->nonce_dir) &&
+ Auth_OpenID::ensureDir($this->association_dir) &&
+ Auth_OpenID::ensureDir($this->temp_dir));
+ }
+
+ /**
+ * Create a temporary file on the same filesystem as
+ * $this->association_dir.
+ *
+ * The temporary directory should not be cleaned if there are any
+ * processes using the store. If there is no active process using
+ * the store, it is safe to remove all of the files in the
+ * temporary directory.
+ *
+ * @return array ($fd, $filename)
+ * @access private
+ */
+ function _mktemp()
+ {
+ $name = Auth_OpenID_FileStore::_mkstemp($dir = $this->temp_dir);
+ $file_obj = @fopen($name, 'wb');
+ if ($file_obj !== false) {
+ return array($file_obj, $name);
+ } else {
+ Auth_OpenID_FileStore::_removeIfPresent($name);
+ }
+ }
+
+ function cleanupNonces()
+ {
+ global $Auth_OpenID_SKEW;
+
+ $nonces = Auth_OpenID_FileStore::_listdir($this->nonce_dir);
+ $now = time();
+
+ $removed = 0;
+ // Check all nonces for expiry
+ foreach ($nonces as $nonce_fname) {
+ $base = basename($nonce_fname);
+ $parts = explode('-', $base, 2);
+ $timestamp = $parts[0];
+ $timestamp = intval($timestamp, 16);
+ if (abs($timestamp - $now) > $Auth_OpenID_SKEW) {
+ Auth_OpenID_FileStore::_removeIfPresent($nonce_fname);
+ $removed += 1;
+ }
+ }
+ return $removed;
+ }
+
+ /**
+ * Create a unique filename for a given server url and
+ * handle. This implementation does not assume anything about the
+ * format of the handle. The filename that is returned will
+ * contain the domain name from the server URL for ease of human
+ * inspection of the data directory.
+ *
+ * @return string $filename
+ */
+ function getAssociationFilename($server_url, $handle)
+ {
+ if (!$this->active) {
+ trigger_error("FileStore no longer active", E_USER_ERROR);
+ return null;
+ }
+
+ if (strpos($server_url, '://') === false) {
+ trigger_error(sprintf("Bad server URL: %s", $server_url),
+ E_USER_WARNING);
+ return null;
+ }
+
+ list($proto, $rest) = explode('://', $server_url, 2);
+ $parts = explode('/', $rest);
+ $domain = Auth_OpenID_FileStore::_filenameEscape($parts[0]);
+ $url_hash = Auth_OpenID_FileStore::_safe64($server_url);
+ if ($handle) {
+ $handle_hash = Auth_OpenID_FileStore::_safe64($handle);
+ } else {
+ $handle_hash = '';
+ }
+
+ $filename = sprintf('%s-%s-%s-%s', $proto, $domain, $url_hash,
+ $handle_hash);
+
+ return $this->association_dir. DIRECTORY_SEPARATOR . $filename;
+ }
+
+ /**
+ * Store an association in the association directory.
+ */
+ function storeAssociation($server_url, $association)
+ {
+ if (!$this->active) {
+ trigger_error("FileStore no longer active", E_USER_ERROR);
+ return false;
+ }
+
+ $association_s = $association->serialize();
+ $filename = $this->getAssociationFilename($server_url,
+ $association->handle);
+ list($tmp_file, $tmp) = $this->_mktemp();
+
+ if (!$tmp_file) {
+ trigger_error("_mktemp didn't return a valid file descriptor",
+ E_USER_WARNING);
+ return false;
+ }
+
+ fwrite($tmp_file, $association_s);
+
+ fflush($tmp_file);
+
+ fclose($tmp_file);
+
+ if (@rename($tmp, $filename)) {
+ return true;
+ } else {
+ // In case we are running on Windows, try unlinking the
+ // file in case it exists.
+ @unlink($filename);
+
+ // Now the target should not exist. Try renaming again,
+ // giving up if it fails.
+ if (@rename($tmp, $filename)) {
+ return true;
+ }
+ }
+
+ // If there was an error, don't leave the temporary file
+ // around.
+ Auth_OpenID_FileStore::_removeIfPresent($tmp);
+ return false;
+ }
+
+ /**
+ * Retrieve an association. If no handle is specified, return the
+ * association with the most recent issue time.
+ *
+ * @return mixed $association
+ */
+ function getAssociation($server_url, $handle = null)
+ {
+ if (!$this->active) {
+ trigger_error("FileStore no longer active", E_USER_ERROR);
+ return null;
+ }
+
+ if ($handle === null) {
+ $handle = '';
+ }
+
+ // The filename with the empty handle is a prefix of all other
+ // associations for the given server URL.
+ $filename = $this->getAssociationFilename($server_url, $handle);
+
+ if ($handle) {
+ return $this->_getAssociation($filename);
+ } else {
+ $association_files =
+ Auth_OpenID_FileStore::_listdir($this->association_dir);
+ $matching_files = array();
+
+ // strip off the path to do the comparison
+ $name = basename($filename);
+ foreach ($association_files as $association_file) {
+ $base = basename($association_file);
+ if (strpos($base, $name) === 0) {
+ $matching_files[] = $association_file;
+ }
+ }
+
+ $matching_associations = array();
+ // read the matching files and sort by time issued
+ foreach ($matching_files as $full_name) {
+ $association = $this->_getAssociation($full_name);
+ if ($association !== null) {
+ $matching_associations[] = array($association->issued,
+ $association);
+ }
+ }
+
+ $issued = array();
+ $assocs = array();
+ foreach ($matching_associations as $key => $assoc) {
+ $issued[$key] = $assoc[0];
+ $assocs[$key] = $assoc[1];
+ }
+
+ array_multisort($issued, SORT_DESC, $assocs, SORT_DESC,
+ $matching_associations);
+
+ // return the most recently issued one.
+ if ($matching_associations) {
+ list($issued, $assoc) = $matching_associations[0];
+ return $assoc;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _getAssociation($filename)
+ {
+ if (!$this->active) {
+ trigger_error("FileStore no longer active", E_USER_ERROR);
+ return null;
+ }
+
+ $assoc_file = @fopen($filename, 'rb');
+
+ if ($assoc_file === false) {
+ return null;
+ }
+
+ $assoc_s = fread($assoc_file, filesize($filename));
+ fclose($assoc_file);
+
+ if (!$assoc_s) {
+ return null;
+ }
+
+ $association =
+ Auth_OpenID_Association::deserialize('Auth_OpenID_Association',
+ $assoc_s);
+
+ if (!$association) {
+ Auth_OpenID_FileStore::_removeIfPresent($filename);
+ return null;
+ }
+
+ if ($association->getExpiresIn() == 0) {
+ Auth_OpenID_FileStore::_removeIfPresent($filename);
+ return null;
+ } else {
+ return $association;
+ }
+ }
+
+ /**
+ * Remove an association if it exists. Do nothing if it does not.
+ *
+ * @return bool $success
+ */
+ function removeAssociation($server_url, $handle)
+ {
+ if (!$this->active) {
+ trigger_error("FileStore no longer active", E_USER_ERROR);
+ return null;
+ }
+
+ $assoc = $this->getAssociation($server_url, $handle);
+ if ($assoc === null) {
+ return false;
+ } else {
+ $filename = $this->getAssociationFilename($server_url, $handle);
+ return Auth_OpenID_FileStore::_removeIfPresent($filename);
+ }
+ }
+
+ /**
+ * Return whether this nonce is present. As a side effect, mark it
+ * as no longer present.
+ *
+ * @return bool $present
+ */
+ function useNonce($server_url, $timestamp, $salt)
+ {
+ global $Auth_OpenID_SKEW;
+
+ if (!$this->active) {
+ trigger_error("FileStore no longer active", E_USER_ERROR);
+ return null;
+ }
+
+ if ( abs($timestamp - time()) > $Auth_OpenID_SKEW ) {
+ return false;
+ }
+
+ if ($server_url) {
+ list($proto, $rest) = explode('://', $server_url, 2);
+ } else {
+ $proto = '';
+ $rest = '';
+ }
+
+ $parts = explode('/', $rest, 2);
+ $domain = $this->_filenameEscape($parts[0]);
+ $url_hash = $this->_safe64($server_url);
+ $salt_hash = $this->_safe64($salt);
+
+ $filename = sprintf('%08x-%s-%s-%s-%s', $timestamp, $proto,
+ $domain, $url_hash, $salt_hash);
+ $filename = $this->nonce_dir . DIRECTORY_SEPARATOR . $filename;
+
+ $result = @fopen($filename, 'x');
+
+ if ($result === false) {
+ return false;
+ } else {
+ fclose($result);
+ return true;
+ }
+ }
+
+ /**
+ * Remove expired entries from the database. This is potentially
+ * expensive, so only run when it is acceptable to take time.
+ *
+ * @access private
+ */
+ function _allAssocs()
+ {
+ $all_associations = array();
+
+ $association_filenames =
+ Auth_OpenID_FileStore::_listdir($this->association_dir);
+
+ foreach ($association_filenames as $association_filename) {
+ $association_file = fopen($association_filename, 'rb');
+
+ if ($association_file !== false) {
+ $assoc_s = fread($association_file,
+ filesize($association_filename));
+ fclose($association_file);
+
+ // Remove expired or corrupted associations
+ $association =
+ Auth_OpenID_Association::deserialize(
+ 'Auth_OpenID_Association', $assoc_s);
+
+ if ($association === null) {
+ Auth_OpenID_FileStore::_removeIfPresent(
+ $association_filename);
+ } else {
+ if ($association->getExpiresIn() == 0) {
+ $all_associations[] = array($association_filename,
+ $association);
+ }
+ }
+ }
+ }
+
+ return $all_associations;
+ }
+
+ function clean()
+ {
+ if (!$this->active) {
+ trigger_error("FileStore no longer active", E_USER_ERROR);
+ return null;
+ }
+
+ $nonces = Auth_OpenID_FileStore::_listdir($this->nonce_dir);
+ $now = time();
+
+ // Check all nonces for expiry
+ foreach ($nonces as $nonce) {
+ if (!Auth_OpenID_checkTimestamp($nonce, $now)) {
+ $filename = $this->nonce_dir . DIRECTORY_SEPARATOR . $nonce;
+ Auth_OpenID_FileStore::_removeIfPresent($filename);
+ }
+ }
+
+ foreach ($this->_allAssocs() as $pair) {
+ list($assoc_filename, $assoc) = $pair;
+ if ($assoc->getExpiresIn() == 0) {
+ Auth_OpenID_FileStore::_removeIfPresent($assoc_filename);
+ }
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _rmtree($dir)
+ {
+ if ($dir[strlen($dir) - 1] != DIRECTORY_SEPARATOR) {
+ $dir .= DIRECTORY_SEPARATOR;
+ }
+
+ if ($handle = opendir($dir)) {
+ while ($item = readdir($handle)) {
+ if (!in_array($item, array('.', '..'))) {
+ if (is_dir($dir . $item)) {
+
+ if (!Auth_OpenID_FileStore::_rmtree($dir . $item)) {
+ return false;
+ }
+ } else if (is_file($dir . $item)) {
+ if (!unlink($dir . $item)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ closedir($handle);
+
+ if (!@rmdir($dir)) {
+ return false;
+ }
+
+ return true;
+ } else {
+ // Couldn't open directory.
+ return false;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _mkstemp($dir)
+ {
+ foreach (range(0, 4) as $i) {
+ $name = tempnam($dir, "php_openid_filestore_");
+
+ if ($name !== false) {
+ return $name;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @access private
+ */
+ static function _mkdtemp($dir)
+ {
+ foreach (range(0, 4) as $i) {
+ $name = $dir . strval(DIRECTORY_SEPARATOR) . strval(getmypid()) .
+ "-" . strval(rand(1, time()));
+ if (!mkdir($name, 0700)) {
+ return false;
+ } else {
+ return $name;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @access private
+ */
+ function _listdir($dir)
+ {
+ $handle = opendir($dir);
+ $files = array();
+ while (false !== ($filename = readdir($handle))) {
+ if (!in_array($filename, array('.', '..'))) {
+ $files[] = $dir . DIRECTORY_SEPARATOR . $filename;
+ }
+ }
+ return $files;
+ }
+
+ /**
+ * @access private
+ */
+ function _isFilenameSafe($char)
+ {
+ $_Auth_OpenID_filename_allowed = Auth_OpenID_letters .
+ Auth_OpenID_digits . ".";
+ return (strpos($_Auth_OpenID_filename_allowed, $char) !== false);
+ }
+
+ /**
+ * @access private
+ */
+ function _safe64($str)
+ {
+ $h64 = base64_encode(Auth_OpenID_SHA1($str));
+ $h64 = str_replace('+', '_', $h64);
+ $h64 = str_replace('/', '.', $h64);
+ $h64 = str_replace('=', '', $h64);
+ return $h64;
+ }
+
+ /**
+ * @access private
+ */
+ function _filenameEscape($str)
+ {
+ $filename = "";
+ $b = Auth_OpenID::toBytes($str);
+
+ for ($i = 0; $i < count($b); $i++) {
+ $c = $b[$i];
+ if (Auth_OpenID_FileStore::_isFilenameSafe($c)) {
+ $filename .= $c;
+ } else {
+ $filename .= sprintf("_%02X", ord($c));
+ }
+ }
+ return $filename;
+ }
+
+ /**
+ * Attempt to remove a file, returning whether the file existed at
+ * the time of the call.
+ *
+ * @access private
+ * @return bool $result True if the file was present, false if not.
+ */
+ function _removeIfPresent($filename)
+ {
+ return @unlink($filename);
+ }
+
+ function cleanupAssociations()
+ {
+ $removed = 0;
+ foreach ($this->_allAssocs() as $pair) {
+ list($assoc_filename, $assoc) = $pair;
+ if ($assoc->getExpiresIn() == 0) {
+ $this->_removeIfPresent($assoc_filename);
+ $removed += 1;
+ }
+ }
+ return $removed;
+ }
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/HMAC.php b/plugins/openid/lib/Auth/OpenID/HMAC.php
new file mode 100644
index 00000000..e6c4bdfd
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/HMAC.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * This is the HMACSHA1 implementation for the OpenID library.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @access private
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+require_once 'Auth/OpenID.php';
+
+/**
+ * SHA1_BLOCKSIZE is this module's SHA1 blocksize used by the fallback
+ * implementation.
+ */
+define('Auth_OpenID_SHA1_BLOCKSIZE', 64);
+
+function Auth_OpenID_SHA1($text)
+{
+ if (function_exists('hash') &&
+ function_exists('hash_algos') &&
+ (in_array('sha1', hash_algos()))) {
+ // PHP 5 case (sometimes): 'hash' available and 'sha1' algo
+ // supported.
+ return hash('sha1', $text, true);
+ } else if (function_exists('sha1')) {
+ // PHP 4 case: 'sha1' available.
+ $hex = sha1($text);
+ $raw = '';
+ for ($i = 0; $i < 40; $i += 2) {
+ $hexcode = substr($hex, $i, 2);
+ $charcode = (int)base_convert($hexcode, 16, 10);
+ $raw .= chr($charcode);
+ }
+ return $raw;
+ } else {
+ // Explode.
+ trigger_error('No SHA1 function found', E_USER_ERROR);
+ }
+}
+
+/**
+ * Compute an HMAC/SHA1 hash.
+ *
+ * @access private
+ * @param string $key The HMAC key
+ * @param string $text The message text to hash
+ * @return string $mac The MAC
+ */
+function Auth_OpenID_HMACSHA1($key, $text)
+{
+ if (Auth_OpenID::bytes($key) > Auth_OpenID_SHA1_BLOCKSIZE) {
+ $key = Auth_OpenID_SHA1($key, true);
+ }
+
+ if (function_exists('hash_hmac') &&
+ function_exists('hash_algos') &&
+ (in_array('sha1', hash_algos()))) {
+ return hash_hmac('sha1', $text, $key, true);
+ }
+ // Home-made solution
+
+ $key = str_pad($key, Auth_OpenID_SHA1_BLOCKSIZE, chr(0x00));
+ $ipad = str_repeat(chr(0x36), Auth_OpenID_SHA1_BLOCKSIZE);
+ $opad = str_repeat(chr(0x5c), Auth_OpenID_SHA1_BLOCKSIZE);
+ $hash1 = Auth_OpenID_SHA1(($key ^ $ipad) . $text, true);
+ $hmac = Auth_OpenID_SHA1(($key ^ $opad) . $hash1, true);
+ return $hmac;
+}
+
+if (function_exists('hash') &&
+ function_exists('hash_algos') &&
+ (in_array('sha256', hash_algos()))) {
+ function Auth_OpenID_SHA256($text)
+ {
+ // PHP 5 case: 'hash' available and 'sha256' algo supported.
+ return hash('sha256', $text, true);
+ }
+ define('Auth_OpenID_SHA256_SUPPORTED', true);
+} else {
+ define('Auth_OpenID_SHA256_SUPPORTED', false);
+}
+
+if (function_exists('hash_hmac') &&
+ function_exists('hash_algos') &&
+ (in_array('sha256', hash_algos()))) {
+
+ function Auth_OpenID_HMACSHA256($key, $text)
+ {
+ // Return raw MAC (not hex string).
+ return hash_hmac('sha256', $text, $key, true);
+ }
+
+ define('Auth_OpenID_HMACSHA256_SUPPORTED', true);
+} else {
+ define('Auth_OpenID_HMACSHA256_SUPPORTED', false);
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/Interface.php b/plugins/openid/lib/Auth/OpenID/Interface.php
new file mode 100644
index 00000000..eca6b9c5
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Interface.php
@@ -0,0 +1,196 @@
+<?php
+
+/**
+ * This file specifies the interface for PHP OpenID store implementations.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * This is the interface for the store objects the OpenID library
+ * uses. It is a single class that provides all of the persistence
+ * mechanisms that the OpenID library needs, for both servers and
+ * consumers. If you want to create an SQL-driven store, please see
+ * then {@link Auth_OpenID_SQLStore} class.
+ *
+ * Change: Version 2.0 removed the storeNonce, getAuthKey, and isDumb
+ * methods, and changed the behavior of the useNonce method to support
+ * one-way nonces.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ */
+class Auth_OpenID_OpenIDStore {
+ /**
+ * This method puts an Association object into storage,
+ * retrievable by server URL and handle.
+ *
+ * @param string $server_url The URL of the identity server that
+ * this association is with. Because of the way the server portion
+ * of the library uses this interface, don't assume there are any
+ * limitations on the character set of the input string. In
+ * particular, expect to see unescaped non-url-safe characters in
+ * the server_url field.
+ *
+ * @param Association $association The Association to store.
+ */
+ function storeAssociation($server_url, $association)
+ {
+ trigger_error("Auth_OpenID_OpenIDStore::storeAssociation ".
+ "not implemented", E_USER_ERROR);
+ }
+
+ /*
+ * Remove expired nonces from the store.
+ *
+ * Discards any nonce from storage that is old enough that its
+ * timestamp would not pass useNonce().
+ *
+ * This method is not called in the normal operation of the
+ * library. It provides a way for store admins to keep their
+ * storage from filling up with expired data.
+ *
+ * @return the number of nonces expired
+ */
+ function cleanupNonces()
+ {
+ trigger_error("Auth_OpenID_OpenIDStore::cleanupNonces ".
+ "not implemented", E_USER_ERROR);
+ }
+
+ /*
+ * Remove expired associations from the store.
+ *
+ * This method is not called in the normal operation of the
+ * library. It provides a way for store admins to keep their
+ * storage from filling up with expired data.
+ *
+ * @return the number of associations expired.
+ */
+ function cleanupAssociations()
+ {
+ trigger_error("Auth_OpenID_OpenIDStore::cleanupAssociations ".
+ "not implemented", E_USER_ERROR);
+ }
+
+ /*
+ * Shortcut for cleanupNonces(), cleanupAssociations().
+ *
+ * This method is not called in the normal operation of the
+ * library. It provides a way for store admins to keep their
+ * storage from filling up with expired data.
+ */
+ function cleanup()
+ {
+ return array($this->cleanupNonces(),
+ $this->cleanupAssociations());
+ }
+
+ /**
+ * Report whether this storage supports cleanup
+ */
+ function supportsCleanup()
+ {
+ return true;
+ }
+
+ /**
+ * This method returns an Association object from storage that
+ * matches the server URL and, if specified, handle. It returns
+ * null if no such association is found or if the matching
+ * association is expired.
+ *
+ * If no handle is specified, the store may return any association
+ * which matches the server URL. If multiple associations are
+ * valid, the recommended return value for this method is the one
+ * most recently issued.
+ *
+ * This method is allowed (and encouraged) to garbage collect
+ * expired associations when found. This method must not return
+ * expired associations.
+ *
+ * @param string $server_url The URL of the identity server to get
+ * the association for. Because of the way the server portion of
+ * the library uses this interface, don't assume there are any
+ * limitations on the character set of the input string. In
+ * particular, expect to see unescaped non-url-safe characters in
+ * the server_url field.
+ *
+ * @param mixed $handle This optional parameter is the handle of
+ * the specific association to get. If no specific handle is
+ * provided, any valid association matching the server URL is
+ * returned.
+ *
+ * @return Association The Association for the given identity
+ * server.
+ */
+ function getAssociation($server_url, $handle = null)
+ {
+ trigger_error("Auth_OpenID_OpenIDStore::getAssociation ".
+ "not implemented", E_USER_ERROR);
+ }
+
+ /**
+ * This method removes the matching association if it's found, and
+ * returns whether the association was removed or not.
+ *
+ * @param string $server_url The URL of the identity server the
+ * association to remove belongs to. Because of the way the server
+ * portion of the library uses this interface, don't assume there
+ * are any limitations on the character set of the input
+ * string. In particular, expect to see unescaped non-url-safe
+ * characters in the server_url field.
+ *
+ * @param string $handle This is the handle of the association to
+ * remove. If there isn't an association found that matches both
+ * the given URL and handle, then there was no matching handle
+ * found.
+ *
+ * @return mixed Returns whether or not the given association existed.
+ */
+ function removeAssociation($server_url, $handle)
+ {
+ trigger_error("Auth_OpenID_OpenIDStore::removeAssociation ".
+ "not implemented", E_USER_ERROR);
+ }
+
+ /**
+ * Called when using a nonce.
+ *
+ * This method should return C{True} if the nonce has not been
+ * used before, and store it for a while to make sure nobody
+ * tries to use the same value again. If the nonce has already
+ * been used, return C{False}.
+ *
+ * Change: In earlier versions, round-trip nonces were used and a
+ * nonce was only valid if it had been previously stored with
+ * storeNonce. Version 2.0 uses one-way nonces, requiring a
+ * different implementation here that does not depend on a
+ * storeNonce call. (storeNonce is no longer part of the
+ * interface.
+ *
+ * @param string $nonce The nonce to use.
+ *
+ * @return bool Whether or not the nonce was valid.
+ */
+ function useNonce($server_url, $timestamp, $salt)
+ {
+ trigger_error("Auth_OpenID_OpenIDStore::useNonce ".
+ "not implemented", E_USER_ERROR);
+ }
+
+ /**
+ * Removes all entries from the store; implementation is optional.
+ */
+ function reset()
+ {
+ }
+
+}
diff --git a/plugins/openid/lib/Auth/OpenID/KVForm.php b/plugins/openid/lib/Auth/OpenID/KVForm.php
new file mode 100644
index 00000000..dd02661d
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/KVForm.php
@@ -0,0 +1,111 @@
+<?php
+
+/**
+ * OpenID protocol key-value/comma-newline format parsing and
+ * serialization
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @access private
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Container for key-value/comma-newline OpenID format and parsing
+ */
+class Auth_OpenID_KVForm {
+ /**
+ * Convert an OpenID colon/newline separated string into an
+ * associative array
+ *
+ * @static
+ * @access private
+ */
+ static function toArray($kvs, $strict=false)
+ {
+ $lines = explode("\n", $kvs);
+
+ $last = array_pop($lines);
+ if ($last !== '') {
+ array_push($lines, $last);
+ if ($strict) {
+ return false;
+ }
+ }
+
+ $values = array();
+
+ for ($lineno = 0; $lineno < count($lines); $lineno++) {
+ $line = $lines[$lineno];
+ $kv = explode(':', $line, 2);
+ if (count($kv) != 2) {
+ if ($strict) {
+ return false;
+ }
+ continue;
+ }
+
+ $key = $kv[0];
+ $tkey = trim($key);
+ if ($tkey != $key) {
+ if ($strict) {
+ return false;
+ }
+ }
+
+ $value = $kv[1];
+ $tval = trim($value);
+ if ($tval != $value) {
+ if ($strict) {
+ return false;
+ }
+ }
+
+ $values[$tkey] = $tval;
+ }
+
+ return $values;
+ }
+
+ /**
+ * Convert an array into an OpenID colon/newline separated string
+ *
+ * @static
+ * @access private
+ */
+ static function fromArray($values)
+ {
+ if ($values === null) {
+ return null;
+ }
+
+ ksort($values);
+
+ $serialized = '';
+ foreach ($values as $key => $value) {
+ if (is_array($value)) {
+ list($key, $value) = array($value[0], $value[1]);
+ }
+
+ if (strpos($key, ':') !== false) {
+ return null;
+ }
+
+ if (strpos($key, "\n") !== false) {
+ return null;
+ }
+
+ if (strpos($value, "\n") !== false) {
+ return null;
+ }
+ $serialized .= "$key:$value\n";
+ }
+ return $serialized;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/MDB2Store.php b/plugins/openid/lib/Auth/OpenID/MDB2Store.php
new file mode 100644
index 00000000..80024bad
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/MDB2Store.php
@@ -0,0 +1,413 @@
+<?php
+
+/**
+ * SQL-backed OpenID stores for use with PEAR::MDB2.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005 Janrain, Inc.
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL
+ */
+
+require_once 'MDB2.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/Interface.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/Nonce.php';
+
+/**
+ * This store uses a PEAR::MDB2 connection to store persistence
+ * information.
+ *
+ * The table names used are determined by the class variables
+ * associations_table_name and nonces_table_name. To change the name
+ * of the tables used, pass new table names into the constructor.
+ *
+ * To create the tables with the proper schema, see the createTables
+ * method.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_MDB2Store extends Auth_OpenID_OpenIDStore {
+ /**
+ * This creates a new MDB2Store instance. It requires an
+ * established database connection be given to it, and it allows
+ * overriding the default table names.
+ *
+ * @param connection $connection This must be an established
+ * connection to a database of the correct type for the SQLStore
+ * subclass you're using. This must be a PEAR::MDB2 connection
+ * handle.
+ *
+ * @param associations_table: This is an optional parameter to
+ * specify the name of the table used for storing associations.
+ * The default value is 'oid_associations'.
+ *
+ * @param nonces_table: This is an optional parameter to specify
+ * the name of the table used for storing nonces. The default
+ * value is 'oid_nonces'.
+ */
+ function Auth_OpenID_MDB2Store($connection,
+ $associations_table = null,
+ $nonces_table = null)
+ {
+ $this->associations_table_name = "oid_associations";
+ $this->nonces_table_name = "oid_nonces";
+
+ // Check the connection object type to be sure it's a PEAR
+ // database connection.
+ if (!is_object($connection) ||
+ !is_subclass_of($connection, 'mdb2_driver_common')) {
+ trigger_error("Auth_OpenID_MDB2Store expected PEAR connection " .
+ "object (got ".get_class($connection).")",
+ E_USER_ERROR);
+ return;
+ }
+
+ $this->connection = $connection;
+
+ // Be sure to set the fetch mode so the results are keyed on
+ // column name instead of column index.
+ $this->connection->setFetchMode(MDB2_FETCHMODE_ASSOC);
+
+ if (PEAR::isError($this->connection->loadModule('Extended'))) {
+ trigger_error("Unable to load MDB2_Extended module", E_USER_ERROR);
+ return;
+ }
+
+ if ($associations_table) {
+ $this->associations_table_name = $associations_table;
+ }
+
+ if ($nonces_table) {
+ $this->nonces_table_name = $nonces_table;
+ }
+
+ $this->max_nonce_age = 6 * 60 * 60;
+ }
+
+ function tableExists($table_name)
+ {
+ return !PEAR::isError($this->connection->query(
+ sprintf("SELECT * FROM %s LIMIT 0",
+ $table_name)));
+ }
+
+ function createTables()
+ {
+ $n = $this->create_nonce_table();
+ $a = $this->create_assoc_table();
+
+ if (!$n || !$a) {
+ return false;
+ }
+ return true;
+ }
+
+ function create_nonce_table()
+ {
+ if (!$this->tableExists($this->nonces_table_name)) {
+ switch ($this->connection->phptype) {
+ case "mysql":
+ case "mysqli":
+ // Custom SQL for MySQL to use InnoDB and variable-
+ // length keys
+ $r = $this->connection->exec(
+ sprintf("CREATE TABLE %s (\n".
+ " server_url VARCHAR(2047) NOT NULL DEFAULT '',\n".
+ " timestamp INTEGER NOT NULL,\n".
+ " salt CHAR(40) NOT NULL,\n".
+ " UNIQUE (server_url(255), timestamp, salt)\n".
+ ") TYPE=InnoDB",
+ $this->nonces_table_name));
+ if (PEAR::isError($r)) {
+ return false;
+ }
+ break;
+ default:
+ if (PEAR::isError(
+ $this->connection->loadModule('Manager'))) {
+ return false;
+ }
+ $fields = array(
+ "server_url" => array(
+ "type" => "text",
+ "length" => 2047,
+ "notnull" => true
+ ),
+ "timestamp" => array(
+ "type" => "integer",
+ "notnull" => true
+ ),
+ "salt" => array(
+ "type" => "text",
+ "length" => 40,
+ "fixed" => true,
+ "notnull" => true
+ )
+ );
+ $constraint = array(
+ "unique" => 1,
+ "fields" => array(
+ "server_url" => true,
+ "timestamp" => true,
+ "salt" => true
+ )
+ );
+
+ $r = $this->connection->createTable($this->nonces_table_name,
+ $fields);
+ if (PEAR::isError($r)) {
+ return false;
+ }
+
+ $r = $this->connection->createConstraint(
+ $this->nonces_table_name,
+ $this->nonces_table_name . "_constraint",
+ $constraint);
+ if (PEAR::isError($r)) {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ function create_assoc_table()
+ {
+ if (!$this->tableExists($this->associations_table_name)) {
+ switch ($this->connection->phptype) {
+ case "mysql":
+ case "mysqli":
+ // Custom SQL for MySQL to use InnoDB and variable-
+ // length keys
+ $r = $this->connection->exec(
+ sprintf("CREATE TABLE %s(\n".
+ " server_url VARCHAR(2047) NOT NULL DEFAULT '',\n".
+ " handle VARCHAR(255) NOT NULL,\n".
+ " secret BLOB NOT NULL,\n".
+ " issued INTEGER NOT NULL,\n".
+ " lifetime INTEGER NOT NULL,\n".
+ " assoc_type VARCHAR(64) NOT NULL,\n".
+ " PRIMARY KEY (server_url(255), handle)\n".
+ ") TYPE=InnoDB",
+ $this->associations_table_name));
+ if (PEAR::isError($r)) {
+ return false;
+ }
+ break;
+ default:
+ if (PEAR::isError(
+ $this->connection->loadModule('Manager'))) {
+ return false;
+ }
+ $fields = array(
+ "server_url" => array(
+ "type" => "text",
+ "length" => 2047,
+ "notnull" => true
+ ),
+ "handle" => array(
+ "type" => "text",
+ "length" => 255,
+ "notnull" => true
+ ),
+ "secret" => array(
+ "type" => "blob",
+ "length" => "255",
+ "notnull" => true
+ ),
+ "issued" => array(
+ "type" => "integer",
+ "notnull" => true
+ ),
+ "lifetime" => array(
+ "type" => "integer",
+ "notnull" => true
+ ),
+ "assoc_type" => array(
+ "type" => "text",
+ "length" => 64,
+ "notnull" => true
+ )
+ );
+ $options = array(
+ "primary" => array(
+ "server_url" => true,
+ "handle" => true
+ )
+ );
+
+ $r = $this->connection->createTable(
+ $this->associations_table_name,
+ $fields,
+ $options);
+ if (PEAR::isError($r)) {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ function storeAssociation($server_url, $association)
+ {
+ $fields = array(
+ "server_url" => array(
+ "value" => $server_url,
+ "key" => true
+ ),
+ "handle" => array(
+ "value" => $association->handle,
+ "key" => true
+ ),
+ "secret" => array(
+ "value" => $association->secret,
+ "type" => "blob"
+ ),
+ "issued" => array(
+ "value" => $association->issued
+ ),
+ "lifetime" => array(
+ "value" => $association->lifetime
+ ),
+ "assoc_type" => array(
+ "value" => $association->assoc_type
+ )
+ );
+
+ return !PEAR::isError($this->connection->replace(
+ $this->associations_table_name,
+ $fields));
+ }
+
+ function cleanupNonces()
+ {
+ global $Auth_OpenID_SKEW;
+ $v = time() - $Auth_OpenID_SKEW;
+
+ return $this->connection->exec(
+ sprintf("DELETE FROM %s WHERE timestamp < %d",
+ $this->nonces_table_name, $v));
+ }
+
+ function cleanupAssociations()
+ {
+ return $this->connection->exec(
+ sprintf("DELETE FROM %s WHERE issued + lifetime < %d",
+ $this->associations_table_name, time()));
+ }
+
+ function getAssociation($server_url, $handle = null)
+ {
+ $sql = "";
+ $params = null;
+ $types = array(
+ "text",
+ "blob",
+ "integer",
+ "integer",
+ "text"
+ );
+ if ($handle !== null) {
+ $sql = sprintf("SELECT handle, secret, issued, lifetime, assoc_type " .
+ "FROM %s WHERE server_url = ? AND handle = ?",
+ $this->associations_table_name);
+ $params = array($server_url, $handle);
+ } else {
+ $sql = sprintf("SELECT handle, secret, issued, lifetime, assoc_type " .
+ "FROM %s WHERE server_url = ? ORDER BY issued DESC",
+ $this->associations_table_name);
+ $params = array($server_url);
+ }
+
+ $assoc = $this->connection->getRow($sql, $types, $params);
+
+ if (!$assoc || PEAR::isError($assoc)) {
+ return null;
+ } else {
+ $association = new Auth_OpenID_Association($assoc['handle'],
+ stream_get_contents(
+ $assoc['secret']),
+ $assoc['issued'],
+ $assoc['lifetime'],
+ $assoc['assoc_type']);
+ fclose($assoc['secret']);
+ return $association;
+ }
+ }
+
+ function removeAssociation($server_url, $handle)
+ {
+ $r = $this->connection->execParam(
+ sprintf("DELETE FROM %s WHERE server_url = ? AND handle = ?",
+ $this->associations_table_name),
+ array($server_url, $handle));
+
+ if (PEAR::isError($r) || $r == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ function useNonce($server_url, $timestamp, $salt)
+ {
+ global $Auth_OpenID_SKEW;
+
+ if (abs($timestamp - time()) > $Auth_OpenID_SKEW ) {
+ return false;
+ }
+
+ $fields = array(
+ "timestamp" => $timestamp,
+ "salt" => $salt
+ );
+
+ if (!empty($server_url)) {
+ $fields["server_url"] = $server_url;
+ }
+
+ $r = $this->connection->autoExecute(
+ $this->nonces_table_name,
+ $fields,
+ MDB2_AUTOQUERY_INSERT);
+
+ if (PEAR::isError($r)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Resets the store by removing all records from the store's
+ * tables.
+ */
+ function reset()
+ {
+ $this->connection->query(sprintf("DELETE FROM %s",
+ $this->associations_table_name));
+
+ $this->connection->query(sprintf("DELETE FROM %s",
+ $this->nonces_table_name));
+ }
+
+}
+
+?>
diff --git a/plugins/openid/lib/Auth/OpenID/MemcachedStore.php b/plugins/openid/lib/Auth/OpenID/MemcachedStore.php
new file mode 100644
index 00000000..fc10800b
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/MemcachedStore.php
@@ -0,0 +1,207 @@
+<?php
+
+/**
+ * This file supplies a memcached store backend for OpenID servers and
+ * consumers.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author Artemy Tregubenko <me@arty.name>
+ * @copyright 2008 JanRain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ * Contributed by Open Web Technologies <http://openwebtech.ru/>
+ */
+
+/**
+ * Import the interface for creating a new store class.
+ */
+require_once 'Auth/OpenID/Interface.php';
+
+/**
+ * This is a memcached-based store for OpenID associations and
+ * nonces.
+ *
+ * As memcache has limit of 250 chars for key length,
+ * server_url, handle and salt are hashed with sha1().
+ *
+ * Most of the methods of this class are implementation details.
+ * People wishing to just use this store need only pay attention to
+ * the constructor.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_MemcachedStore extends Auth_OpenID_OpenIDStore {
+
+ /**
+ * Initializes a new {@link Auth_OpenID_MemcachedStore} instance.
+ * Just saves memcached object as property.
+ *
+ * @param resource connection Memcache connection resourse
+ */
+ function Auth_OpenID_MemcachedStore($connection, $compress = false)
+ {
+ $this->connection = $connection;
+ $this->compress = $compress ? MEMCACHE_COMPRESSED : 0;
+ }
+
+ /**
+ * Store association until its expiration time in memcached.
+ * Overwrites any existing association with same server_url and
+ * handle. Handles list of associations for every server.
+ */
+ function storeAssociation($server_url, $association)
+ {
+ // create memcached keys for association itself
+ // and list of associations for this server
+ $associationKey = $this->associationKey($server_url,
+ $association->handle);
+ $serverKey = $this->associationServerKey($server_url);
+
+ // get list of associations
+ $serverAssociations = $this->connection->get($serverKey);
+
+ // if no such list, initialize it with empty array
+ if (!$serverAssociations) {
+ $serverAssociations = array();
+ }
+ // and store given association key in it
+ $serverAssociations[$association->issued] = $associationKey;
+
+ // save associations' keys list
+ $this->connection->set(
+ $serverKey,
+ $serverAssociations,
+ $this->compress
+ );
+ // save association itself
+ $this->connection->set(
+ $associationKey,
+ $association,
+ $this->compress,
+ $association->issued + $association->lifetime);
+ }
+
+ /**
+ * Read association from memcached. If no handle given
+ * and multiple associations found, returns latest issued
+ */
+ function getAssociation($server_url, $handle = null)
+ {
+ // simple case: handle given
+ if ($handle !== null) {
+ // get association, return null if failed
+ $association = $this->connection->get(
+ $this->associationKey($server_url, $handle));
+ return $association ? $association : null;
+ }
+
+ // no handle given, working with list
+ // create key for list of associations
+ $serverKey = $this->associationServerKey($server_url);
+
+ // get list of associations
+ $serverAssociations = $this->connection->get($serverKey);
+ // return null if failed or got empty list
+ if (!$serverAssociations) {
+ return null;
+ }
+
+ // get key of most recently issued association
+ $keys = array_keys($serverAssociations);
+ sort($keys);
+ $lastKey = $serverAssociations[array_pop($keys)];
+
+ // get association, return null if failed
+ $association = $this->connection->get($lastKey);
+ return $association ? $association : null;
+ }
+
+ /**
+ * Immediately delete association from memcache.
+ */
+ function removeAssociation($server_url, $handle)
+ {
+ // create memcached keys for association itself
+ // and list of associations for this server
+ $serverKey = $this->associationServerKey($server_url);
+ $associationKey = $this->associationKey($server_url,
+ $handle);
+
+ // get list of associations
+ $serverAssociations = $this->connection->get($serverKey);
+ // return null if failed or got empty list
+ if (!$serverAssociations) {
+ return false;
+ }
+
+ // ensure that given association key exists in list
+ $serverAssociations = array_flip($serverAssociations);
+ if (!array_key_exists($associationKey, $serverAssociations)) {
+ return false;
+ }
+
+ // remove given association key from list
+ unset($serverAssociations[$associationKey]);
+ $serverAssociations = array_flip($serverAssociations);
+
+ // save updated list
+ $this->connection->set(
+ $serverKey,
+ $serverAssociations,
+ $this->compress
+ );
+
+ // delete association
+ return $this->connection->delete($associationKey);
+ }
+
+ /**
+ * Create nonce for server and salt, expiring after
+ * $Auth_OpenID_SKEW seconds.
+ */
+ function useNonce($server_url, $timestamp, $salt)
+ {
+ global $Auth_OpenID_SKEW;
+
+ // save one request to memcache when nonce obviously expired
+ if (abs($timestamp - time()) > $Auth_OpenID_SKEW) {
+ return false;
+ }
+
+ // returns false when nonce already exists
+ // otherwise adds nonce
+ return $this->connection->add(
+ 'openid_nonce_' . sha1($server_url) . '_' . sha1($salt),
+ 1, // any value here
+ $this->compress,
+ $Auth_OpenID_SKEW);
+ }
+
+ /**
+ * Memcache key is prefixed with 'openid_association_' string.
+ */
+ function associationKey($server_url, $handle = null)
+ {
+ return 'openid_association_' . sha1($server_url) . '_' . sha1($handle);
+ }
+
+ /**
+ * Memcache key is prefixed with 'openid_association_' string.
+ */
+ function associationServerKey($server_url)
+ {
+ return 'openid_association_server_' . sha1($server_url);
+ }
+
+ /**
+ * Report that this storage doesn't support cleanup
+ */
+ function supportsCleanup()
+ {
+ return false;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/Message.php b/plugins/openid/lib/Auth/OpenID/Message.php
new file mode 100644
index 00000000..9a5b20d0
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Message.php
@@ -0,0 +1,920 @@
+<?php
+
+/**
+ * Extension argument processing code
+ *
+ * @package OpenID
+ */
+
+/**
+ * Import tools needed to deal with messages.
+ */
+require_once 'Auth/OpenID.php';
+require_once 'Auth/OpenID/KVForm.php';
+require_once 'Auth/Yadis/XML.php';
+require_once 'Auth/OpenID/Consumer.php'; // For Auth_OpenID_FailureResponse
+
+// This doesn't REALLY belong here, but where is better?
+define('Auth_OpenID_IDENTIFIER_SELECT',
+ "http://specs.openid.net/auth/2.0/identifier_select");
+
+// URI for Simple Registration extension, the only commonly deployed
+// OpenID 1.x extension, and so a special case
+define('Auth_OpenID_SREG_URI', 'http://openid.net/sreg/1.0');
+
+// The OpenID 1.X namespace URI
+define('Auth_OpenID_OPENID1_NS', 'http://openid.net/signon/1.0');
+define('Auth_OpenID_THE_OTHER_OPENID1_NS', 'http://openid.net/signon/1.1');
+
+function Auth_OpenID_isOpenID1($ns)
+{
+ return ($ns == Auth_OpenID_THE_OTHER_OPENID1_NS) ||
+ ($ns == Auth_OpenID_OPENID1_NS);
+}
+
+// The OpenID 2.0 namespace URI
+define('Auth_OpenID_OPENID2_NS', 'http://specs.openid.net/auth/2.0');
+
+// The namespace consisting of pairs with keys that are prefixed with
+// "openid." but not in another namespace.
+define('Auth_OpenID_NULL_NAMESPACE', 'Null namespace');
+
+// The null namespace, when it is an allowed OpenID namespace
+define('Auth_OpenID_OPENID_NS', 'OpenID namespace');
+
+// The top-level namespace, excluding all pairs with keys that start
+// with "openid."
+define('Auth_OpenID_BARE_NS', 'Bare namespace');
+
+// Sentinel for Message implementation to indicate that getArg should
+// return null instead of returning a default.
+define('Auth_OpenID_NO_DEFAULT', 'NO DEFAULT ALLOWED');
+
+// Limit, in bytes, of identity provider and return_to URLs, including
+// response payload. See OpenID 1.1 specification, Appendix D.
+define('Auth_OpenID_OPENID1_URL_LIMIT', 2047);
+
+// All OpenID protocol fields. Used to check namespace aliases.
+global $Auth_OpenID_OPENID_PROTOCOL_FIELDS;
+$Auth_OpenID_OPENID_PROTOCOL_FIELDS = array(
+ 'ns', 'mode', 'error', 'return_to', 'contact', 'reference',
+ 'signed', 'assoc_type', 'session_type', 'dh_modulus', 'dh_gen',
+ 'dh_consumer_public', 'claimed_id', 'identity', 'realm',
+ 'invalidate_handle', 'op_endpoint', 'response_nonce', 'sig',
+ 'assoc_handle', 'trust_root', 'openid');
+
+// Global namespace / alias registration map. See
+// Auth_OpenID_registerNamespaceAlias.
+global $Auth_OpenID_registered_aliases;
+$Auth_OpenID_registered_aliases = array();
+
+/**
+ * Registers a (namespace URI, alias) mapping in a global namespace
+ * alias map. Raises NamespaceAliasRegistrationError if either the
+ * namespace URI or alias has already been registered with a different
+ * value. This function is required if you want to use a namespace
+ * with an OpenID 1 message.
+ */
+function Auth_OpenID_registerNamespaceAlias($namespace_uri, $alias)
+{
+ global $Auth_OpenID_registered_aliases;
+
+ if (Auth_OpenID::arrayGet($Auth_OpenID_registered_aliases,
+ $alias) == $namespace_uri) {
+ return true;
+ }
+
+ if (in_array($namespace_uri,
+ array_values($Auth_OpenID_registered_aliases))) {
+ return false;
+ }
+
+ if (in_array($alias, array_keys($Auth_OpenID_registered_aliases))) {
+ return false;
+ }
+
+ $Auth_OpenID_registered_aliases[$alias] = $namespace_uri;
+ return true;
+}
+
+/**
+ * Removes a (namespace_uri, alias) registration from the global
+ * namespace alias map. Returns true if the removal succeeded; false
+ * if not (if the mapping did not exist).
+ */
+function Auth_OpenID_removeNamespaceAlias($namespace_uri, $alias)
+{
+ global $Auth_OpenID_registered_aliases;
+
+ if (Auth_OpenID::arrayGet($Auth_OpenID_registered_aliases,
+ $alias) === $namespace_uri) {
+ unset($Auth_OpenID_registered_aliases[$alias]);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * An Auth_OpenID_Mapping maintains a mapping from arbitrary keys to
+ * arbitrary values. (This is unlike an ordinary PHP array, whose
+ * keys may be only simple scalars.)
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Mapping {
+ /**
+ * Initialize a mapping. If $classic_array is specified, its keys
+ * and values are used to populate the mapping.
+ */
+ function Auth_OpenID_Mapping($classic_array = null)
+ {
+ $this->keys = array();
+ $this->values = array();
+
+ if (is_array($classic_array)) {
+ foreach ($classic_array as $key => $value) {
+ $this->set($key, $value);
+ }
+ }
+ }
+
+ /**
+ * Returns true if $thing is an Auth_OpenID_Mapping object; false
+ * if not.
+ */
+ static function isA($thing)
+ {
+ return (is_object($thing) &&
+ strtolower(get_class($thing)) == 'auth_openid_mapping');
+ }
+
+ /**
+ * Returns an array of the keys in the mapping.
+ */
+ function keys()
+ {
+ return $this->keys;
+ }
+
+ /**
+ * Returns an array of values in the mapping.
+ */
+ function values()
+ {
+ return $this->values;
+ }
+
+ /**
+ * Returns an array of (key, value) pairs in the mapping.
+ */
+ function items()
+ {
+ $temp = array();
+
+ for ($i = 0; $i < count($this->keys); $i++) {
+ $temp[] = array($this->keys[$i],
+ $this->values[$i]);
+ }
+ return $temp;
+ }
+
+ /**
+ * Returns the "length" of the mapping, or the number of keys.
+ */
+ function len()
+ {
+ return count($this->keys);
+ }
+
+ /**
+ * Sets a key-value pair in the mapping. If the key already
+ * exists, its value is replaced with the new value.
+ */
+ function set($key, $value)
+ {
+ $index = array_search($key, $this->keys);
+
+ if ($index !== false) {
+ $this->values[$index] = $value;
+ } else {
+ $this->keys[] = $key;
+ $this->values[] = $value;
+ }
+ }
+
+ /**
+ * Gets a specified value from the mapping, associated with the
+ * specified key. If the key does not exist in the mapping,
+ * $default is returned instead.
+ */
+ function get($key, $default = null)
+ {
+ $index = array_search($key, $this->keys);
+
+ if ($index !== false) {
+ return $this->values[$index];
+ } else {
+ return $default;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _reflow()
+ {
+ // PHP is broken yet again. Sort the arrays to remove the
+ // hole in the numeric indexes that make up the array.
+ $old_keys = $this->keys;
+ $old_values = $this->values;
+
+ $this->keys = array();
+ $this->values = array();
+
+ foreach ($old_keys as $k) {
+ $this->keys[] = $k;
+ }
+
+ foreach ($old_values as $v) {
+ $this->values[] = $v;
+ }
+ }
+
+ /**
+ * Deletes a key-value pair from the mapping with the specified
+ * key.
+ */
+ function del($key)
+ {
+ $index = array_search($key, $this->keys);
+
+ if ($index !== false) {
+ unset($this->keys[$index]);
+ unset($this->values[$index]);
+ $this->_reflow();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the specified value has a key in the mapping;
+ * false if not.
+ */
+ function contains($value)
+ {
+ return (array_search($value, $this->keys) !== false);
+ }
+}
+
+/**
+ * Maintains a bijective map between namespace uris and aliases.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_NamespaceMap {
+ function Auth_OpenID_NamespaceMap()
+ {
+ $this->alias_to_namespace = new Auth_OpenID_Mapping();
+ $this->namespace_to_alias = new Auth_OpenID_Mapping();
+ $this->implicit_namespaces = array();
+ }
+
+ function getAlias($namespace_uri)
+ {
+ return $this->namespace_to_alias->get($namespace_uri);
+ }
+
+ function getNamespaceURI($alias)
+ {
+ return $this->alias_to_namespace->get($alias);
+ }
+
+ function iterNamespaceURIs()
+ {
+ // Return an iterator over the namespace URIs
+ return $this->namespace_to_alias->keys();
+ }
+
+ function iterAliases()
+ {
+ // Return an iterator over the aliases"""
+ return $this->alias_to_namespace->keys();
+ }
+
+ function iteritems()
+ {
+ return $this->namespace_to_alias->items();
+ }
+
+ function isImplicit($namespace_uri)
+ {
+ return in_array($namespace_uri, $this->implicit_namespaces);
+ }
+
+ function addAlias($namespace_uri, $desired_alias, $implicit=false)
+ {
+ // Add an alias from this namespace URI to the desired alias
+ global $Auth_OpenID_OPENID_PROTOCOL_FIELDS;
+
+ // Check that desired_alias is not an openid protocol field as
+ // per the spec.
+ if (in_array($desired_alias, $Auth_OpenID_OPENID_PROTOCOL_FIELDS)) {
+ Auth_OpenID::log("\"%s\" is not an allowed namespace alias",
+ $desired_alias);
+ return null;
+ }
+
+ // Check that desired_alias does not contain a period as per
+ // the spec.
+ if (strpos($desired_alias, '.') !== false) {
+ Auth_OpenID::log('"%s" must not contain a dot', $desired_alias);
+ return null;
+ }
+
+ // Check that there is not a namespace already defined for the
+ // desired alias
+ $current_namespace_uri =
+ $this->alias_to_namespace->get($desired_alias);
+
+ if (($current_namespace_uri !== null) &&
+ ($current_namespace_uri != $namespace_uri)) {
+ Auth_OpenID::log('Cannot map "%s" because previous mapping exists',
+ $namespace_uri);
+ return null;
+ }
+
+ // Check that there is not already a (different) alias for
+ // this namespace URI
+ $alias = $this->namespace_to_alias->get($namespace_uri);
+
+ if (($alias !== null) && ($alias != $desired_alias)) {
+ Auth_OpenID::log('Cannot map %s to alias %s. ' .
+ 'It is already mapped to alias %s',
+ $namespace_uri, $desired_alias, $alias);
+ return null;
+ }
+
+ assert((Auth_OpenID_NULL_NAMESPACE === $desired_alias) ||
+ is_string($desired_alias));
+
+ $this->alias_to_namespace->set($desired_alias, $namespace_uri);
+ $this->namespace_to_alias->set($namespace_uri, $desired_alias);
+ if ($implicit) {
+ array_push($this->implicit_namespaces, $namespace_uri);
+ }
+
+ return $desired_alias;
+ }
+
+ function add($namespace_uri)
+ {
+ // Add this namespace URI to the mapping, without caring what
+ // alias it ends up with
+
+ // See if this namespace is already mapped to an alias
+ $alias = $this->namespace_to_alias->get($namespace_uri);
+
+ if ($alias !== null) {
+ return $alias;
+ }
+
+ // Fall back to generating a numerical alias
+ $i = 0;
+ while (1) {
+ $alias = 'ext' . strval($i);
+ if ($this->addAlias($namespace_uri, $alias) === null) {
+ $i += 1;
+ } else {
+ return $alias;
+ }
+ }
+
+ // Should NEVER be reached!
+ return null;
+ }
+
+ function contains($namespace_uri)
+ {
+ return $this->isDefined($namespace_uri);
+ }
+
+ function isDefined($namespace_uri)
+ {
+ return $this->namespace_to_alias->contains($namespace_uri);
+ }
+}
+
+/**
+ * In the implementation of this object, null represents the global
+ * namespace as well as a namespace with no key.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Message {
+
+ function Auth_OpenID_Message($openid_namespace = null)
+ {
+ // Create an empty Message
+ $this->allowed_openid_namespaces = array(
+ Auth_OpenID_OPENID1_NS,
+ Auth_OpenID_THE_OTHER_OPENID1_NS,
+ Auth_OpenID_OPENID2_NS);
+
+ $this->args = new Auth_OpenID_Mapping();
+ $this->namespaces = new Auth_OpenID_NamespaceMap();
+ if ($openid_namespace === null) {
+ $this->_openid_ns_uri = null;
+ } else {
+ $implicit = Auth_OpenID_isOpenID1($openid_namespace);
+ $this->setOpenIDNamespace($openid_namespace, $implicit);
+ }
+ }
+
+ function isOpenID1()
+ {
+ return Auth_OpenID_isOpenID1($this->getOpenIDNamespace());
+ }
+
+ function isOpenID2()
+ {
+ return $this->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS;
+ }
+
+ static function fromPostArgs($args)
+ {
+ // Construct a Message containing a set of POST arguments
+ $obj = new Auth_OpenID_Message();
+
+ // Partition into "openid." args and bare args
+ $openid_args = array();
+ foreach ($args as $key => $value) {
+
+ if (is_array($value)) {
+ return null;
+ }
+
+ $parts = explode('.', $key, 2);
+
+ if (count($parts) == 2) {
+ list($prefix, $rest) = $parts;
+ } else {
+ $prefix = null;
+ }
+
+ if ($prefix != 'openid') {
+ $obj->args->set(array(Auth_OpenID_BARE_NS, $key), $value);
+ } else {
+ $openid_args[$rest] = $value;
+ }
+ }
+
+ if ($obj->_fromOpenIDArgs($openid_args)) {
+ return $obj;
+ } else {
+ return null;
+ }
+ }
+
+ static function fromOpenIDArgs($openid_args)
+ {
+ // Takes an array.
+
+ // Construct a Message from a parsed KVForm message
+ $obj = new Auth_OpenID_Message();
+ if ($obj->_fromOpenIDArgs($openid_args)) {
+ return $obj;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _fromOpenIDArgs($openid_args)
+ {
+ global $Auth_OpenID_registered_aliases;
+
+ // Takes an Auth_OpenID_Mapping instance OR an array.
+
+ if (!Auth_OpenID_Mapping::isA($openid_args)) {
+ $openid_args = new Auth_OpenID_Mapping($openid_args);
+ }
+
+ $ns_args = array();
+
+ // Resolve namespaces
+ foreach ($openid_args->items() as $pair) {
+ list($rest, $value) = $pair;
+
+ $parts = explode('.', $rest, 2);
+
+ if (count($parts) == 2) {
+ list($ns_alias, $ns_key) = $parts;
+ } else {
+ $ns_alias = Auth_OpenID_NULL_NAMESPACE;
+ $ns_key = $rest;
+ }
+
+ if ($ns_alias == 'ns') {
+ if ($this->namespaces->addAlias($value, $ns_key) === null) {
+ return false;
+ }
+ } else if (($ns_alias == Auth_OpenID_NULL_NAMESPACE) &&
+ ($ns_key == 'ns')) {
+ // null namespace
+ if ($this->setOpenIDNamespace($value, false) === false) {
+ return false;
+ }
+ } else {
+ $ns_args[] = array($ns_alias, $ns_key, $value);
+ }
+ }
+
+ if (!$this->getOpenIDNamespace()) {
+ if ($this->setOpenIDNamespace(Auth_OpenID_OPENID1_NS, true) ===
+ false) {
+ return false;
+ }
+ }
+
+ // Actually put the pairs into the appropriate namespaces
+ foreach ($ns_args as $triple) {
+ list($ns_alias, $ns_key, $value) = $triple;
+ $ns_uri = $this->namespaces->getNamespaceURI($ns_alias);
+ if ($ns_uri === null) {
+ $ns_uri = $this->_getDefaultNamespace($ns_alias);
+ if ($ns_uri === null) {
+
+ $ns_uri = Auth_OpenID_OPENID_NS;
+ $ns_key = sprintf('%s.%s', $ns_alias, $ns_key);
+ } else {
+ $this->namespaces->addAlias($ns_uri, $ns_alias, true);
+ }
+ }
+
+ $this->setArg($ns_uri, $ns_key, $value);
+ }
+
+ return true;
+ }
+
+ function _getDefaultNamespace($mystery_alias)
+ {
+ global $Auth_OpenID_registered_aliases;
+ if ($this->isOpenID1()) {
+ return @$Auth_OpenID_registered_aliases[$mystery_alias];
+ }
+ return null;
+ }
+
+ function setOpenIDNamespace($openid_ns_uri, $implicit)
+ {
+ if (!in_array($openid_ns_uri, $this->allowed_openid_namespaces)) {
+ Auth_OpenID::log('Invalid null namespace: "%s"', $openid_ns_uri);
+ return false;
+ }
+
+ $succeeded = $this->namespaces->addAlias($openid_ns_uri,
+ Auth_OpenID_NULL_NAMESPACE,
+ $implicit);
+ if ($succeeded === false) {
+ return false;
+ }
+
+ $this->_openid_ns_uri = $openid_ns_uri;
+
+ return true;
+ }
+
+ function getOpenIDNamespace()
+ {
+ return $this->_openid_ns_uri;
+ }
+
+ static function fromKVForm($kvform_string)
+ {
+ // Create a Message from a KVForm string
+ return Auth_OpenID_Message::fromOpenIDArgs(
+ Auth_OpenID_KVForm::toArray($kvform_string));
+ }
+
+ function copy()
+ {
+ return $this;
+ }
+
+ function toPostArgs()
+ {
+ // Return all arguments with openid. in front of namespaced
+ // arguments.
+
+ $args = array();
+
+ // Add namespace definitions to the output
+ foreach ($this->namespaces->iteritems() as $pair) {
+ list($ns_uri, $alias) = $pair;
+ if ($this->namespaces->isImplicit($ns_uri)) {
+ continue;
+ }
+ if ($alias == Auth_OpenID_NULL_NAMESPACE) {
+ $ns_key = 'openid.ns';
+ } else {
+ $ns_key = 'openid.ns.' . $alias;
+ }
+ $args[$ns_key] = $ns_uri;
+ }
+
+ foreach ($this->args->items() as $pair) {
+ list($ns_parts, $value) = $pair;
+ list($ns_uri, $ns_key) = $ns_parts;
+ $key = $this->getKey($ns_uri, $ns_key);
+ $args[$key] = $value;
+ }
+
+ return $args;
+ }
+
+ function toArgs()
+ {
+ // Return all namespaced arguments, failing if any
+ // non-namespaced arguments exist.
+ $post_args = $this->toPostArgs();
+ $kvargs = array();
+ foreach ($post_args as $k => $v) {
+ if (strpos($k, 'openid.') !== 0) {
+ // raise ValueError(
+ // 'This message can only be encoded as a POST, because it '
+ // 'contains arguments that are not prefixed with "openid."')
+ return null;
+ } else {
+ $kvargs[substr($k, 7)] = $v;
+ }
+ }
+
+ return $kvargs;
+ }
+
+ function toFormMarkup($action_url, $form_tag_attrs = null,
+ $submit_text = "Continue")
+ {
+ $form = "<form accept-charset=\"UTF-8\" ".
+ "enctype=\"application/x-www-form-urlencoded\"";
+
+ if (!$form_tag_attrs) {
+ $form_tag_attrs = array();
+ }
+
+ $form_tag_attrs['action'] = $action_url;
+ $form_tag_attrs['method'] = 'post';
+
+ unset($form_tag_attrs['enctype']);
+ unset($form_tag_attrs['accept-charset']);
+
+ if ($form_tag_attrs) {
+ foreach ($form_tag_attrs as $name => $attr) {
+ $form .= sprintf(" %s=\"%s\"", $name, $attr);
+ }
+ }
+
+ $form .= ">\n";
+
+ foreach ($this->toPostArgs() as $name => $value) {
+ $form .= sprintf(
+ "<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
+ $name, urldecode($value));
+ }
+
+ $form .= sprintf("<input type=\"submit\" value=\"%s\" />\n",
+ $submit_text);
+
+ $form .= "</form>\n";
+
+ return $form;
+ }
+
+ function toURL($base_url)
+ {
+ // Generate a GET URL with the parameters in this message
+ // attached as query parameters.
+ return Auth_OpenID::appendArgs($base_url, $this->toPostArgs());
+ }
+
+ function toKVForm()
+ {
+ // Generate a KVForm string that contains the parameters in
+ // this message. This will fail if the message contains
+ // arguments outside of the 'openid.' prefix.
+ return Auth_OpenID_KVForm::fromArray($this->toArgs());
+ }
+
+ function toURLEncoded()
+ {
+ // Generate an x-www-urlencoded string
+ $args = array();
+
+ foreach ($this->toPostArgs() as $k => $v) {
+ $args[] = array($k, $v);
+ }
+
+ sort($args);
+ return Auth_OpenID::httpBuildQuery($args);
+ }
+
+ /**
+ * @access private
+ */
+ function _fixNS($namespace)
+ {
+ // Convert an input value into the internally used values of
+ // this object
+
+ if ($namespace == Auth_OpenID_OPENID_NS) {
+ if ($this->_openid_ns_uri === null) {
+ return new Auth_OpenID_FailureResponse(null,
+ 'OpenID namespace not set');
+ } else {
+ $namespace = $this->_openid_ns_uri;
+ }
+ }
+
+ if (($namespace != Auth_OpenID_BARE_NS) &&
+ (!is_string($namespace))) {
+ //TypeError
+ $err_msg = sprintf("Namespace must be Auth_OpenID_BARE_NS, ".
+ "Auth_OpenID_OPENID_NS or a string. got %s",
+ print_r($namespace, true));
+ return new Auth_OpenID_FailureResponse(null, $err_msg);
+ }
+
+ if (($namespace != Auth_OpenID_BARE_NS) &&
+ (strpos($namespace, ':') === false)) {
+ // fmt = 'OpenID 2.0 namespace identifiers SHOULD be URIs. Got %r'
+ // warnings.warn(fmt % (namespace,), DeprecationWarning)
+
+ if ($namespace == 'sreg') {
+ // fmt = 'Using %r instead of "sreg" as namespace'
+ // warnings.warn(fmt % (SREG_URI,), DeprecationWarning,)
+ return Auth_OpenID_SREG_URI;
+ }
+ }
+
+ return $namespace;
+ }
+
+ function hasKey($namespace, $ns_key)
+ {
+ $namespace = $this->_fixNS($namespace);
+ if (Auth_OpenID::isFailure($namespace)) {
+ // XXX log me
+ return false;
+ } else {
+ return $this->args->contains(array($namespace, $ns_key));
+ }
+ }
+
+ function getKey($namespace, $ns_key)
+ {
+ // Get the key for a particular namespaced argument
+ $namespace = $this->_fixNS($namespace);
+ if (Auth_OpenID::isFailure($namespace)) {
+ return $namespace;
+ }
+ if ($namespace == Auth_OpenID_BARE_NS) {
+ return $ns_key;
+ }
+
+ $ns_alias = $this->namespaces->getAlias($namespace);
+
+ // No alias is defined, so no key can exist
+ if ($ns_alias === null) {
+ return null;
+ }
+
+ if ($ns_alias == Auth_OpenID_NULL_NAMESPACE) {
+ $tail = $ns_key;
+ } else {
+ $tail = sprintf('%s.%s', $ns_alias, $ns_key);
+ }
+
+ return 'openid.' . $tail;
+ }
+
+ function getArg($namespace, $key, $default = null)
+ {
+ // Get a value for a namespaced key.
+ $namespace = $this->_fixNS($namespace);
+
+ if (Auth_OpenID::isFailure($namespace)) {
+ return $namespace;
+ } else {
+ if ((!$this->args->contains(array($namespace, $key))) &&
+ ($default == Auth_OpenID_NO_DEFAULT)) {
+ $err_msg = sprintf("Namespace %s missing required field %s",
+ $namespace, $key);
+ return new Auth_OpenID_FailureResponse(null, $err_msg);
+ } else {
+ return $this->args->get(array($namespace, $key), $default);
+ }
+ }
+ }
+
+ function getArgs($namespace)
+ {
+ // Get the arguments that are defined for this namespace URI
+
+ $namespace = $this->_fixNS($namespace);
+ if (Auth_OpenID::isFailure($namespace)) {
+ return $namespace;
+ } else {
+ $stuff = array();
+ foreach ($this->args->items() as $pair) {
+ list($key, $value) = $pair;
+ list($pair_ns, $ns_key) = $key;
+ if ($pair_ns == $namespace) {
+ $stuff[$ns_key] = $value;
+ }
+ }
+
+ return $stuff;
+ }
+ }
+
+ function updateArgs($namespace, $updates)
+ {
+ // Set multiple key/value pairs in one call
+
+ $namespace = $this->_fixNS($namespace);
+
+ if (Auth_OpenID::isFailure($namespace)) {
+ return $namespace;
+ } else {
+ foreach ($updates as $k => $v) {
+ $this->setArg($namespace, $k, $v);
+ }
+ return true;
+ }
+ }
+
+ function setArg($namespace, $key, $value)
+ {
+ // Set a single argument in this namespace
+ $namespace = $this->_fixNS($namespace);
+
+ if (Auth_OpenID::isFailure($namespace)) {
+ return $namespace;
+ } else {
+ $this->args->set(array($namespace, $key), $value);
+ if ($namespace !== Auth_OpenID_BARE_NS) {
+ $this->namespaces->add($namespace);
+ }
+ return true;
+ }
+ }
+
+ function delArg($namespace, $key)
+ {
+ $namespace = $this->_fixNS($namespace);
+
+ if (Auth_OpenID::isFailure($namespace)) {
+ return $namespace;
+ } else {
+ return $this->args->del(array($namespace, $key));
+ }
+ }
+
+ function getAliasedArg($aliased_key, $default = null)
+ {
+ if ($aliased_key == 'ns') {
+ // Return the namespace URI for the OpenID namespace
+ return $this->getOpenIDNamespace();
+ }
+
+ $parts = explode('.', $aliased_key, 2);
+
+ if (count($parts) != 2) {
+ $ns = null;
+ } else {
+ list($alias, $key) = $parts;
+
+ if ($alias == 'ns') {
+ // Return the namespace URI for a namespace alias
+ // parameter.
+ return $this->namespaces->getNamespaceURI($key);
+ } else {
+ $ns = $this->namespaces->getNamespaceURI($alias);
+ }
+ }
+
+ if ($ns === null) {
+ $key = $aliased_key;
+ $ns = $this->getOpenIDNamespace();
+ }
+
+ return $this->getArg($ns, $key, $default);
+ }
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/MySQLStore.php b/plugins/openid/lib/Auth/OpenID/MySQLStore.php
new file mode 100644
index 00000000..a5299b3a
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/MySQLStore.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * A MySQL store.
+ *
+ * @package OpenID
+ */
+
+/**
+ * Require the base class file.
+ */
+require_once "Auth/OpenID/SQLStore.php";
+
+/**
+ * An SQL store that uses MySQL as its backend.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_MySQLStore extends Auth_OpenID_SQLStore {
+ /**
+ * @access private
+ */
+ function setSQL()
+ {
+ $this->sql['nonce_table'] =
+ "CREATE TABLE %s (\n".
+ " server_url VARCHAR(2047) NOT NULL,\n".
+ " timestamp INTEGER NOT NULL,\n".
+ " salt CHAR(40) NOT NULL,\n".
+ " UNIQUE (server_url(255), timestamp, salt)\n".
+ ") ENGINE=InnoDB";
+
+ $this->sql['assoc_table'] =
+ "CREATE TABLE %s (\n".
+ " server_url VARCHAR(2047) NOT NULL,\n".
+ " handle VARCHAR(255) NOT NULL,\n".
+ " secret BLOB NOT NULL,\n".
+ " issued INTEGER NOT NULL,\n".
+ " lifetime INTEGER NOT NULL,\n".
+ " assoc_type VARCHAR(64) NOT NULL,\n".
+ " PRIMARY KEY (server_url(255), handle)\n".
+ ") ENGINE=InnoDB";
+
+ $this->sql['set_assoc'] =
+ "REPLACE INTO %s (server_url, handle, secret, issued,\n".
+ " lifetime, assoc_type) VALUES (?, ?, !, ?, ?, ?)";
+
+ $this->sql['get_assocs'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ?";
+
+ $this->sql['get_assoc'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ? AND handle = ?";
+
+ $this->sql['remove_assoc'] =
+ "DELETE FROM %s WHERE server_url = ? AND handle = ?";
+
+ $this->sql['add_nonce'] =
+ "INSERT INTO %s (server_url, timestamp, salt) VALUES (?, ?, ?)";
+
+ $this->sql['clean_nonce'] =
+ "DELETE FROM %s WHERE timestamp < ?";
+
+ $this->sql['clean_assoc'] =
+ "DELETE FROM %s WHERE issued + lifetime < ?";
+ }
+
+ /**
+ * @access private
+ */
+ function blobEncode($blob)
+ {
+ return "0x" . bin2hex($blob);
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/Nonce.php b/plugins/openid/lib/Auth/OpenID/Nonce.php
new file mode 100644
index 00000000..b83c5911
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Nonce.php
@@ -0,0 +1,108 @@
+<?php
+
+/**
+ * Nonce-related functionality.
+ *
+ * @package OpenID
+ */
+
+/**
+ * Need CryptUtil to generate random strings.
+ */
+require_once 'Auth/OpenID/CryptUtil.php';
+
+/**
+ * This is the characters that the nonces are made from.
+ */
+define('Auth_OpenID_Nonce_CHRS',"abcdefghijklmnopqrstuvwxyz" .
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
+
+// Keep nonces for five hours (allow five hours for the combination of
+// request time and clock skew). This is probably way more than is
+// necessary, but there is not much overhead in storing nonces.
+global $Auth_OpenID_SKEW;
+$Auth_OpenID_SKEW = 60 * 60 * 5;
+
+define('Auth_OpenID_Nonce_REGEX',
+ '/(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z(.*)/');
+
+define('Auth_OpenID_Nonce_TIME_FMT',
+ '%Y-%m-%dT%H:%M:%SZ');
+
+function Auth_OpenID_splitNonce($nonce_string)
+{
+ // Extract a timestamp from the given nonce string
+ $result = preg_match(Auth_OpenID_Nonce_REGEX, $nonce_string, $matches);
+ if ($result != 1 || count($matches) != 8) {
+ return null;
+ }
+
+ list($unused,
+ $tm_year,
+ $tm_mon,
+ $tm_mday,
+ $tm_hour,
+ $tm_min,
+ $tm_sec,
+ $uniquifier) = $matches;
+
+ $timestamp =
+ @gmmktime($tm_hour, $tm_min, $tm_sec, $tm_mon, $tm_mday, $tm_year);
+
+ if ($timestamp === false || $timestamp < 0) {
+ return null;
+ }
+
+ return array($timestamp, $uniquifier);
+}
+
+function Auth_OpenID_checkTimestamp($nonce_string,
+ $allowed_skew = null,
+ $now = null)
+{
+ // Is the timestamp that is part of the specified nonce string
+ // within the allowed clock-skew of the current time?
+ global $Auth_OpenID_SKEW;
+
+ if ($allowed_skew === null) {
+ $allowed_skew = $Auth_OpenID_SKEW;
+ }
+
+ $parts = Auth_OpenID_splitNonce($nonce_string);
+ if ($parts == null) {
+ return false;
+ }
+
+ if ($now === null) {
+ $now = time();
+ }
+
+ $stamp = $parts[0];
+
+ // Time after which we should not use the nonce
+ $past = $now - $allowed_skew;
+
+ // Time that is too far in the future for us to allow
+ $future = $now + $allowed_skew;
+
+ // the stamp is not too far in the future and is not too far
+ // in the past
+ return (($past <= $stamp) && ($stamp <= $future));
+}
+
+function Auth_OpenID_mkNonce($when = null)
+{
+ // Generate a nonce with the current timestamp
+ $salt = Auth_OpenID_CryptUtil::randomString(
+ 6, Auth_OpenID_Nonce_CHRS);
+ if ($when === null) {
+ // It's safe to call time() with no arguments; it returns a
+ // GMT unix timestamp on PHP 4 and PHP 5. gmmktime() with no
+ // args returns a local unix timestamp on PHP 4, so don't use
+ // that.
+ $when = time();
+ }
+ $time_str = gmstrftime(Auth_OpenID_Nonce_TIME_FMT, $when);
+ return $time_str . $salt;
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/PAPE.php b/plugins/openid/lib/Auth/OpenID/PAPE.php
new file mode 100644
index 00000000..f08ca8bd
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/PAPE.php
@@ -0,0 +1,300 @@
+<?php
+
+/**
+ * An implementation of the OpenID Provider Authentication Policy
+ * Extension 1.0
+ *
+ * See:
+ * http://openid.net/developers/specs/
+ */
+
+require_once "Auth/OpenID/Extension.php";
+
+define('Auth_OpenID_PAPE_NS_URI',
+ "http://specs.openid.net/extensions/pape/1.0");
+
+define('PAPE_AUTH_MULTI_FACTOR_PHYSICAL',
+ 'http://schemas.openid.net/pape/policies/2007/06/multi-factor-physical');
+define('PAPE_AUTH_MULTI_FACTOR',
+ 'http://schemas.openid.net/pape/policies/2007/06/multi-factor');
+define('PAPE_AUTH_PHISHING_RESISTANT',
+ 'http://schemas.openid.net/pape/policies/2007/06/phishing-resistant');
+
+define('PAPE_TIME_VALIDATOR',
+ '/^[0-9]{4,4}-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z$/');
+/**
+ * A Provider Authentication Policy request, sent from a relying party
+ * to a provider
+ *
+ * preferred_auth_policies: The authentication policies that
+ * the relying party prefers
+ *
+ * max_auth_age: The maximum time, in seconds, that the relying party
+ * wants to allow to have elapsed before the user must re-authenticate
+ */
+class Auth_OpenID_PAPE_Request extends Auth_OpenID_Extension {
+
+ var $ns_alias = 'pape';
+ var $ns_uri = Auth_OpenID_PAPE_NS_URI;
+
+ function Auth_OpenID_PAPE_Request($preferred_auth_policies=null,
+ $max_auth_age=null)
+ {
+ if ($preferred_auth_policies === null) {
+ $preferred_auth_policies = array();
+ }
+
+ $this->preferred_auth_policies = $preferred_auth_policies;
+ $this->max_auth_age = $max_auth_age;
+ }
+
+ /**
+ * Add an acceptable authentication policy URI to this request
+ *
+ * This method is intended to be used by the relying party to add
+ * acceptable authentication types to the request.
+ *
+ * policy_uri: The identifier for the preferred type of
+ * authentication.
+ */
+ function addPolicyURI($policy_uri)
+ {
+ if (!in_array($policy_uri, $this->preferred_auth_policies)) {
+ $this->preferred_auth_policies[] = $policy_uri;
+ }
+ }
+
+ function getExtensionArgs()
+ {
+ $ns_args = array(
+ 'preferred_auth_policies' =>
+ implode(' ', $this->preferred_auth_policies)
+ );
+
+ if ($this->max_auth_age !== null) {
+ $ns_args['max_auth_age'] = strval($this->max_auth_age);
+ }
+
+ return $ns_args;
+ }
+
+ /**
+ * Instantiate a Request object from the arguments in a checkid_*
+ * OpenID message
+ */
+ static function fromOpenIDRequest($request)
+ {
+ $obj = new Auth_OpenID_PAPE_Request();
+ $args = $request->message->getArgs(Auth_OpenID_PAPE_NS_URI);
+
+ if ($args === null || $args === array()) {
+ return null;
+ }
+
+ $obj->parseExtensionArgs($args);
+ return $obj;
+ }
+
+ /**
+ * Set the state of this request to be that expressed in these
+ * PAPE arguments
+ *
+ * @param args: The PAPE arguments without a namespace
+ */
+ function parseExtensionArgs($args)
+ {
+ // preferred_auth_policies is a space-separated list of policy
+ // URIs
+ $this->preferred_auth_policies = array();
+
+ $policies_str = Auth_OpenID::arrayGet($args, 'preferred_auth_policies');
+ if ($policies_str) {
+ foreach (explode(' ', $policies_str) as $uri) {
+ if (!in_array($uri, $this->preferred_auth_policies)) {
+ $this->preferred_auth_policies[] = $uri;
+ }
+ }
+ }
+
+ // max_auth_age is base-10 integer number of seconds
+ $max_auth_age_str = Auth_OpenID::arrayGet($args, 'max_auth_age');
+ if ($max_auth_age_str) {
+ $this->max_auth_age = Auth_OpenID::intval($max_auth_age_str);
+ } else {
+ $this->max_auth_age = null;
+ }
+ }
+
+ /**
+ * Given a list of authentication policy URIs that a provider
+ * supports, this method returns the subsequence of those types
+ * that are preferred by the relying party.
+ *
+ * @param supported_types: A sequence of authentication policy
+ * type URIs that are supported by a provider
+ *
+ * @return array The sub-sequence of the supported types that are
+ * preferred by the relying party. This list will be ordered in
+ * the order that the types appear in the supported_types
+ * sequence, and may be empty if the provider does not prefer any
+ * of the supported authentication types.
+ */
+ function preferredTypes($supported_types)
+ {
+ $result = array();
+
+ foreach ($supported_types as $st) {
+ if (in_array($st, $this->preferred_auth_policies)) {
+ $result[] = $st;
+ }
+ }
+ return $result;
+ }
+}
+
+/**
+ * A Provider Authentication Policy response, sent from a provider to
+ * a relying party
+ */
+class Auth_OpenID_PAPE_Response extends Auth_OpenID_Extension {
+
+ var $ns_alias = 'pape';
+ var $ns_uri = Auth_OpenID_PAPE_NS_URI;
+
+ function Auth_OpenID_PAPE_Response($auth_policies=null, $auth_time=null,
+ $nist_auth_level=null)
+ {
+ if ($auth_policies) {
+ $this->auth_policies = $auth_policies;
+ } else {
+ $this->auth_policies = array();
+ }
+
+ $this->auth_time = $auth_time;
+ $this->nist_auth_level = $nist_auth_level;
+ }
+
+ /**
+ * Add a authentication policy to this response
+ *
+ * This method is intended to be used by the provider to add a
+ * policy that the provider conformed to when authenticating the
+ * user.
+ *
+ * @param policy_uri: The identifier for the preferred type of
+ * authentication.
+ */
+ function addPolicyURI($policy_uri)
+ {
+ if (!in_array($policy_uri, $this->auth_policies)) {
+ $this->auth_policies[] = $policy_uri;
+ }
+ }
+
+ /**
+ * Create an Auth_OpenID_PAPE_Response object from a successful
+ * OpenID library response.
+ *
+ * @param success_response $success_response A SuccessResponse
+ * from Auth_OpenID_Consumer::complete()
+ *
+ * @returns: A provider authentication policy response from the
+ * data that was supplied with the id_res response.
+ */
+ static function fromSuccessResponse($success_response)
+ {
+ $obj = new Auth_OpenID_PAPE_Response();
+
+ // PAPE requires that the args be signed.
+ $args = $success_response->getSignedNS(Auth_OpenID_PAPE_NS_URI);
+
+ if ($args === null || $args === array()) {
+ return null;
+ }
+
+ $result = $obj->parseExtensionArgs($args);
+
+ if ($result === false) {
+ return null;
+ } else {
+ return $obj;
+ }
+ }
+
+ /**
+ * Parse the provider authentication policy arguments into the
+ * internal state of this object
+ *
+ * @param args: unqualified provider authentication policy
+ * arguments
+ *
+ * @param strict: Whether to return false when bad data is
+ * encountered
+ *
+ * @return null The data is parsed into the internal fields of
+ * this object.
+ */
+ function parseExtensionArgs($args, $strict=false)
+ {
+ $policies_str = Auth_OpenID::arrayGet($args, 'auth_policies');
+ if ($policies_str && $policies_str != "none") {
+ $this->auth_policies = explode(" ", $policies_str);
+ }
+
+ $nist_level_str = Auth_OpenID::arrayGet($args, 'nist_auth_level');
+ if ($nist_level_str !== null) {
+ $nist_level = Auth_OpenID::intval($nist_level_str);
+
+ if ($nist_level === false) {
+ if ($strict) {
+ return false;
+ } else {
+ $nist_level = null;
+ }
+ }
+
+ if (0 <= $nist_level && $nist_level < 5) {
+ $this->nist_auth_level = $nist_level;
+ } else if ($strict) {
+ return false;
+ }
+ }
+
+ $auth_time = Auth_OpenID::arrayGet($args, 'auth_time');
+ if ($auth_time !== null) {
+ if (preg_match(PAPE_TIME_VALIDATOR, $auth_time)) {
+ $this->auth_time = $auth_time;
+ } else if ($strict) {
+ return false;
+ }
+ }
+ }
+
+ function getExtensionArgs()
+ {
+ $ns_args = array();
+ if (count($this->auth_policies) > 0) {
+ $ns_args['auth_policies'] = implode(' ', $this->auth_policies);
+ } else {
+ $ns_args['auth_policies'] = 'none';
+ }
+
+ if ($this->nist_auth_level !== null) {
+ if (!in_array($this->nist_auth_level, range(0, 4), true)) {
+ return false;
+ }
+ $ns_args['nist_auth_level'] = strval($this->nist_auth_level);
+ }
+
+ if ($this->auth_time !== null) {
+ if (!preg_match(PAPE_TIME_VALIDATOR, $this->auth_time)) {
+ return false;
+ }
+
+ $ns_args['auth_time'] = $this->auth_time;
+ }
+
+ return $ns_args;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/Parse.php b/plugins/openid/lib/Auth/OpenID/Parse.php
new file mode 100644
index 00000000..0461bdcf
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Parse.php
@@ -0,0 +1,381 @@
+<?php
+
+/**
+ * This module implements a VERY limited parser that finds <link> tags
+ * in the head of HTML or XHTML documents and parses out their
+ * attributes according to the OpenID spec. It is a liberal parser,
+ * but it requires these things from the data in order to work:
+ *
+ * - There must be an open <html> tag
+ *
+ * - There must be an open <head> tag inside of the <html> tag
+ *
+ * - Only <link>s that are found inside of the <head> tag are parsed
+ * (this is by design)
+ *
+ * - The parser follows the OpenID specification in resolving the
+ * attributes of the link tags. This means that the attributes DO
+ * NOT get resolved as they would by an XML or HTML parser. In
+ * particular, only certain entities get replaced, and href
+ * attributes do not get resolved relative to a base URL.
+ *
+ * From http://openid.net/specs.bml:
+ *
+ * - The openid.server URL MUST be an absolute URL. OpenID consumers
+ * MUST NOT attempt to resolve relative URLs.
+ *
+ * - The openid.server URL MUST NOT include entities other than &amp;,
+ * &lt;, &gt;, and &quot;.
+ *
+ * The parser ignores SGML comments and <![CDATA[blocks]]>. Both kinds
+ * of quoting are allowed for attributes.
+ *
+ * The parser deals with invalid markup in these ways:
+ *
+ * - Tag names are not case-sensitive
+ *
+ * - The <html> tag is accepted even when it is not at the top level
+ *
+ * - The <head> tag is accepted even when it is not a direct child of
+ * the <html> tag, but a <html> tag must be an ancestor of the
+ * <head> tag
+ *
+ * - <link> tags are accepted even when they are not direct children
+ * of the <head> tag, but a <head> tag must be an ancestor of the
+ * <link> tag
+ *
+ * - If there is no closing tag for an open <html> or <head> tag, the
+ * remainder of the document is viewed as being inside of the
+ * tag. If there is no closing tag for a <link> tag, the link tag is
+ * treated as a short tag. Exceptions to this rule are that <html>
+ * closes <html> and <body> or <head> closes <head>
+ *
+ * - Attributes of the <link> tag are not required to be quoted.
+ *
+ * - In the case of duplicated attribute names, the attribute coming
+ * last in the tag will be the value returned.
+ *
+ * - Any text that does not parse as an attribute within a link tag
+ * will be ignored. (e.g. <link pumpkin rel='openid.server' /> will
+ * ignore pumpkin)
+ *
+ * - If there are more than one <html> or <head> tag, the parser only
+ * looks inside of the first one.
+ *
+ * - The contents of <script> tags are ignored entirely, except
+ * unclosed <script> tags. Unclosed <script> tags are ignored.
+ *
+ * - Any other invalid markup is ignored, including unclosed SGML
+ * comments and unclosed <![CDATA[blocks.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @access private
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Require Auth_OpenID::arrayGet().
+ */
+require_once "Auth/OpenID.php";
+
+class Auth_OpenID_Parse {
+
+ /**
+ * Specify some flags for use with regex matching.
+ */
+ var $_re_flags = "si";
+
+ /**
+ * Stuff to remove before we start looking for tags
+ */
+ var $_removed_re =
+ "<!--.*?-->|<!\[CDATA\[.*?\]\]>|<script\b(?!:)[^>]*>.*?<\/script>";
+
+ /**
+ * Starts with the tag name at a word boundary, where the tag name
+ * is not a namespace
+ */
+ var $_tag_expr = "<%s\b(?!:)([^>]*?)(?:\/>|>(.*)(?:<\/?%s\s*>|\Z))";
+
+ var $_attr_find = '\b(\w+)=("[^"]*"|\'[^\']*\'|[^\'"\s\/<>]+)';
+
+ var $_open_tag_expr = "<%s\b";
+ var $_close_tag_expr = "<((\/%s\b)|(%s[^>\/]*\/))>";
+
+ function Auth_OpenID_Parse()
+ {
+ $this->_link_find = sprintf("/<link\b(?!:)([^>]*)(?!<)>/%s",
+ $this->_re_flags);
+
+ $this->_entity_replacements = array(
+ 'amp' => '&',
+ 'lt' => '<',
+ 'gt' => '>',
+ 'quot' => '"'
+ );
+
+ $this->_attr_find = sprintf("/%s/%s",
+ $this->_attr_find,
+ $this->_re_flags);
+
+ $this->_removed_re = sprintf("/%s/%s",
+ $this->_removed_re,
+ $this->_re_flags);
+
+ $this->_ent_replace =
+ sprintf("&(%s);", implode("|",
+ $this->_entity_replacements));
+ }
+
+ /**
+ * Returns a regular expression that will match a given tag in an
+ * SGML string.
+ */
+ function tagMatcher($tag_name, $close_tags = null)
+ {
+ $expr = $this->_tag_expr;
+
+ if ($close_tags) {
+ $options = implode("|", array_merge(array($tag_name), $close_tags));
+ $closer = sprintf("(?:%s)", $options);
+ } else {
+ $closer = $tag_name;
+ }
+
+ $expr = sprintf($expr, $tag_name, $closer);
+ return sprintf("/%s/%s", $expr, $this->_re_flags);
+ }
+
+ function openTag($tag_name)
+ {
+ $expr = sprintf($this->_open_tag_expr, $tag_name);
+ return sprintf("/%s/%s", $expr, $this->_re_flags);
+ }
+
+ function closeTag($tag_name)
+ {
+ $expr = sprintf($this->_close_tag_expr, $tag_name, $tag_name);
+ return sprintf("/%s/%s", $expr, $this->_re_flags);
+ }
+
+ function htmlBegin($s)
+ {
+ $matches = array();
+ $result = preg_match($this->openTag('html'), $s,
+ $matches, PREG_OFFSET_CAPTURE);
+ if ($result === false || !$matches) {
+ return false;
+ }
+ // Return the offset of the first match.
+ return $matches[0][1];
+ }
+
+ function htmlEnd($s)
+ {
+ $matches = array();
+ $result = preg_match($this->closeTag('html'), $s,
+ $matches, PREG_OFFSET_CAPTURE);
+ if ($result === false || !$matches) {
+ return false;
+ }
+ // Return the offset of the first match.
+ return $matches[count($matches) - 1][1];
+ }
+
+ function headFind()
+ {
+ return $this->tagMatcher('head', array('body', 'html'));
+ }
+
+ function replaceEntities($str)
+ {
+ foreach ($this->_entity_replacements as $old => $new) {
+ $str = preg_replace(sprintf("/&%s;/", $old), $new, $str);
+ }
+ return $str;
+ }
+
+ function removeQuotes($str)
+ {
+ $matches = array();
+ $double = '/^"(.*)"$/';
+ $single = "/^\'(.*)\'$/";
+
+ if (preg_match($double, $str, $matches)) {
+ return $matches[1];
+ } else if (preg_match($single, $str, $matches)) {
+ return $matches[1];
+ } else {
+ return $str;
+ }
+ }
+
+ function match($regexp, $text, &$match)
+ {
+ if (!is_callable('mb_ereg_search_init')) {
+ if (!preg_match($regexp, $text, $match)) {
+ return false;
+ }
+ $match = $match[0];
+ return true;
+ }
+
+ $regexp = substr($regexp, 1, strlen($regexp) - 2 - strlen($this->_re_flags));
+ mb_ereg_search_init($text);
+ if (!mb_ereg_search($regexp)) {
+ return false;
+ }
+ $match = mb_ereg_search_getregs();
+ return true;
+ }
+
+ /**
+ * Find all link tags in a string representing a HTML document and
+ * return a list of their attributes.
+ *
+ * @todo This is quite ineffective and may fail with the default
+ * pcre.backtrack_limit of 100000 in PHP 5.2, if $html is big.
+ * It should rather use stripos (in PHP5) or strpos()+strtoupper()
+ * in PHP4 to manage this.
+ *
+ * @param string $html The text to parse
+ * @return array $list An array of arrays of attributes, one for each
+ * link tag
+ */
+ function parseLinkAttrs($html)
+ {
+ $stripped = preg_replace($this->_removed_re,
+ "",
+ $html);
+
+ $html_begin = $this->htmlBegin($stripped);
+ $html_end = $this->htmlEnd($stripped);
+
+ if ($html_begin === false) {
+ return array();
+ }
+
+ if ($html_end === false) {
+ $html_end = strlen($stripped);
+ }
+
+ $stripped = substr($stripped, $html_begin,
+ $html_end - $html_begin);
+
+ // Workaround to prevent PREG_BACKTRACK_LIMIT_ERROR:
+ $old_btlimit = ini_set( 'pcre.backtrack_limit', -1 );
+
+ // Try to find the <HEAD> tag.
+ $head_re = $this->headFind();
+ $head_match = array();
+ if (!$this->match($head_re, $stripped, $head_match)) {
+ ini_set( 'pcre.backtrack_limit', $old_btlimit );
+ return array();
+ }
+
+ $link_data = array();
+ $link_matches = array();
+
+ if (!preg_match_all($this->_link_find, $head_match[0],
+ $link_matches)) {
+ ini_set( 'pcre.backtrack_limit', $old_btlimit );
+ return array();
+ }
+
+ foreach ($link_matches[0] as $link) {
+ $attr_matches = array();
+ preg_match_all($this->_attr_find, $link, $attr_matches);
+ $link_attrs = array();
+ foreach ($attr_matches[0] as $index => $full_match) {
+ $name = $attr_matches[1][$index];
+ $value = $this->replaceEntities(
+ $this->removeQuotes($attr_matches[2][$index]));
+
+ $link_attrs[strtolower($name)] = $value;
+ }
+ $link_data[] = $link_attrs;
+ }
+
+ ini_set( 'pcre.backtrack_limit', $old_btlimit );
+ return $link_data;
+ }
+
+ function relMatches($rel_attr, $target_rel)
+ {
+ // Does this target_rel appear in the rel_str?
+ // XXX: TESTME
+ $rels = preg_split("/\s+/", trim($rel_attr));
+ foreach ($rels as $rel) {
+ $rel = strtolower($rel);
+ if ($rel == $target_rel) {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ function linkHasRel($link_attrs, $target_rel)
+ {
+ // Does this link have target_rel as a relationship?
+ // XXX: TESTME
+ $rel_attr = Auth_OpeniD::arrayGet($link_attrs, 'rel', null);
+ return ($rel_attr && $this->relMatches($rel_attr,
+ $target_rel));
+ }
+
+ function findLinksRel($link_attrs_list, $target_rel)
+ {
+ // Filter the list of link attributes on whether it has
+ // target_rel as a relationship.
+ // XXX: TESTME
+ $result = array();
+ foreach ($link_attrs_list as $attr) {
+ if ($this->linkHasRel($attr, $target_rel)) {
+ $result[] = $attr;
+ }
+ }
+
+ return $result;
+ }
+
+ function findFirstHref($link_attrs_list, $target_rel)
+ {
+ // Return the value of the href attribute for the first link
+ // tag in the list that has target_rel as a relationship.
+ // XXX: TESTME
+ $matches = $this->findLinksRel($link_attrs_list,
+ $target_rel);
+ if (!$matches) {
+ return null;
+ }
+ $first = $matches[0];
+ return Auth_OpenID::arrayGet($first, 'href', null);
+ }
+}
+
+function Auth_OpenID_legacy_discover($html_text, $server_rel,
+ $delegate_rel)
+{
+ $p = new Auth_OpenID_Parse();
+
+ $link_attrs = $p->parseLinkAttrs($html_text);
+
+ $server_url = $p->findFirstHref($link_attrs,
+ $server_rel);
+
+ if ($server_url === null) {
+ return false;
+ } else {
+ $delegate_url = $p->findFirstHref($link_attrs,
+ $delegate_rel);
+ return array($delegate_url, $server_url);
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/PostgreSQLStore.php b/plugins/openid/lib/Auth/OpenID/PostgreSQLStore.php
new file mode 100644
index 00000000..d90e43e0
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/PostgreSQLStore.php
@@ -0,0 +1,112 @@
+<?php
+
+/**
+ * A PostgreSQL store.
+ *
+ * @package OpenID
+ */
+
+/**
+ * Require the base class file.
+ */
+require_once "Auth/OpenID/SQLStore.php";
+
+/**
+ * An SQL store that uses PostgreSQL as its backend.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_PostgreSQLStore extends Auth_OpenID_SQLStore {
+ /**
+ * @access private
+ */
+ function setSQL()
+ {
+ $this->sql['nonce_table'] =
+ "CREATE TABLE %s (server_url VARCHAR(2047) NOT NULL, ".
+ "timestamp INTEGER NOT NULL, ".
+ "salt CHAR(40) NOT NULL, ".
+ "UNIQUE (server_url, timestamp, salt))";
+
+ $this->sql['assoc_table'] =
+ "CREATE TABLE %s (server_url VARCHAR(2047) NOT NULL, ".
+ "handle VARCHAR(255) NOT NULL, ".
+ "secret BYTEA NOT NULL, ".
+ "issued INTEGER NOT NULL, ".
+ "lifetime INTEGER NOT NULL, ".
+ "assoc_type VARCHAR(64) NOT NULL, ".
+ "PRIMARY KEY (server_url, handle), ".
+ "CONSTRAINT secret_length_constraint CHECK ".
+ "(LENGTH(secret) <= 128))";
+
+ $this->sql['set_assoc'] =
+ array(
+ 'insert_assoc' => "INSERT INTO %s (server_url, handle, ".
+ "secret, issued, lifetime, assoc_type) VALUES ".
+ "(?, ?, '!', ?, ?, ?)",
+ 'update_assoc' => "UPDATE %s SET secret = '!', issued = ?, ".
+ "lifetime = ?, assoc_type = ? WHERE server_url = ? AND ".
+ "handle = ?"
+ );
+
+ $this->sql['get_assocs'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ?";
+
+ $this->sql['get_assoc'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ? AND handle = ?";
+
+ $this->sql['remove_assoc'] =
+ "DELETE FROM %s WHERE server_url = ? AND handle = ?";
+
+ $this->sql['add_nonce'] =
+ "INSERT INTO %s (server_url, timestamp, salt) VALUES ".
+ "(?, ?, ?)"
+ ;
+
+ $this->sql['clean_nonce'] =
+ "DELETE FROM %s WHERE timestamp < ?";
+
+ $this->sql['clean_assoc'] =
+ "DELETE FROM %s WHERE issued + lifetime < ?";
+ }
+
+ /**
+ * @access private
+ */
+ function _set_assoc($server_url, $handle, $secret, $issued, $lifetime,
+ $assoc_type)
+ {
+ $result = $this->_get_assoc($server_url, $handle);
+ if ($result) {
+ // Update the table since this associations already exists.
+ $this->connection->query($this->sql['set_assoc']['update_assoc'],
+ array($secret, $issued, $lifetime,
+ $assoc_type, $server_url, $handle));
+ } else {
+ // Insert a new record because this association wasn't
+ // found.
+ $this->connection->query($this->sql['set_assoc']['insert_assoc'],
+ array($server_url, $handle, $secret,
+ $issued, $lifetime, $assoc_type));
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function blobEncode($blob)
+ {
+ return $this->_octify($blob);
+ }
+
+ /**
+ * @access private
+ */
+ function blobDecode($blob)
+ {
+ return $this->_unoctify($blob);
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/SQLStore.php b/plugins/openid/lib/Auth/OpenID/SQLStore.php
new file mode 100644
index 00000000..c0405973
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/SQLStore.php
@@ -0,0 +1,557 @@
+<?php
+
+/**
+ * SQL-backed OpenID stores.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/Interface.php';
+require_once 'Auth/OpenID/Nonce.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/Nonce.php';
+
+/**
+ * This is the parent class for the SQL stores, which contains the
+ * logic common to all of the SQL stores.
+ *
+ * The table names used are determined by the class variables
+ * associations_table_name and nonces_table_name. To change the name
+ * of the tables used, pass new table names into the constructor.
+ *
+ * To create the tables with the proper schema, see the createTables
+ * method.
+ *
+ * This class shouldn't be used directly. Use one of its subclasses
+ * instead, as those contain the code necessary to use a specific
+ * database. If you're an OpenID integrator and you'd like to create
+ * an SQL-driven store that wraps an application's database
+ * abstraction, be sure to create a subclass of
+ * {@link Auth_OpenID_DatabaseConnection} that calls the application's
+ * database abstraction calls. Then, pass an instance of your new
+ * database connection class to your SQLStore subclass constructor.
+ *
+ * All methods other than the constructor and createTables should be
+ * considered implementation details.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore {
+
+ /**
+ * This creates a new SQLStore instance. It requires an
+ * established database connection be given to it, and it allows
+ * overriding the default table names.
+ *
+ * @param connection $connection This must be an established
+ * connection to a database of the correct type for the SQLStore
+ * subclass you're using. This must either be an PEAR DB
+ * connection handle or an instance of a subclass of
+ * Auth_OpenID_DatabaseConnection.
+ *
+ * @param associations_table: This is an optional parameter to
+ * specify the name of the table used for storing associations.
+ * The default value is 'oid_associations'.
+ *
+ * @param nonces_table: This is an optional parameter to specify
+ * the name of the table used for storing nonces. The default
+ * value is 'oid_nonces'.
+ */
+ function Auth_OpenID_SQLStore($connection,
+ $associations_table = null,
+ $nonces_table = null)
+ {
+ $this->associations_table_name = "oid_associations";
+ $this->nonces_table_name = "oid_nonces";
+
+ // Check the connection object type to be sure it's a PEAR
+ // database connection.
+ if (!(is_object($connection) &&
+ (is_subclass_of($connection, 'db_common') ||
+ is_subclass_of($connection,
+ 'auth_openid_databaseconnection')))) {
+ trigger_error("Auth_OpenID_SQLStore expected PEAR connection " .
+ "object (got ".get_class($connection).")",
+ E_USER_ERROR);
+ return;
+ }
+
+ $this->connection = $connection;
+
+ // Be sure to set the fetch mode so the results are keyed on
+ // column name instead of column index. This is a PEAR
+ // constant, so only try to use it if PEAR is present. Note
+ // that Auth_Openid_Databaseconnection instances need not
+ // implement ::setFetchMode for this reason.
+ if (is_subclass_of($this->connection, 'db_common')) {
+ $this->connection->setFetchMode(DB_FETCHMODE_ASSOC);
+ }
+
+ if ($associations_table) {
+ $this->associations_table_name = $associations_table;
+ }
+
+ if ($nonces_table) {
+ $this->nonces_table_name = $nonces_table;
+ }
+
+ $this->max_nonce_age = 6 * 60 * 60;
+
+ // Be sure to run the database queries with auto-commit mode
+ // turned OFF, because we want every function to run in a
+ // transaction, implicitly. As a rule, methods named with a
+ // leading underscore will NOT control transaction behavior.
+ // Callers of these methods will worry about transactions.
+ $this->connection->autoCommit(false);
+
+ // Create an empty SQL strings array.
+ $this->sql = array();
+
+ // Call this method (which should be overridden by subclasses)
+ // to populate the $this->sql array with SQL strings.
+ $this->setSQL();
+
+ // Verify that all required SQL statements have been set, and
+ // raise an error if any expected SQL strings were either
+ // absent or empty.
+ list($missing, $empty) = $this->_verifySQL();
+
+ if ($missing) {
+ trigger_error("Expected keys in SQL query list: " .
+ implode(", ", $missing),
+ E_USER_ERROR);
+ return;
+ }
+
+ if ($empty) {
+ trigger_error("SQL list keys have no SQL strings: " .
+ implode(", ", $empty),
+ E_USER_ERROR);
+ return;
+ }
+
+ // Add table names to queries.
+ $this->_fixSQL();
+ }
+
+ function tableExists($table_name)
+ {
+ return !$this->isError(
+ $this->connection->query(
+ sprintf("SELECT * FROM %s LIMIT 0",
+ $table_name)));
+ }
+
+ /**
+ * Returns true if $value constitutes a database error; returns
+ * false otherwise.
+ */
+ function isError($value)
+ {
+ return PEAR::isError($value);
+ }
+
+ /**
+ * Converts a query result to a boolean. If the result is a
+ * database error according to $this->isError(), this returns
+ * false; otherwise, this returns true.
+ */
+ function resultToBool($obj)
+ {
+ if ($this->isError($obj)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * This method should be overridden by subclasses. This method is
+ * called by the constructor to set values in $this->sql, which is
+ * an array keyed on sql name.
+ */
+ function setSQL()
+ {
+ }
+
+ /**
+ * Resets the store by removing all records from the store's
+ * tables.
+ */
+ function reset()
+ {
+ $this->connection->query(sprintf("DELETE FROM %s",
+ $this->associations_table_name));
+
+ $this->connection->query(sprintf("DELETE FROM %s",
+ $this->nonces_table_name));
+ }
+
+ /**
+ * @access private
+ */
+ function _verifySQL()
+ {
+ $missing = array();
+ $empty = array();
+
+ $required_sql_keys = array(
+ 'nonce_table',
+ 'assoc_table',
+ 'set_assoc',
+ 'get_assoc',
+ 'get_assocs',
+ 'remove_assoc'
+ );
+
+ foreach ($required_sql_keys as $key) {
+ if (!array_key_exists($key, $this->sql)) {
+ $missing[] = $key;
+ } else if (!$this->sql[$key]) {
+ $empty[] = $key;
+ }
+ }
+
+ return array($missing, $empty);
+ }
+
+ /**
+ * @access private
+ */
+ function _fixSQL()
+ {
+ $replacements = array(
+ array(
+ 'value' => $this->nonces_table_name,
+ 'keys' => array('nonce_table',
+ 'add_nonce',
+ 'clean_nonce')
+ ),
+ array(
+ 'value' => $this->associations_table_name,
+ 'keys' => array('assoc_table',
+ 'set_assoc',
+ 'get_assoc',
+ 'get_assocs',
+ 'remove_assoc',
+ 'clean_assoc')
+ )
+ );
+
+ foreach ($replacements as $item) {
+ $value = $item['value'];
+ $keys = $item['keys'];
+
+ foreach ($keys as $k) {
+ if (is_array($this->sql[$k])) {
+ foreach ($this->sql[$k] as $part_key => $part_value) {
+ $this->sql[$k][$part_key] = sprintf($part_value,
+ $value);
+ }
+ } else {
+ $this->sql[$k] = sprintf($this->sql[$k], $value);
+ }
+ }
+ }
+ }
+
+ function blobDecode($blob)
+ {
+ return $blob;
+ }
+
+ function blobEncode($str)
+ {
+ return $str;
+ }
+
+ function createTables()
+ {
+ $this->connection->autoCommit(true);
+ $n = $this->create_nonce_table();
+ $a = $this->create_assoc_table();
+ $this->connection->autoCommit(false);
+
+ if ($n && $a) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function create_nonce_table()
+ {
+ if (!$this->tableExists($this->nonces_table_name)) {
+ $r = $this->connection->query($this->sql['nonce_table']);
+ return $this->resultToBool($r);
+ }
+ return true;
+ }
+
+ function create_assoc_table()
+ {
+ if (!$this->tableExists($this->associations_table_name)) {
+ $r = $this->connection->query($this->sql['assoc_table']);
+ return $this->resultToBool($r);
+ }
+ return true;
+ }
+
+ /**
+ * @access private
+ */
+ function _set_assoc($server_url, $handle, $secret, $issued,
+ $lifetime, $assoc_type)
+ {
+ return $this->connection->query($this->sql['set_assoc'],
+ array(
+ $server_url,
+ $handle,
+ $secret,
+ $issued,
+ $lifetime,
+ $assoc_type));
+ }
+
+ function storeAssociation($server_url, $association)
+ {
+ if ($this->resultToBool($this->_set_assoc(
+ $server_url,
+ $association->handle,
+ $this->blobEncode(
+ $association->secret),
+ $association->issued,
+ $association->lifetime,
+ $association->assoc_type
+ ))) {
+ $this->connection->commit();
+ } else {
+ $this->connection->rollback();
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _get_assoc($server_url, $handle)
+ {
+ $result = $this->connection->getRow($this->sql['get_assoc'],
+ array($server_url, $handle));
+ if ($this->isError($result)) {
+ return null;
+ } else {
+ return $result;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _get_assocs($server_url)
+ {
+ $result = $this->connection->getAll($this->sql['get_assocs'],
+ array($server_url));
+
+ if ($this->isError($result)) {
+ return array();
+ } else {
+ return $result;
+ }
+ }
+
+ function removeAssociation($server_url, $handle)
+ {
+ if ($this->_get_assoc($server_url, $handle) == null) {
+ return false;
+ }
+
+ if ($this->resultToBool($this->connection->query(
+ $this->sql['remove_assoc'],
+ array($server_url, $handle)))) {
+ $this->connection->commit();
+ } else {
+ $this->connection->rollback();
+ }
+
+ return true;
+ }
+
+ function getAssociation($server_url, $handle = null)
+ {
+ if ($handle !== null) {
+ $assoc = $this->_get_assoc($server_url, $handle);
+
+ $assocs = array();
+ if ($assoc) {
+ $assocs[] = $assoc;
+ }
+ } else {
+ $assocs = $this->_get_assocs($server_url);
+ }
+
+ if (!$assocs || (count($assocs) == 0)) {
+ return null;
+ } else {
+ $associations = array();
+
+ foreach ($assocs as $assoc_row) {
+ $assoc = new Auth_OpenID_Association($assoc_row['handle'],
+ $assoc_row['secret'],
+ $assoc_row['issued'],
+ $assoc_row['lifetime'],
+ $assoc_row['assoc_type']);
+
+ $assoc->secret = $this->blobDecode($assoc->secret);
+
+ if ($assoc->getExpiresIn() == 0) {
+ $this->removeAssociation($server_url, $assoc->handle);
+ } else {
+ $associations[] = array($assoc->issued, $assoc);
+ }
+ }
+
+ if ($associations) {
+ $issued = array();
+ $assocs = array();
+ foreach ($associations as $key => $assoc) {
+ $issued[$key] = $assoc[0];
+ $assocs[$key] = $assoc[1];
+ }
+
+ array_multisort($issued, SORT_DESC, $assocs, SORT_DESC,
+ $associations);
+
+ // return the most recently issued one.
+ list($issued, $assoc) = $associations[0];
+ return $assoc;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _add_nonce($server_url, $timestamp, $salt)
+ {
+ $sql = $this->sql['add_nonce'];
+ $result = $this->connection->query($sql, array($server_url,
+ $timestamp,
+ $salt));
+ if ($this->isError($result)) {
+ $this->connection->rollback();
+ } else {
+ $this->connection->commit();
+ }
+ return $this->resultToBool($result);
+ }
+
+ function useNonce($server_url, $timestamp, $salt)
+ {
+ global $Auth_OpenID_SKEW;
+
+ if ( abs($timestamp - time()) > $Auth_OpenID_SKEW ) {
+ return false;
+ }
+
+ return $this->_add_nonce($server_url, $timestamp, $salt);
+ }
+
+ /**
+ * "Octifies" a binary string by returning a string with escaped
+ * octal bytes. This is used for preparing binary data for
+ * PostgreSQL BYTEA fields.
+ *
+ * @access private
+ */
+ function _octify($str)
+ {
+ $result = "";
+ for ($i = 0; $i < Auth_OpenID::bytes($str); $i++) {
+ $ch = substr($str, $i, 1);
+ if ($ch == "\\") {
+ $result .= "\\\\\\\\";
+ } else if (ord($ch) == 0) {
+ $result .= "\\\\000";
+ } else {
+ $result .= "\\" . strval(decoct(ord($ch)));
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * "Unoctifies" octal-escaped data from PostgreSQL and returns the
+ * resulting ASCII (possibly binary) string.
+ *
+ * @access private
+ */
+ function _unoctify($str)
+ {
+ $result = "";
+ $i = 0;
+ while ($i < strlen($str)) {
+ $char = $str[$i];
+ if ($char == "\\") {
+ // Look to see if the next char is a backslash and
+ // append it.
+ if ($str[$i + 1] != "\\") {
+ $octal_digits = substr($str, $i + 1, 3);
+ $dec = octdec($octal_digits);
+ $char = chr($dec);
+ $i += 4;
+ } else {
+ $char = "\\";
+ $i += 2;
+ }
+ } else {
+ $i += 1;
+ }
+
+ $result .= $char;
+ }
+
+ return $result;
+ }
+
+ function cleanupNonces()
+ {
+ global $Auth_OpenID_SKEW;
+ $v = time() - $Auth_OpenID_SKEW;
+
+ $this->connection->query($this->sql['clean_nonce'], array($v));
+ $num = $this->connection->affectedRows();
+ $this->connection->commit();
+ return $num;
+ }
+
+ function cleanupAssociations()
+ {
+ $this->connection->query($this->sql['clean_assoc'],
+ array(time()));
+ $num = $this->connection->affectedRows();
+ $this->connection->commit();
+ return $num;
+ }
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/SQLiteStore.php b/plugins/openid/lib/Auth/OpenID/SQLiteStore.php
new file mode 100644
index 00000000..4558fa1c
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/SQLiteStore.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * An SQLite store.
+ *
+ * @package OpenID
+ */
+
+/**
+ * Require the base class file.
+ */
+require_once "Auth/OpenID/SQLStore.php";
+
+/**
+ * An SQL store that uses SQLite as its backend.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SQLiteStore extends Auth_OpenID_SQLStore {
+ function setSQL()
+ {
+ $this->sql['nonce_table'] =
+ "CREATE TABLE %s (server_url VARCHAR(2047), timestamp INTEGER, ".
+ "salt CHAR(40), UNIQUE (server_url, timestamp, salt))";
+
+ $this->sql['assoc_table'] =
+ "CREATE TABLE %s (server_url VARCHAR(2047), handle VARCHAR(255), ".
+ "secret BLOB(128), issued INTEGER, lifetime INTEGER, ".
+ "assoc_type VARCHAR(64), PRIMARY KEY (server_url, handle))";
+
+ $this->sql['set_assoc'] =
+ "INSERT OR REPLACE INTO %s VALUES (?, ?, ?, ?, ?, ?)";
+
+ $this->sql['get_assocs'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ?";
+
+ $this->sql['get_assoc'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ? AND handle = ?";
+
+ $this->sql['remove_assoc'] =
+ "DELETE FROM %s WHERE server_url = ? AND handle = ?";
+
+ $this->sql['add_nonce'] =
+ "INSERT INTO %s (server_url, timestamp, salt) VALUES (?, ?, ?)";
+
+ $this->sql['clean_nonce'] =
+ "DELETE FROM %s WHERE timestamp < ?";
+
+ $this->sql['clean_assoc'] =
+ "DELETE FROM %s WHERE issued + lifetime < ?";
+ }
+
+ /**
+ * @access private
+ */
+ function _add_nonce($server_url, $timestamp, $salt)
+ {
+ // PECL SQLite extensions 1.0.3 and older (1.0.3 is the
+ // current release at the time of this writing) have a broken
+ // sqlite_escape_string function that breaks when passed the
+ // empty string. Prefixing all strings with one character
+ // keeps them unique and avoids this bug. The nonce table is
+ // write-only, so we don't have to worry about updating other
+ // functions with this same bad hack.
+ return parent::_add_nonce('x' . $server_url, $timestamp, $salt);
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/SReg.php b/plugins/openid/lib/Auth/OpenID/SReg.php
new file mode 100644
index 00000000..5ece7072
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/SReg.php
@@ -0,0 +1,521 @@
+<?php
+
+/**
+ * Simple registration request and response parsing and object
+ * representation.
+ *
+ * This module contains objects representing simple registration
+ * requests and responses that can be used with both OpenID relying
+ * parties and OpenID providers.
+ *
+ * 1. The relying party creates a request object and adds it to the
+ * {@link Auth_OpenID_AuthRequest} object before making the
+ * checkid request to the OpenID provider:
+ *
+ * $sreg_req = Auth_OpenID_SRegRequest::build(array('email'));
+ * $auth_request->addExtension($sreg_req);
+ *
+ * 2. The OpenID provider extracts the simple registration request
+ * from the OpenID request using {@link
+ * Auth_OpenID_SRegRequest::fromOpenIDRequest}, gets the user's
+ * approval and data, creates an {@link Auth_OpenID_SRegResponse}
+ * object and adds it to the id_res response:
+ *
+ * $sreg_req = Auth_OpenID_SRegRequest::fromOpenIDRequest(
+ * $checkid_request);
+ * // [ get the user's approval and data, informing the user that
+ * // the fields in sreg_response were requested ]
+ * $sreg_resp = Auth_OpenID_SRegResponse::extractResponse(
+ * $sreg_req, $user_data);
+ * $sreg_resp->toMessage($openid_response->fields);
+ *
+ * 3. The relying party uses {@link
+ * Auth_OpenID_SRegResponse::fromSuccessResponse} to extract the data
+ * from the OpenID response:
+ *
+ * $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse(
+ * $success_response);
+ *
+ * @package OpenID
+ */
+
+/**
+ * Import message and extension internals.
+ */
+require_once 'Auth/OpenID/Message.php';
+require_once 'Auth/OpenID/Extension.php';
+
+// The data fields that are listed in the sreg spec
+global $Auth_OpenID_sreg_data_fields;
+$Auth_OpenID_sreg_data_fields = array(
+ 'fullname' => 'Full Name',
+ 'nickname' => 'Nickname',
+ 'dob' => 'Date of Birth',
+ 'email' => 'E-mail Address',
+ 'gender' => 'Gender',
+ 'postcode' => 'Postal Code',
+ 'country' => 'Country',
+ 'language' => 'Language',
+ 'timezone' => 'Time Zone');
+
+/**
+ * Check to see that the given value is a valid simple registration
+ * data field name. Return true if so, false if not.
+ */
+function Auth_OpenID_checkFieldName($field_name)
+{
+ global $Auth_OpenID_sreg_data_fields;
+
+ if (!in_array($field_name, array_keys($Auth_OpenID_sreg_data_fields))) {
+ return false;
+ }
+ return true;
+}
+
+// URI used in the wild for Yadis documents advertising simple
+// registration support
+define('Auth_OpenID_SREG_NS_URI_1_0', 'http://openid.net/sreg/1.0');
+
+// URI in the draft specification for simple registration 1.1
+// <http://openid.net/specs/openid-simple-registration-extension-1_1-01.html>
+define('Auth_OpenID_SREG_NS_URI_1_1', 'http://openid.net/extensions/sreg/1.1');
+
+// This attribute will always hold the preferred URI to use when
+// adding sreg support to an XRDS file or in an OpenID namespace
+// declaration.
+define('Auth_OpenID_SREG_NS_URI', Auth_OpenID_SREG_NS_URI_1_1);
+
+Auth_OpenID_registerNamespaceAlias(Auth_OpenID_SREG_NS_URI_1_1, 'sreg');
+
+/**
+ * Does the given endpoint advertise support for simple
+ * registration?
+ *
+ * $endpoint: The endpoint object as returned by OpenID discovery.
+ * returns whether an sreg type was advertised by the endpoint
+ */
+function Auth_OpenID_supportsSReg($endpoint)
+{
+ return ($endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_1) ||
+ $endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_0));
+}
+
+/**
+ * A base class for classes dealing with Simple Registration protocol
+ * messages.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SRegBase extends Auth_OpenID_Extension {
+ /**
+ * Extract the simple registration namespace URI from the given
+ * OpenID message. Handles OpenID 1 and 2, as well as both sreg
+ * namespace URIs found in the wild, as well as missing namespace
+ * definitions (for OpenID 1)
+ *
+ * $message: The OpenID message from which to parse simple
+ * registration fields. This may be a request or response message.
+ *
+ * Returns the sreg namespace URI for the supplied message. The
+ * message may be modified to define a simple registration
+ * namespace.
+ *
+ * @access private
+ */
+ static function _getSRegNS($message)
+ {
+ $alias = null;
+ $found_ns_uri = null;
+
+ // See if there exists an alias for one of the two defined
+ // simple registration types.
+ foreach (array(Auth_OpenID_SREG_NS_URI_1_1,
+ Auth_OpenID_SREG_NS_URI_1_0) as $sreg_ns_uri) {
+ $alias = $message->namespaces->getAlias($sreg_ns_uri);
+ if ($alias !== null) {
+ $found_ns_uri = $sreg_ns_uri;
+ break;
+ }
+ }
+
+ if ($alias === null) {
+ // There is no alias for either of the types, so try to
+ // add one. We default to using the modern value (1.1)
+ $found_ns_uri = Auth_OpenID_SREG_NS_URI_1_1;
+ if ($message->namespaces->addAlias(Auth_OpenID_SREG_NS_URI_1_1,
+ 'sreg') === null) {
+ // An alias for the string 'sreg' already exists, but
+ // it's defined for something other than simple
+ // registration
+ return null;
+ }
+ }
+
+ return $found_ns_uri;
+ }
+}
+
+/**
+ * An object to hold the state of a simple registration request.
+ *
+ * required: A list of the required fields in this simple registration
+ * request
+ *
+ * optional: A list of the optional fields in this simple registration
+ * request
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase {
+
+ var $ns_alias = 'sreg';
+
+ /**
+ * Initialize an empty simple registration request.
+ */
+ static function build($required=null, $optional=null,
+ $policy_url=null,
+ $sreg_ns_uri=Auth_OpenID_SREG_NS_URI,
+ $cls='Auth_OpenID_SRegRequest')
+ {
+ $obj = new $cls();
+
+ $obj->required = array();
+ $obj->optional = array();
+ $obj->policy_url = $policy_url;
+ $obj->ns_uri = $sreg_ns_uri;
+
+ if ($required) {
+ if (!$obj->requestFields($required, true, true)) {
+ return null;
+ }
+ }
+
+ if ($optional) {
+ if (!$obj->requestFields($optional, false, true)) {
+ return null;
+ }
+ }
+
+ return $obj;
+ }
+
+ /**
+ * Create a simple registration request that contains the fields
+ * that were requested in the OpenID request with the given
+ * arguments
+ *
+ * $request: The OpenID authentication request from which to
+ * extract an sreg request.
+ *
+ * $cls: name of class to use when creating sreg request object.
+ * Used for testing.
+ *
+ * Returns the newly created simple registration request
+ */
+ static function fromOpenIDRequest($request, $cls='Auth_OpenID_SRegRequest')
+ {
+
+ $obj = call_user_func_array(array($cls, 'build'),
+ array(null, null, null, Auth_OpenID_SREG_NS_URI, $cls));
+
+ // Since we're going to mess with namespace URI mapping, don't
+ // mutate the object that was passed in.
+ $m = $request->message;
+
+ $obj->ns_uri = $obj->_getSRegNS($m);
+ $args = $m->getArgs($obj->ns_uri);
+
+ if ($args === null || Auth_OpenID::isFailure($args)) {
+ return null;
+ }
+
+ $obj->parseExtensionArgs($args);
+
+ return $obj;
+ }
+
+ /**
+ * Parse the unqualified simple registration request parameters
+ * and add them to this object.
+ *
+ * This method is essentially the inverse of
+ * getExtensionArgs. This method restores the serialized simple
+ * registration request fields.
+ *
+ * If you are extracting arguments from a standard OpenID
+ * checkid_* request, you probably want to use fromOpenIDRequest,
+ * which will extract the sreg namespace and arguments from the
+ * OpenID request. This method is intended for cases where the
+ * OpenID server needs more control over how the arguments are
+ * parsed than that method provides.
+ *
+ * $args == $message->getArgs($ns_uri);
+ * $request->parseExtensionArgs($args);
+ *
+ * $args: The unqualified simple registration arguments
+ *
+ * strict: Whether requests with fields that are not defined in
+ * the simple registration specification should be tolerated (and
+ * ignored)
+ */
+ function parseExtensionArgs($args, $strict=false)
+ {
+ foreach (array('required', 'optional') as $list_name) {
+ $required = ($list_name == 'required');
+ $items = Auth_OpenID::arrayGet($args, $list_name);
+ if ($items) {
+ foreach (explode(',', $items) as $field_name) {
+ if (!$this->requestField($field_name, $required, $strict)) {
+ if ($strict) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ $this->policy_url = Auth_OpenID::arrayGet($args, 'policy_url');
+
+ return true;
+ }
+
+ /**
+ * A list of all of the simple registration fields that were
+ * requested, whether they were required or optional.
+ */
+ function allRequestedFields()
+ {
+ return array_merge($this->required, $this->optional);
+ }
+
+ /**
+ * Have any simple registration fields been requested?
+ */
+ function wereFieldsRequested()
+ {
+ return count($this->allRequestedFields());
+ }
+
+ /**
+ * Was this field in the request?
+ */
+ function contains($field_name)
+ {
+ return (in_array($field_name, $this->required) ||
+ in_array($field_name, $this->optional));
+ }
+
+ /**
+ * Request the specified field from the OpenID user
+ *
+ * $field_name: the unqualified simple registration field name
+ *
+ * required: whether the given field should be presented to the
+ * user as being a required to successfully complete the request
+ *
+ * strict: whether to raise an exception when a field is added to
+ * a request more than once
+ */
+ function requestField($field_name,
+ $required=false, $strict=false)
+ {
+ if (!Auth_OpenID_checkFieldName($field_name)) {
+ return false;
+ }
+
+ if ($strict) {
+ if ($this->contains($field_name)) {
+ return false;
+ }
+ } else {
+ if (in_array($field_name, $this->required)) {
+ return true;
+ }
+
+ if (in_array($field_name, $this->optional)) {
+ if ($required) {
+ unset($this->optional[array_search($field_name,
+ $this->optional)]);
+ } else {
+ return true;
+ }
+ }
+ }
+
+ if ($required) {
+ $this->required[] = $field_name;
+ } else {
+ $this->optional[] = $field_name;
+ }
+
+ return true;
+ }
+
+ /**
+ * Add the given list of fields to the request
+ *
+ * field_names: The simple registration data fields to request
+ *
+ * required: Whether these values should be presented to the user
+ * as required
+ *
+ * strict: whether to raise an exception when a field is added to
+ * a request more than once
+ */
+ function requestFields($field_names, $required=false, $strict=false)
+ {
+ if (!is_array($field_names)) {
+ return false;
+ }
+
+ foreach ($field_names as $field_name) {
+ if (!$this->requestField($field_name, $required, $strict=$strict)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Get a dictionary of unqualified simple registration arguments
+ * representing this request.
+ *
+ * This method is essentially the inverse of
+ * C{L{parseExtensionArgs}}. This method serializes the simple
+ * registration request fields.
+ */
+ function getExtensionArgs()
+ {
+ $args = array();
+
+ if ($this->required) {
+ $args['required'] = implode(',', $this->required);
+ }
+
+ if ($this->optional) {
+ $args['optional'] = implode(',', $this->optional);
+ }
+
+ if ($this->policy_url) {
+ $args['policy_url'] = $this->policy_url;
+ }
+
+ return $args;
+ }
+}
+
+/**
+ * Represents the data returned in a simple registration response
+ * inside of an OpenID C{id_res} response. This object will be created
+ * by the OpenID server, added to the C{id_res} response object, and
+ * then extracted from the C{id_res} message by the Consumer.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase {
+
+ var $ns_alias = 'sreg';
+
+ function Auth_OpenID_SRegResponse($data=null,
+ $sreg_ns_uri=Auth_OpenID_SREG_NS_URI)
+ {
+ if ($data === null) {
+ $this->data = array();
+ } else {
+ $this->data = $data;
+ }
+
+ $this->ns_uri = $sreg_ns_uri;
+ }
+
+ /**
+ * Take a C{L{SRegRequest}} and a dictionary of simple
+ * registration values and create a C{L{SRegResponse}} object
+ * containing that data.
+ *
+ * request: The simple registration request object
+ *
+ * data: The simple registration data for this response, as a
+ * dictionary from unqualified simple registration field name to
+ * string (unicode) value. For instance, the nickname should be
+ * stored under the key 'nickname'.
+ */
+ static function extractResponse($request, $data)
+ {
+ $obj = new Auth_OpenID_SRegResponse();
+ $obj->ns_uri = $request->ns_uri;
+
+ foreach ($request->allRequestedFields() as $field) {
+ $value = Auth_OpenID::arrayGet($data, $field);
+ if ($value !== null) {
+ $obj->data[$field] = $value;
+ }
+ }
+
+ return $obj;
+ }
+
+ /**
+ * Create a C{L{SRegResponse}} object from a successful OpenID
+ * library response
+ * (C{L{openid.consumer.consumer.SuccessResponse}}) response
+ * message
+ *
+ * success_response: A SuccessResponse from consumer.complete()
+ *
+ * signed_only: Whether to process only data that was
+ * signed in the id_res message from the server.
+ *
+ * Returns a simple registration response containing the data that
+ * was supplied with the C{id_res} response.
+ */
+ static function fromSuccessResponse($success_response, $signed_only=true)
+ {
+ global $Auth_OpenID_sreg_data_fields;
+
+ $obj = new Auth_OpenID_SRegResponse();
+ $obj->ns_uri = $obj->_getSRegNS($success_response->message);
+
+ if ($signed_only) {
+ $args = $success_response->getSignedNS($obj->ns_uri);
+ } else {
+ $args = $success_response->message->getArgs($obj->ns_uri);
+ }
+
+ if ($args === null || Auth_OpenID::isFailure($args)) {
+ return null;
+ }
+
+ foreach ($Auth_OpenID_sreg_data_fields as $field_name => $desc) {
+ if (in_array($field_name, array_keys($args))) {
+ $obj->data[$field_name] = $args[$field_name];
+ }
+ }
+
+ return $obj;
+ }
+
+ function getExtensionArgs()
+ {
+ return $this->data;
+ }
+
+ // Read-only dictionary interface
+ function get($field_name, $default=null)
+ {
+ if (!Auth_OpenID_checkFieldName($field_name)) {
+ return null;
+ }
+
+ return Auth_OpenID::arrayGet($this->data, $field_name, $default);
+ }
+
+ function contents()
+ {
+ return $this->data;
+ }
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/Server.php b/plugins/openid/lib/Auth/OpenID/Server.php
new file mode 100644
index 00000000..9887d1e8
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/Server.php
@@ -0,0 +1,1765 @@
+<?php
+
+/**
+ * OpenID server protocol and logic.
+ *
+ * Overview
+ *
+ * An OpenID server must perform three tasks:
+ *
+ * 1. Examine the incoming request to determine its nature and validity.
+ * 2. Make a decision about how to respond to this request.
+ * 3. Format the response according to the protocol.
+ *
+ * The first and last of these tasks may performed by the {@link
+ * Auth_OpenID_Server::decodeRequest()} and {@link
+ * Auth_OpenID_Server::encodeResponse} methods. Who gets to do the
+ * intermediate task -- deciding how to respond to the request -- will
+ * depend on what type of request it is.
+ *
+ * If it's a request to authenticate a user (a 'checkid_setup' or
+ * 'checkid_immediate' request), you need to decide if you will assert
+ * that this user may claim the identity in question. Exactly how you
+ * do that is a matter of application policy, but it generally
+ * involves making sure the user has an account with your system and
+ * is logged in, checking to see if that identity is hers to claim,
+ * and verifying with the user that she does consent to releasing that
+ * information to the party making the request.
+ *
+ * Examine the properties of the {@link Auth_OpenID_CheckIDRequest}
+ * object, and if and when you've come to a decision, form a response
+ * by calling {@link Auth_OpenID_CheckIDRequest::answer()}.
+ *
+ * Other types of requests relate to establishing associations between
+ * client and server and verifing the authenticity of previous
+ * communications. {@link Auth_OpenID_Server} contains all the logic
+ * and data necessary to respond to such requests; just pass it to
+ * {@link Auth_OpenID_Server::handleRequest()}.
+ *
+ * OpenID Extensions
+ *
+ * Do you want to provide other information for your users in addition
+ * to authentication? Version 1.2 of the OpenID protocol allows
+ * consumers to add extensions to their requests. For example, with
+ * sites using the Simple Registration
+ * Extension
+ * (http://openid.net/specs/openid-simple-registration-extension-1_0.html),
+ * a user can agree to have their nickname and e-mail address sent to
+ * a site when they sign up.
+ *
+ * Since extensions do not change the way OpenID authentication works,
+ * code to handle extension requests may be completely separate from
+ * the {@link Auth_OpenID_Request} class here. But you'll likely want
+ * data sent back by your extension to be signed. {@link
+ * Auth_OpenID_ServerResponse} provides methods with which you can add
+ * data to it which can be signed with the other data in the OpenID
+ * signature.
+ *
+ * For example:
+ *
+ * <pre> // when request is a checkid_* request
+ * $response = $request->answer(true);
+ * // this will a signed 'openid.sreg.timezone' parameter to the response
+ * response.addField('sreg', 'timezone', 'America/Los_Angeles')</pre>
+ *
+ * Stores
+ *
+ * The OpenID server needs to maintain state between requests in order
+ * to function. Its mechanism for doing this is called a store. The
+ * store interface is defined in Interface.php. Additionally, several
+ * concrete store implementations are provided, so that most sites
+ * won't need to implement a custom store. For a store backed by flat
+ * files on disk, see {@link Auth_OpenID_FileStore}. For stores based
+ * on MySQL, SQLite, or PostgreSQL, see the {@link
+ * Auth_OpenID_SQLStore} subclasses.
+ *
+ * Upgrading
+ *
+ * The keys by which a server looks up associations in its store have
+ * changed in version 1.2 of this library. If your store has entries
+ * created from version 1.0 code, you should empty it.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Required imports
+ */
+require_once "Auth/OpenID.php";
+require_once "Auth/OpenID/Association.php";
+require_once "Auth/OpenID/CryptUtil.php";
+require_once "Auth/OpenID/BigMath.php";
+require_once "Auth/OpenID/DiffieHellman.php";
+require_once "Auth/OpenID/KVForm.php";
+require_once "Auth/OpenID/TrustRoot.php";
+require_once "Auth/OpenID/ServerRequest.php";
+require_once "Auth/OpenID/Message.php";
+require_once "Auth/OpenID/Nonce.php";
+
+define('AUTH_OPENID_HTTP_OK', 200);
+define('AUTH_OPENID_HTTP_REDIRECT', 302);
+define('AUTH_OPENID_HTTP_ERROR', 400);
+
+/**
+ * @access private
+ */
+global $_Auth_OpenID_Request_Modes;
+$_Auth_OpenID_Request_Modes = array('checkid_setup',
+ 'checkid_immediate');
+
+/**
+ * @access private
+ */
+define('Auth_OpenID_ENCODE_KVFORM', 'kfvorm');
+
+/**
+ * @access private
+ */
+define('Auth_OpenID_ENCODE_URL', 'URL/redirect');
+
+/**
+ * @access private
+ */
+define('Auth_OpenID_ENCODE_HTML_FORM', 'HTML form');
+
+/**
+ * @access private
+ */
+function Auth_OpenID_isError($obj, $cls = 'Auth_OpenID_ServerError')
+{
+ return is_a($obj, $cls);
+}
+
+/**
+ * An error class which gets instantiated and returned whenever an
+ * OpenID protocol error occurs. Be prepared to use this in place of
+ * an ordinary server response.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_ServerError {
+ /**
+ * @access private
+ */
+ function Auth_OpenID_ServerError($message = null, $text = null,
+ $reference = null, $contact = null)
+ {
+ $this->message = $message;
+ $this->text = $text;
+ $this->contact = $contact;
+ $this->reference = $reference;
+ }
+
+ function getReturnTo()
+ {
+ if ($this->message &&
+ $this->message->hasKey(Auth_OpenID_OPENID_NS, 'return_to')) {
+ return $this->message->getArg(Auth_OpenID_OPENID_NS,
+ 'return_to');
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the return_to URL for the request which caused this
+ * error.
+ */
+ function hasReturnTo()
+ {
+ return $this->getReturnTo() !== null;
+ }
+
+ /**
+ * Encodes this error's response as a URL suitable for
+ * redirection. If the response has no return_to, another
+ * Auth_OpenID_ServerError is returned.
+ */
+ function encodeToURL()
+ {
+ if (!$this->message) {
+ return null;
+ }
+
+ $msg = $this->toMessage();
+ return $msg->toURL($this->getReturnTo());
+ }
+
+ /**
+ * Encodes the response to key-value form. This is a
+ * machine-readable format used to respond to messages which came
+ * directly from the consumer and not through the user-agent. See
+ * the OpenID specification.
+ */
+ function encodeToKVForm()
+ {
+ return Auth_OpenID_KVForm::fromArray(
+ array('mode' => 'error',
+ 'error' => $this->toString()));
+ }
+
+ function toFormMarkup($form_tag_attrs=null)
+ {
+ $msg = $this->toMessage();
+ return $msg->toFormMarkup($this->getReturnTo(), $form_tag_attrs);
+ }
+
+ function toHTML($form_tag_attrs=null)
+ {
+ return Auth_OpenID::autoSubmitHTML(
+ $this->toFormMarkup($form_tag_attrs));
+ }
+
+ function toMessage()
+ {
+ // Generate a Message object for sending to the relying party,
+ // after encoding.
+ $namespace = $this->message->getOpenIDNamespace();
+ $reply = new Auth_OpenID_Message($namespace);
+ $reply->setArg(Auth_OpenID_OPENID_NS, 'mode', 'error');
+ $reply->setArg(Auth_OpenID_OPENID_NS, 'error', $this->toString());
+
+ if ($this->contact !== null) {
+ $reply->setArg(Auth_OpenID_OPENID_NS, 'contact', $this->contact);
+ }
+
+ if ($this->reference !== null) {
+ $reply->setArg(Auth_OpenID_OPENID_NS, 'reference',
+ $this->reference);
+ }
+
+ return $reply;
+ }
+
+ /**
+ * Returns one of Auth_OpenID_ENCODE_URL,
+ * Auth_OpenID_ENCODE_KVFORM, or null, depending on the type of
+ * encoding expected for this error's payload.
+ */
+ function whichEncoding()
+ {
+ global $_Auth_OpenID_Request_Modes;
+
+ if ($this->hasReturnTo()) {
+ if ($this->message->isOpenID2() &&
+ (strlen($this->encodeToURL()) >
+ Auth_OpenID_OPENID1_URL_LIMIT)) {
+ return Auth_OpenID_ENCODE_HTML_FORM;
+ } else {
+ return Auth_OpenID_ENCODE_URL;
+ }
+ }
+
+ if (!$this->message) {
+ return null;
+ }
+
+ $mode = $this->message->getArg(Auth_OpenID_OPENID_NS,
+ 'mode');
+
+ if ($mode) {
+ if (!in_array($mode, $_Auth_OpenID_Request_Modes)) {
+ return Auth_OpenID_ENCODE_KVFORM;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns this error message.
+ */
+ function toString()
+ {
+ if ($this->text) {
+ return $this->text;
+ } else {
+ return get_class($this) . " error";
+ }
+ }
+}
+
+/**
+ * Error returned by the server code when a return_to is absent from a
+ * request.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_NoReturnToError extends Auth_OpenID_ServerError {
+ function Auth_OpenID_NoReturnToError($message = null,
+ $text = "No return_to URL available")
+ {
+ parent::Auth_OpenID_ServerError($message, $text);
+ }
+
+ function toString()
+ {
+ return "No return_to available";
+ }
+}
+
+/**
+ * An error indicating that the return_to URL is malformed.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_MalformedReturnURL extends Auth_OpenID_ServerError {
+ function Auth_OpenID_MalformedReturnURL($message, $return_to)
+ {
+ $this->return_to = $return_to;
+ parent::Auth_OpenID_ServerError($message, "malformed return_to URL");
+ }
+}
+
+/**
+ * This error is returned when the trust_root value is malformed.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_MalformedTrustRoot extends Auth_OpenID_ServerError {
+ function Auth_OpenID_MalformedTrustRoot($message = null,
+ $text = "Malformed trust root")
+ {
+ parent::Auth_OpenID_ServerError($message, $text);
+ }
+
+ function toString()
+ {
+ return "Malformed trust root";
+ }
+}
+
+/**
+ * The base class for all server request classes.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Request {
+ var $mode = null;
+}
+
+/**
+ * A request to verify the validity of a previous response.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request {
+ var $mode = "check_authentication";
+ var $invalidate_handle = null;
+
+ function Auth_OpenID_CheckAuthRequest($assoc_handle, $signed,
+ $invalidate_handle = null)
+ {
+ $this->assoc_handle = $assoc_handle;
+ $this->signed = $signed;
+ if ($invalidate_handle !== null) {
+ $this->invalidate_handle = $invalidate_handle;
+ }
+ $this->namespace = Auth_OpenID_OPENID2_NS;
+ $this->message = null;
+ }
+
+ static function fromMessage($message, $server=null)
+ {
+ $required_keys = array('assoc_handle', 'sig', 'signed');
+
+ foreach ($required_keys as $k) {
+ if (!$message->getArg(Auth_OpenID_OPENID_NS, $k)) {
+ return new Auth_OpenID_ServerError($message,
+ sprintf("%s request missing required parameter %s from \
+ query", "check_authentication", $k));
+ }
+ }
+
+ $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS, 'assoc_handle');
+ $sig = $message->getArg(Auth_OpenID_OPENID_NS, 'sig');
+
+ $signed_list = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
+ $signed_list = explode(",", $signed_list);
+
+ $signed = $message;
+ if ($signed->hasKey(Auth_OpenID_OPENID_NS, 'mode')) {
+ $signed->setArg(Auth_OpenID_OPENID_NS, 'mode', 'id_res');
+ }
+
+ $result = new Auth_OpenID_CheckAuthRequest($assoc_handle, $signed);
+ $result->message = $message;
+ $result->sig = $sig;
+ $result->invalidate_handle = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'invalidate_handle');
+ return $result;
+ }
+
+ function answer($signatory)
+ {
+ $is_valid = $signatory->verify($this->assoc_handle, $this->signed);
+
+ // Now invalidate that assoc_handle so it this checkAuth
+ // message cannot be replayed.
+ $signatory->invalidate($this->assoc_handle, true);
+ $response = new Auth_OpenID_ServerResponse($this);
+
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'is_valid',
+ ($is_valid ? "true" : "false"));
+
+ if ($this->invalidate_handle) {
+ $assoc = $signatory->getAssociation($this->invalidate_handle,
+ false);
+ if (!$assoc) {
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'invalidate_handle',
+ $this->invalidate_handle);
+ }
+ }
+ return $response;
+ }
+}
+
+/**
+ * A class implementing plaintext server sessions.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_PlainTextServerSession {
+ /**
+ * An object that knows how to handle association requests with no
+ * session type.
+ */
+ var $session_type = 'no-encryption';
+ var $needs_math = false;
+ var $allowed_assoc_types = array('HMAC-SHA1', 'HMAC-SHA256');
+
+ static function fromMessage($unused_request)
+ {
+ return new Auth_OpenID_PlainTextServerSession();
+ }
+
+ function answer($secret)
+ {
+ return array('mac_key' => base64_encode($secret));
+ }
+}
+
+/**
+ * A class implementing DH-SHA1 server sessions.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_DiffieHellmanSHA1ServerSession {
+ /**
+ * An object that knows how to handle association requests with
+ * the Diffie-Hellman session type.
+ */
+
+ var $session_type = 'DH-SHA1';
+ var $needs_math = true;
+ var $allowed_assoc_types = array('HMAC-SHA1');
+ var $hash_func = 'Auth_OpenID_SHA1';
+
+ function Auth_OpenID_DiffieHellmanSHA1ServerSession($dh, $consumer_pubkey)
+ {
+ $this->dh = $dh;
+ $this->consumer_pubkey = $consumer_pubkey;
+ }
+
+ static function getDH($message)
+ {
+ $dh_modulus = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_modulus');
+ $dh_gen = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_gen');
+
+ if ((($dh_modulus === null) && ($dh_gen !== null)) ||
+ (($dh_gen === null) && ($dh_modulus !== null))) {
+
+ if ($dh_modulus === null) {
+ $missing = 'modulus';
+ } else {
+ $missing = 'generator';
+ }
+
+ return new Auth_OpenID_ServerError($message,
+ 'If non-default modulus or generator is '.
+ 'supplied, both must be supplied. Missing '.
+ $missing);
+ }
+
+ $lib = Auth_OpenID_getMathLib();
+
+ if ($dh_modulus || $dh_gen) {
+ $dh_modulus = $lib->base64ToLong($dh_modulus);
+ $dh_gen = $lib->base64ToLong($dh_gen);
+ if ($lib->cmp($dh_modulus, 0) == 0 ||
+ $lib->cmp($dh_gen, 0) == 0) {
+ return new Auth_OpenID_ServerError(
+ $message, "Failed to parse dh_mod or dh_gen");
+ }
+ $dh = new Auth_OpenID_DiffieHellman($dh_modulus, $dh_gen);
+ } else {
+ $dh = new Auth_OpenID_DiffieHellman();
+ }
+
+ $consumer_pubkey = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'dh_consumer_public');
+ if ($consumer_pubkey === null) {
+ return new Auth_OpenID_ServerError($message,
+ 'Public key for DH-SHA1 session '.
+ 'not found in query');
+ }
+
+ $consumer_pubkey =
+ $lib->base64ToLong($consumer_pubkey);
+
+ if ($consumer_pubkey === false) {
+ return new Auth_OpenID_ServerError($message,
+ "dh_consumer_public is not base64");
+ }
+
+ return array($dh, $consumer_pubkey);
+ }
+
+ static function fromMessage($message)
+ {
+ $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message);
+
+ if (is_a($result, 'Auth_OpenID_ServerError')) {
+ return $result;
+ } else {
+ list($dh, $consumer_pubkey) = $result;
+ return new Auth_OpenID_DiffieHellmanSHA1ServerSession($dh,
+ $consumer_pubkey);
+ }
+ }
+
+ function answer($secret)
+ {
+ $lib = Auth_OpenID_getMathLib();
+ $mac_key = $this->dh->xorSecret($this->consumer_pubkey, $secret,
+ $this->hash_func);
+ return array(
+ 'dh_server_public' =>
+ $lib->longToBase64($this->dh->public),
+ 'enc_mac_key' => base64_encode($mac_key));
+ }
+}
+
+/**
+ * A class implementing DH-SHA256 server sessions.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_DiffieHellmanSHA256ServerSession
+ extends Auth_OpenID_DiffieHellmanSHA1ServerSession {
+
+ var $session_type = 'DH-SHA256';
+ var $hash_func = 'Auth_OpenID_SHA256';
+ var $allowed_assoc_types = array('HMAC-SHA256');
+
+ static function fromMessage($message)
+ {
+ $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message);
+
+ if (is_a($result, 'Auth_OpenID_ServerError')) {
+ return $result;
+ } else {
+ list($dh, $consumer_pubkey) = $result;
+ return new Auth_OpenID_DiffieHellmanSHA256ServerSession($dh,
+ $consumer_pubkey);
+ }
+ }
+}
+
+/**
+ * A request to associate with the server.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request {
+ var $mode = "associate";
+
+ static function getSessionClasses()
+ {
+ return array(
+ 'no-encryption' => 'Auth_OpenID_PlainTextServerSession',
+ 'DH-SHA1' => 'Auth_OpenID_DiffieHellmanSHA1ServerSession',
+ 'DH-SHA256' => 'Auth_OpenID_DiffieHellmanSHA256ServerSession');
+ }
+
+ function Auth_OpenID_AssociateRequest($session, $assoc_type)
+ {
+ $this->session = $session;
+ $this->namespace = Auth_OpenID_OPENID2_NS;
+ $this->assoc_type = $assoc_type;
+ }
+
+ static function fromMessage($message, $server=null)
+ {
+ if ($message->isOpenID1()) {
+ $session_type = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'session_type');
+
+ if ($session_type == 'no-encryption') {
+ // oidutil.log('Received OpenID 1 request with a no-encryption '
+ // 'assocaition session type. Continuing anyway.')
+ } else if (!$session_type) {
+ $session_type = 'no-encryption';
+ }
+ } else {
+ $session_type = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'session_type');
+ if ($session_type === null) {
+ return new Auth_OpenID_ServerError($message,
+ "session_type missing from request");
+ }
+ }
+
+ $session_class = Auth_OpenID::arrayGet(
+ Auth_OpenID_AssociateRequest::getSessionClasses(),
+ $session_type);
+
+ if ($session_class === null) {
+ return new Auth_OpenID_ServerError($message,
+ "Unknown session type " .
+ $session_type);
+ }
+
+ $session = call_user_func(array($session_class, 'fromMessage'),
+ $message);
+ if (is_a($session, 'Auth_OpenID_ServerError')) {
+ return $session;
+ }
+
+ $assoc_type = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'assoc_type', 'HMAC-SHA1');
+
+ if (!in_array($assoc_type, $session->allowed_assoc_types)) {
+ $fmt = "Session type %s does not support association type %s";
+ return new Auth_OpenID_ServerError($message,
+ sprintf($fmt, $session_type, $assoc_type));
+ }
+
+ $obj = new Auth_OpenID_AssociateRequest($session, $assoc_type);
+ $obj->message = $message;
+ $obj->namespace = $message->getOpenIDNamespace();
+ return $obj;
+ }
+
+ function answer($assoc)
+ {
+ $response = new Auth_OpenID_ServerResponse($this);
+ $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
+ array(
+ 'expires_in' => sprintf('%d', $assoc->getExpiresIn()),
+ 'assoc_type' => $this->assoc_type,
+ 'assoc_handle' => $assoc->handle));
+
+ $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
+ $this->session->answer($assoc->secret));
+
+ if (! ($this->session->session_type == 'no-encryption'
+ && $this->message->isOpenID1())) {
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'session_type',
+ $this->session->session_type);
+ }
+
+ return $response;
+ }
+
+ function answerUnsupported($text_message,
+ $preferred_association_type=null,
+ $preferred_session_type=null)
+ {
+ if ($this->message->isOpenID1()) {
+ return new Auth_OpenID_ServerError($this->message);
+ }
+
+ $response = new Auth_OpenID_ServerResponse($this);
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'error_code', 'unsupported-type');
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'error', $text_message);
+
+ if ($preferred_association_type) {
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'assoc_type',
+ $preferred_association_type);
+ }
+
+ if ($preferred_session_type) {
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'session_type',
+ $preferred_session_type);
+ }
+ $response->code = AUTH_OPENID_HTTP_ERROR;
+ return $response;
+ }
+}
+
+/**
+ * A request to confirm the identity of a user.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request {
+ /**
+ * Return-to verification callback. Default is
+ * Auth_OpenID_verifyReturnTo from TrustRoot.php.
+ */
+ var $verifyReturnTo = 'Auth_OpenID_verifyReturnTo';
+
+ /**
+ * The mode of this request.
+ */
+ var $mode = "checkid_setup"; // or "checkid_immediate"
+
+ /**
+ * Whether this request is for immediate mode.
+ */
+ var $immediate = false;
+
+ /**
+ * The trust_root value for this request.
+ */
+ var $trust_root = null;
+
+ /**
+ * The OpenID namespace for this request.
+ * deprecated since version 2.0.2
+ */
+ var $namespace;
+
+ static function make($message, $identity, $return_to, $trust_root = null,
+ $immediate = false, $assoc_handle = null, $server = null)
+ {
+ if ($server === null) {
+ return new Auth_OpenID_ServerError($message,
+ "server must not be null");
+ }
+
+ if ($return_to &&
+ !Auth_OpenID_TrustRoot::_parse($return_to)) {
+ return new Auth_OpenID_MalformedReturnURL($message, $return_to);
+ }
+
+ $r = new Auth_OpenID_CheckIDRequest($identity, $return_to,
+ $trust_root, $immediate,
+ $assoc_handle, $server);
+
+ $r->namespace = $message->getOpenIDNamespace();
+ $r->message = $message;
+
+ if (!$r->trustRootValid()) {
+ return new Auth_OpenID_UntrustedReturnURL($message,
+ $return_to,
+ $trust_root);
+ } else {
+ return $r;
+ }
+ }
+
+ function Auth_OpenID_CheckIDRequest($identity, $return_to,
+ $trust_root = null, $immediate = false,
+ $assoc_handle = null, $server = null,
+ $claimed_id = null)
+ {
+ $this->namespace = Auth_OpenID_OPENID2_NS;
+ $this->assoc_handle = $assoc_handle;
+ $this->identity = $identity;
+ if ($claimed_id === null) {
+ $this->claimed_id = $identity;
+ } else {
+ $this->claimed_id = $claimed_id;
+ }
+ $this->return_to = $return_to;
+ $this->trust_root = $trust_root;
+ $this->server = $server;
+
+ if ($immediate) {
+ $this->immediate = true;
+ $this->mode = "checkid_immediate";
+ } else {
+ $this->immediate = false;
+ $this->mode = "checkid_setup";
+ }
+ }
+
+ function equals($other)
+ {
+ return (
+ (is_a($other, 'Auth_OpenID_CheckIDRequest')) &&
+ ($this->namespace == $other->namespace) &&
+ ($this->assoc_handle == $other->assoc_handle) &&
+ ($this->identity == $other->identity) &&
+ ($this->claimed_id == $other->claimed_id) &&
+ ($this->return_to == $other->return_to) &&
+ ($this->trust_root == $other->trust_root));
+ }
+
+ /*
+ * Does the relying party publish the return_to URL for this
+ * response under the realm? It is up to the provider to set a
+ * policy for what kinds of realms should be allowed. This
+ * return_to URL verification reduces vulnerability to data-theft
+ * attacks based on open proxies, corss-site-scripting, or open
+ * redirectors.
+ *
+ * This check should only be performed after making sure that the
+ * return_to URL matches the realm.
+ *
+ * @return true if the realm publishes a document with the
+ * return_to URL listed, false if not or if discovery fails
+ */
+ function returnToVerified()
+ {
+ $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
+ return call_user_func_array($this->verifyReturnTo,
+ array($this->trust_root, $this->return_to, $fetcher));
+ }
+
+ static function fromMessage($message, $server)
+ {
+ $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
+ $immediate = null;
+
+ if ($mode == "checkid_immediate") {
+ $immediate = true;
+ $mode = "checkid_immediate";
+ } else {
+ $immediate = false;
+ $mode = "checkid_setup";
+ }
+
+ $return_to = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'return_to');
+
+ if (($message->isOpenID1()) &&
+ (!$return_to)) {
+ $fmt = "Missing required field 'return_to' from checkid request";
+ return new Auth_OpenID_ServerError($message, $fmt);
+ }
+
+ $identity = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'identity');
+ $claimed_id = $message->getArg(Auth_OpenID_OPENID_NS, 'claimed_id');
+ if ($message->isOpenID1()) {
+ if ($identity === null) {
+ $s = "OpenID 1 message did not contain openid.identity";
+ return new Auth_OpenID_ServerError($message, $s);
+ }
+ } else {
+ if ($identity && !$claimed_id) {
+ $s = "OpenID 2.0 message contained openid.identity but not " .
+ "claimed_id";
+ return new Auth_OpenID_ServerError($message, $s);
+ } else if ($claimed_id && !$identity) {
+ $s = "OpenID 2.0 message contained openid.claimed_id " .
+ "but not identity";
+ return new Auth_OpenID_ServerError($message, $s);
+ }
+ }
+
+ // There's a case for making self.trust_root be a TrustRoot
+ // here. But if TrustRoot isn't currently part of the
+ // "public" API, I'm not sure it's worth doing.
+ if ($message->isOpenID1()) {
+ $trust_root_param = 'trust_root';
+ } else {
+ $trust_root_param = 'realm';
+ }
+ $trust_root = $message->getArg(Auth_OpenID_OPENID_NS,
+ $trust_root_param);
+ if (! $trust_root) {
+ $trust_root = $return_to;
+ }
+
+ if (! $message->isOpenID1() &&
+ ($return_to === null) &&
+ ($trust_root === null)) {
+ return new Auth_OpenID_ServerError($message,
+ "openid.realm required when openid.return_to absent");
+ }
+
+ $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS,
+ 'assoc_handle');
+
+ $obj = Auth_OpenID_CheckIDRequest::make($message,
+ $identity,
+ $return_to,
+ $trust_root,
+ $immediate,
+ $assoc_handle,
+ $server);
+
+ if (is_a($obj, 'Auth_OpenID_ServerError')) {
+ return $obj;
+ }
+
+ $obj->claimed_id = $claimed_id;
+
+ return $obj;
+ }
+
+ function idSelect()
+ {
+ // Is the identifier to be selected by the IDP?
+ // So IDPs don't have to import the constant
+ return $this->identity == Auth_OpenID_IDENTIFIER_SELECT;
+ }
+
+ function trustRootValid()
+ {
+ if (!$this->trust_root) {
+ return true;
+ }
+
+ $tr = Auth_OpenID_TrustRoot::_parse($this->trust_root);
+ if ($tr === false) {
+ return new Auth_OpenID_MalformedTrustRoot($this->message,
+ $this->trust_root);
+ }
+
+ if ($this->return_to !== null) {
+ return Auth_OpenID_TrustRoot::match($this->trust_root,
+ $this->return_to);
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Respond to this request. Return either an
+ * {@link Auth_OpenID_ServerResponse} or
+ * {@link Auth_OpenID_ServerError}.
+ *
+ * @param bool $allow Allow this user to claim this identity, and
+ * allow the consumer to have this information?
+ *
+ * @param string $server_url DEPRECATED. Passing $op_endpoint to
+ * the {@link Auth_OpenID_Server} constructor makes this optional.
+ *
+ * When an OpenID 1.x immediate mode request does not succeed, it
+ * gets back a URL where the request may be carried out in a
+ * not-so-immediate fashion. Pass my URL in here (the fully
+ * qualified address of this server's endpoint, i.e.
+ * http://example.com/server), and I will use it as a base for the
+ * URL for a new request.
+ *
+ * Optional for requests where {@link $immediate} is false or
+ * $allow is true.
+ *
+ * @param string $identity The OP-local identifier to answer with.
+ * Only for use when the relying party requested identifier
+ * selection.
+ *
+ * @param string $claimed_id The claimed identifier to answer
+ * with, for use with identifier selection in the case where the
+ * claimed identifier and the OP-local identifier differ,
+ * i.e. when the claimed_id uses delegation.
+ *
+ * If $identity is provided but this is not, $claimed_id will
+ * default to the value of $identity. When answering requests
+ * that did not ask for identifier selection, the response
+ * $claimed_id will default to that of the request.
+ *
+ * This parameter is new in OpenID 2.0.
+ *
+ * @return mixed
+ */
+ function answer($allow, $server_url = null, $identity = null,
+ $claimed_id = null)
+ {
+ if (!$this->return_to) {
+ return new Auth_OpenID_NoReturnToError();
+ }
+
+ if (!$server_url) {
+ if ((!$this->message->isOpenID1()) &&
+ (!$this->server->op_endpoint)) {
+ return new Auth_OpenID_ServerError(null,
+ "server should be constructed with op_endpoint to " .
+ "respond to OpenID 2.0 messages.");
+ }
+
+ $server_url = $this->server->op_endpoint;
+ }
+
+ if ($allow) {
+ $mode = 'id_res';
+ } else if ($this->message->isOpenID1()) {
+ if ($this->immediate) {
+ $mode = 'id_res';
+ } else {
+ $mode = 'cancel';
+ }
+ } else {
+ if ($this->immediate) {
+ $mode = 'setup_needed';
+ } else {
+ $mode = 'cancel';
+ }
+ }
+
+ if (!$this->trustRootValid()) {
+ return new Auth_OpenID_UntrustedReturnURL(null,
+ $this->return_to,
+ $this->trust_root);
+ }
+
+ $response = new Auth_OpenID_ServerResponse($this);
+
+ if ($claimed_id &&
+ ($this->message->isOpenID1())) {
+ return new Auth_OpenID_ServerError(null,
+ "claimed_id is new in OpenID 2.0 and not " .
+ "available for ".$this->namespace);
+ }
+
+ if ($identity && !$claimed_id) {
+ $claimed_id = $identity;
+ }
+
+ if ($allow) {
+
+ if ($this->identity == Auth_OpenID_IDENTIFIER_SELECT) {
+ if (!$identity) {
+ return new Auth_OpenID_ServerError(null,
+ "This request uses IdP-driven identifier selection. " .
+ "You must supply an identifier in the response.");
+ }
+
+ $response_identity = $identity;
+ $response_claimed_id = $claimed_id;
+
+ } else if ($this->identity) {
+ if ($identity &&
+ ($this->identity != $identity)) {
+ $fmt = "Request was for %s, cannot reply with identity %s";
+ return new Auth_OpenID_ServerError(null,
+ sprintf($fmt, $this->identity, $identity));
+ }
+
+ $response_identity = $this->identity;
+ $response_claimed_id = $this->claimed_id;
+ } else {
+ if ($identity) {
+ return new Auth_OpenID_ServerError(null,
+ "This request specified no identity and " .
+ "you supplied ".$identity);
+ }
+
+ $response_identity = null;
+ }
+
+ if (($this->message->isOpenID1()) &&
+ ($response_identity === null)) {
+ return new Auth_OpenID_ServerError(null,
+ "Request was an OpenID 1 request, so response must " .
+ "include an identifier.");
+ }
+
+ $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
+ array('mode' => $mode,
+ 'return_to' => $this->return_to,
+ 'response_nonce' => Auth_OpenID_mkNonce()));
+
+ if (!$this->message->isOpenID1()) {
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'op_endpoint', $server_url);
+ }
+
+ if ($response_identity !== null) {
+ $response->fields->setArg(
+ Auth_OpenID_OPENID_NS,
+ 'identity',
+ $response_identity);
+ if ($this->message->isOpenID2()) {
+ $response->fields->setArg(
+ Auth_OpenID_OPENID_NS,
+ 'claimed_id',
+ $response_claimed_id);
+ }
+ }
+
+ } else {
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'mode', $mode);
+
+ if ($this->immediate) {
+ if (($this->message->isOpenID1()) &&
+ (!$server_url)) {
+ return new Auth_OpenID_ServerError(null,
+ 'setup_url is required for $allow=false \
+ in OpenID 1.x immediate mode.');
+ }
+
+ $setup_request = new Auth_OpenID_CheckIDRequest(
+ $this->identity,
+ $this->return_to,
+ $this->trust_root,
+ false,
+ $this->assoc_handle,
+ $this->server,
+ $this->claimed_id);
+ $setup_request->message = $this->message;
+
+ $setup_url = $setup_request->encodeToURL($server_url);
+
+ if ($setup_url === null) {
+ return new Auth_OpenID_NoReturnToError();
+ }
+
+ $response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'user_setup_url',
+ $setup_url);
+ }
+ }
+
+ return $response;
+ }
+
+ function encodeToURL($server_url)
+ {
+ if (!$this->return_to) {
+ return new Auth_OpenID_NoReturnToError();
+ }
+
+ // Imported from the alternate reality where these classes are
+ // used in both the client and server code, so Requests are
+ // Encodable too. That's right, code imported from alternate
+ // realities all for the love of you, id_res/user_setup_url.
+
+ $q = array('mode' => $this->mode,
+ 'identity' => $this->identity,
+ 'claimed_id' => $this->claimed_id,
+ 'return_to' => $this->return_to);
+
+ if ($this->trust_root) {
+ if ($this->message->isOpenID1()) {
+ $q['trust_root'] = $this->trust_root;
+ } else {
+ $q['realm'] = $this->trust_root;
+ }
+ }
+
+ if ($this->assoc_handle) {
+ $q['assoc_handle'] = $this->assoc_handle;
+ }
+
+ $response = new Auth_OpenID_Message(
+ $this->message->getOpenIDNamespace());
+ $response->updateArgs(Auth_OpenID_OPENID_NS, $q);
+ return $response->toURL($server_url);
+ }
+
+ function getCancelURL()
+ {
+ if (!$this->return_to) {
+ return new Auth_OpenID_NoReturnToError();
+ }
+
+ if ($this->immediate) {
+ return new Auth_OpenID_ServerError(null,
+ "Cancel is not an appropriate \
+ response to immediate mode \
+ requests.");
+ }
+
+ $response = new Auth_OpenID_Message(
+ $this->message->getOpenIDNamespace());
+ $response->setArg(Auth_OpenID_OPENID_NS, 'mode', 'cancel');
+ return $response->toURL($this->return_to);
+ }
+}
+
+/**
+ * This class encapsulates the response to an OpenID server request.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_ServerResponse {
+
+ function Auth_OpenID_ServerResponse($request)
+ {
+ $this->request = $request;
+ $this->fields = new Auth_OpenID_Message($this->request->namespace);
+ }
+
+ function whichEncoding()
+ {
+ global $_Auth_OpenID_Request_Modes;
+
+ if (in_array($this->request->mode, $_Auth_OpenID_Request_Modes)) {
+ if ($this->fields->isOpenID2() &&
+ (strlen($this->encodeToURL()) >
+ Auth_OpenID_OPENID1_URL_LIMIT)) {
+ return Auth_OpenID_ENCODE_HTML_FORM;
+ } else {
+ return Auth_OpenID_ENCODE_URL;
+ }
+ } else {
+ return Auth_OpenID_ENCODE_KVFORM;
+ }
+ }
+
+ /*
+ * Returns the form markup for this response.
+ *
+ * @return str
+ */
+ function toFormMarkup($form_tag_attrs=null)
+ {
+ return $this->fields->toFormMarkup($this->request->return_to,
+ $form_tag_attrs);
+ }
+
+ /*
+ * Returns an HTML document containing the form markup for this
+ * response that autosubmits with javascript.
+ */
+ function toHTML()
+ {
+ return Auth_OpenID::autoSubmitHTML($this->toFormMarkup());
+ }
+
+ /*
+ * Returns True if this response's encoding is ENCODE_HTML_FORM.
+ * Convenience method for server authors.
+ *
+ * @return bool
+ */
+ function renderAsForm()
+ {
+ return $this->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM;
+ }
+
+
+ function encodeToURL()
+ {
+ return $this->fields->toURL($this->request->return_to);
+ }
+
+ function addExtension($extension_response)
+ {
+ $extension_response->toMessage($this->fields);
+ }
+
+ function needsSigning()
+ {
+ return $this->fields->getArg(Auth_OpenID_OPENID_NS,
+ 'mode') == 'id_res';
+ }
+
+ function encodeToKVForm()
+ {
+ return $this->fields->toKVForm();
+ }
+}
+
+/**
+ * A web-capable response object which you can use to generate a
+ * user-agent response.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_WebResponse {
+ var $code = AUTH_OPENID_HTTP_OK;
+ var $body = "";
+
+ function Auth_OpenID_WebResponse($code = null, $headers = null,
+ $body = null)
+ {
+ if ($code) {
+ $this->code = $code;
+ }
+
+ if ($headers !== null) {
+ $this->headers = $headers;
+ } else {
+ $this->headers = array();
+ }
+
+ if ($body !== null) {
+ $this->body = $body;
+ }
+ }
+}
+
+/**
+ * Responsible for the signature of query data and the verification of
+ * OpenID signature values.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Signatory {
+
+ // = 14 * 24 * 60 * 60; # 14 days, in seconds
+ var $SECRET_LIFETIME = 1209600;
+
+ // keys have a bogus server URL in them because the filestore
+ // really does expect that key to be a URL. This seems a little
+ // silly for the server store, since I expect there to be only one
+ // server URL.
+ var $normal_key = 'http://localhost/|normal';
+ var $dumb_key = 'http://localhost/|dumb';
+
+ /**
+ * Create a new signatory using a given store.
+ */
+ function Auth_OpenID_Signatory($store)
+ {
+ // assert store is not None
+ $this->store = $store;
+ }
+
+ /**
+ * Verify, using a given association handle, a signature with
+ * signed key-value pairs from an HTTP request.
+ */
+ function verify($assoc_handle, $message)
+ {
+ $assoc = $this->getAssociation($assoc_handle, true);
+ if (!$assoc) {
+ // oidutil.log("failed to get assoc with handle %r to verify sig %r"
+ // % (assoc_handle, sig))
+ return false;
+ }
+
+ return $assoc->checkMessageSignature($message);
+ }
+
+ /**
+ * Given a response, sign the fields in the response's 'signed'
+ * list, and insert the signature into the response.
+ */
+ function sign($response)
+ {
+ $signed_response = $response;
+ $assoc_handle = $response->request->assoc_handle;
+
+ if ($assoc_handle) {
+ // normal mode
+ $assoc = $this->getAssociation($assoc_handle, false, false);
+ if (!$assoc || ($assoc->getExpiresIn() <= 0)) {
+ // fall back to dumb mode
+ $signed_response->fields->setArg(Auth_OpenID_OPENID_NS,
+ 'invalidate_handle', $assoc_handle);
+ $assoc_type = ($assoc ? $assoc->assoc_type : 'HMAC-SHA1');
+
+ if ($assoc && ($assoc->getExpiresIn() <= 0)) {
+ $this->invalidate($assoc_handle, false);
+ }
+
+ $assoc = $this->createAssociation(true, $assoc_type);
+ }
+ } else {
+ // dumb mode.
+ $assoc = $this->createAssociation(true);
+ }
+
+ $signed_response->fields = $assoc->signMessage(
+ $signed_response->fields);
+ return $signed_response;
+ }
+
+ /**
+ * Make a new association.
+ */
+ function createAssociation($dumb = true, $assoc_type = 'HMAC-SHA1')
+ {
+ $secret = Auth_OpenID_CryptUtil::getBytes(
+ Auth_OpenID_getSecretSize($assoc_type));
+
+ $uniq = base64_encode(Auth_OpenID_CryptUtil::getBytes(4));
+ $handle = sprintf('{%s}{%x}{%s}', $assoc_type, intval(time()), $uniq);
+
+ $assoc = Auth_OpenID_Association::fromExpiresIn(
+ $this->SECRET_LIFETIME, $handle, $secret, $assoc_type);
+
+ if ($dumb) {
+ $key = $this->dumb_key;
+ } else {
+ $key = $this->normal_key;
+ }
+
+ $this->store->storeAssociation($key, $assoc);
+ return $assoc;
+ }
+
+ /**
+ * Given an association handle, get the association from the
+ * store, or return a ServerError or null if something goes wrong.
+ */
+ function getAssociation($assoc_handle, $dumb, $check_expiration=true)
+ {
+ if ($assoc_handle === null) {
+ return new Auth_OpenID_ServerError(null,
+ "assoc_handle must not be null");
+ }
+
+ if ($dumb) {
+ $key = $this->dumb_key;
+ } else {
+ $key = $this->normal_key;
+ }
+
+ $assoc = $this->store->getAssociation($key, $assoc_handle);
+
+ if (($assoc !== null) && ($assoc->getExpiresIn() <= 0)) {
+ if ($check_expiration) {
+ $this->store->removeAssociation($key, $assoc_handle);
+ $assoc = null;
+ }
+ }
+
+ return $assoc;
+ }
+
+ /**
+ * Invalidate a given association handle.
+ */
+ function invalidate($assoc_handle, $dumb)
+ {
+ if ($dumb) {
+ $key = $this->dumb_key;
+ } else {
+ $key = $this->normal_key;
+ }
+ $this->store->removeAssociation($key, $assoc_handle);
+ }
+}
+
+/**
+ * Encode an {@link Auth_OpenID_ServerResponse} to an
+ * {@link Auth_OpenID_WebResponse}.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Encoder {
+
+ var $responseFactory = 'Auth_OpenID_WebResponse';
+
+ /**
+ * Encode an {@link Auth_OpenID_ServerResponse} and return an
+ * {@link Auth_OpenID_WebResponse}.
+ */
+ function encode($response)
+ {
+ $cls = $this->responseFactory;
+
+ $encode_as = $response->whichEncoding();
+ if ($encode_as == Auth_OpenID_ENCODE_KVFORM) {
+ $wr = new $cls(null, null, $response->encodeToKVForm());
+ if (is_a($response, 'Auth_OpenID_ServerError')) {
+ $wr->code = AUTH_OPENID_HTTP_ERROR;
+ }
+ } else if ($encode_as == Auth_OpenID_ENCODE_URL) {
+ $location = $response->encodeToURL();
+ $wr = new $cls(AUTH_OPENID_HTTP_REDIRECT,
+ array('location' => $location));
+ } else if ($encode_as == Auth_OpenID_ENCODE_HTML_FORM) {
+ $wr = new $cls(AUTH_OPENID_HTTP_OK, array(),
+ $response->toHTML());
+ } else {
+ return new Auth_OpenID_EncodingError($response);
+ }
+ /* Allow the response to carry a custom error code (ex: for Association errors) */
+ if(isset($response->code)) {
+ $wr->code = $response->code;
+ }
+ return $wr;
+ }
+}
+
+/**
+ * An encoder which also takes care of signing fields when required.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder {
+
+ function Auth_OpenID_SigningEncoder($signatory)
+ {
+ $this->signatory = $signatory;
+ }
+
+ /**
+ * Sign an {@link Auth_OpenID_ServerResponse} and return an
+ * {@link Auth_OpenID_WebResponse}.
+ */
+ function encode($response)
+ {
+ // the isinstance is a bit of a kludge... it means there isn't
+ // really an adapter to make the interfaces quite match.
+ if (!is_a($response, 'Auth_OpenID_ServerError') &&
+ $response->needsSigning()) {
+
+ if (!$this->signatory) {
+ return new Auth_OpenID_ServerError(null,
+ "Must have a store to sign request");
+ }
+
+ if ($response->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig')) {
+ return new Auth_OpenID_AlreadySigned($response);
+ }
+ $response = $this->signatory->sign($response);
+ }
+
+ return parent::encode($response);
+ }
+}
+
+/**
+ * Decode an incoming query into an Auth_OpenID_Request.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Decoder {
+
+ function Auth_OpenID_Decoder($server)
+ {
+ $this->server = $server;
+
+ $this->handlers = array(
+ 'checkid_setup' => 'Auth_OpenID_CheckIDRequest',
+ 'checkid_immediate' => 'Auth_OpenID_CheckIDRequest',
+ 'check_authentication' => 'Auth_OpenID_CheckAuthRequest',
+ 'associate' => 'Auth_OpenID_AssociateRequest'
+ );
+ }
+
+ /**
+ * Given an HTTP query in an array (key-value pairs), decode it
+ * into an Auth_OpenID_Request object.
+ */
+ function decode($query)
+ {
+ if (!$query) {
+ return null;
+ }
+
+ $message = Auth_OpenID_Message::fromPostArgs($query);
+
+ if ($message === null) {
+ /*
+ * It's useful to have a Message attached to a
+ * ProtocolError, so we override the bad ns value to build
+ * a Message out of it. Kinda kludgy, since it's made of
+ * lies, but the parts that aren't lies are more useful
+ * than a 'None'.
+ */
+ $old_ns = $query['openid.ns'];
+
+ $query['openid.ns'] = Auth_OpenID_OPENID2_NS;
+ $message = Auth_OpenID_Message::fromPostArgs($query);
+ return new Auth_OpenID_ServerError(
+ $message,
+ sprintf("Invalid OpenID namespace URI: %s", $old_ns));
+ }
+
+ $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
+ if (!$mode) {
+ return new Auth_OpenID_ServerError($message,
+ "No mode value in message");
+ }
+
+ if (Auth_OpenID::isFailure($mode)) {
+ return new Auth_OpenID_ServerError($message,
+ $mode->message);
+ }
+
+ $handlerCls = Auth_OpenID::arrayGet($this->handlers, $mode,
+ $this->defaultDecoder($message));
+
+ if (!is_a($handlerCls, 'Auth_OpenID_ServerError')) {
+ return call_user_func_array(array($handlerCls, 'fromMessage'),
+ array($message, $this->server));
+ } else {
+ return $handlerCls;
+ }
+ }
+
+ function defaultDecoder($message)
+ {
+ $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
+
+ if (Auth_OpenID::isFailure($mode)) {
+ return new Auth_OpenID_ServerError($message,
+ $mode->message);
+ }
+
+ return new Auth_OpenID_ServerError($message,
+ sprintf("Unrecognized OpenID mode %s", $mode));
+ }
+}
+
+/**
+ * An error that indicates an encoding problem occurred.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_EncodingError {
+ function Auth_OpenID_EncodingError($response)
+ {
+ $this->response = $response;
+ }
+}
+
+/**
+ * An error that indicates that a response was already signed.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_AlreadySigned extends Auth_OpenID_EncodingError {
+ // This response is already signed.
+}
+
+/**
+ * An error that indicates that the given return_to is not under the
+ * given trust_root.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError {
+ function Auth_OpenID_UntrustedReturnURL($message, $return_to,
+ $trust_root)
+ {
+ parent::Auth_OpenID_ServerError($message, "Untrusted return_to URL");
+ $this->return_to = $return_to;
+ $this->trust_root = $trust_root;
+ }
+
+ function toString()
+ {
+ return sprintf("return_to %s not under trust_root %s",
+ $this->return_to, $this->trust_root);
+ }
+}
+
+/**
+ * I handle requests for an OpenID server.
+ *
+ * Some types of requests (those which are not checkid requests) may
+ * be handed to my {@link handleRequest} method, and I will take care
+ * of it and return a response.
+ *
+ * For your convenience, I also provide an interface to {@link
+ * Auth_OpenID_Decoder::decode()} and {@link
+ * Auth_OpenID_SigningEncoder::encode()} through my methods {@link
+ * decodeRequest} and {@link encodeResponse}.
+ *
+ * All my state is encapsulated in an {@link Auth_OpenID_OpenIDStore}.
+ *
+ * Example:
+ *
+ * <pre> $oserver = new Auth_OpenID_Server(Auth_OpenID_FileStore($data_path),
+ * "http://example.com/op");
+ * $request = $oserver->decodeRequest();
+ * if (in_array($request->mode, array('checkid_immediate',
+ * 'checkid_setup'))) {
+ * if ($app->isAuthorized($request->identity, $request->trust_root)) {
+ * $response = $request->answer(true);
+ * } else if ($request->immediate) {
+ * $response = $request->answer(false);
+ * } else {
+ * $app->showDecidePage($request);
+ * return;
+ * }
+ * } else {
+ * $response = $oserver->handleRequest($request);
+ * }
+ *
+ * $webresponse = $oserver->encode($response);</pre>
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_Server {
+ function Auth_OpenID_Server($store, $op_endpoint=null)
+ {
+ $this->store = $store;
+ $this->signatory = new Auth_OpenID_Signatory($this->store);
+ $this->encoder = new Auth_OpenID_SigningEncoder($this->signatory);
+ $this->decoder = new Auth_OpenID_Decoder($this);
+ $this->op_endpoint = $op_endpoint;
+ $this->negotiator = Auth_OpenID_getDefaultNegotiator();
+ }
+
+ /**
+ * Handle a request. Given an {@link Auth_OpenID_Request} object,
+ * call the appropriate {@link Auth_OpenID_Server} method to
+ * process the request and generate a response.
+ *
+ * @param Auth_OpenID_Request $request An {@link Auth_OpenID_Request}
+ * returned by {@link Auth_OpenID_Server::decodeRequest()}.
+ *
+ * @return Auth_OpenID_ServerResponse $response A response object
+ * capable of generating a user-agent reply.
+ */
+ function handleRequest($request)
+ {
+ if (method_exists($this, "openid_" . $request->mode)) {
+ $handler = array($this, "openid_" . $request->mode);
+ return call_user_func_array($handler, array($request));
+ }
+ return null;
+ }
+
+ /**
+ * The callback for 'check_authentication' messages.
+ */
+ function openid_check_authentication($request)
+ {
+ return $request->answer($this->signatory);
+ }
+
+ /**
+ * The callback for 'associate' messages.
+ */
+ function openid_associate($request)
+ {
+ $assoc_type = $request->assoc_type;
+ $session_type = $request->session->session_type;
+ if ($this->negotiator->isAllowed($assoc_type, $session_type)) {
+ $assoc = $this->signatory->createAssociation(false,
+ $assoc_type);
+ return $request->answer($assoc);
+ } else {
+ $message = sprintf('Association type %s is not supported with '.
+ 'session type %s', $assoc_type, $session_type);
+ list($preferred_assoc_type, $preferred_session_type) =
+ $this->negotiator->getAllowedType();
+ return $request->answerUnsupported($message,
+ $preferred_assoc_type,
+ $preferred_session_type);
+ }
+ }
+
+ /**
+ * Encodes as response in the appropriate format suitable for
+ * sending to the user agent.
+ */
+ function encodeResponse($response)
+ {
+ return $this->encoder->encode($response);
+ }
+
+ /**
+ * Decodes a query args array into the appropriate
+ * {@link Auth_OpenID_Request} object.
+ */
+ function decodeRequest($query=null)
+ {
+ if ($query === null) {
+ $query = Auth_OpenID::getQuery();
+ }
+
+ return $this->decoder->decode($query);
+ }
+}
+
+
diff --git a/plugins/openid/lib/Auth/OpenID/ServerRequest.php b/plugins/openid/lib/Auth/OpenID/ServerRequest.php
new file mode 100644
index 00000000..69222a5e
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/ServerRequest.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * OpenID Server Request
+ *
+ * @see Auth_OpenID_Server
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Imports
+ */
+require_once "Auth/OpenID.php";
+
+/**
+ * Object that holds the state of a request to the OpenID server
+ *
+ * With accessor functions to get at the internal request data.
+ *
+ * @see Auth_OpenID_Server
+ * @package OpenID
+ */
+class Auth_OpenID_ServerRequest {
+ function Auth_OpenID_ServerRequest()
+ {
+ $this->mode = null;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/TrustRoot.php b/plugins/openid/lib/Auth/OpenID/TrustRoot.php
new file mode 100644
index 00000000..000440b5
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/TrustRoot.php
@@ -0,0 +1,461 @@
+<?php
+/**
+ * Functions for dealing with OpenID trust roots
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+require_once 'Auth/OpenID/Discover.php';
+
+/**
+ * A regular expression that matches a domain ending in a top-level domains.
+ * Used in checking trust roots for sanity.
+ *
+ * @access private
+ */
+define('Auth_OpenID___TLDs',
+ '/\.(ac|ad|ae|aero|af|ag|ai|al|am|an|ao|aq|ar|arpa|as|asia' .
+ '|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|biz|bj|bm|bn|bo|br' .
+ '|bs|bt|bv|bw|by|bz|ca|cat|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co' .
+ '|com|coop|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg' .
+ '|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl' .
+ '|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie' .
+ '|il|im|in|info|int|io|iq|ir|is|it|je|jm|jo|jobs|jp|ke|kg|kh' .
+ '|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly' .
+ '|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mo|mobi|mp|mq|mr|ms|mt' .
+ '|mu|museum|mv|mw|mx|my|mz|na|name|nc|ne|net|nf|ng|ni|nl|no' .
+ '|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pro|ps|pt' .
+ '|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl' .
+ '|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm' .
+ '|tn|to|tp|tr|travel|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve' .
+ '|vg|vi|vn|vu|wf|ws|xn--0zwm56d|xn--11b5bs3a9aj6g' .
+ '|xn--80akhbyknj4f|xn--9t4b11yi5a|xn--deba0ad|xn--g6w251d' .
+ '|xn--hgbk6aj7f53bba|xn--hlcj6aya9esc7a|xn--jxalpdlp' .
+ '|xn--kgbechtv|xn--zckzah|ye|yt|yu|za|zm|zw)\.?$/');
+
+define('Auth_OpenID___HostSegmentRe',
+ "/^(?:[-a-zA-Z0-9!$&'\\(\\)\\*+,;=._~]|%[a-zA-Z0-9]{2})*$/");
+
+/**
+ * A wrapper for trust-root related functions
+ */
+class Auth_OpenID_TrustRoot {
+ /*
+ * Return a discovery URL for this realm.
+ *
+ * Return null if the realm could not be parsed or was not valid.
+ *
+ * @param return_to The relying party return URL of the OpenID
+ * authentication request
+ *
+ * @return The URL upon which relying party discovery should be
+ * run in order to verify the return_to URL
+ */
+ static function buildDiscoveryURL($realm)
+ {
+ $parsed = Auth_OpenID_TrustRoot::_parse($realm);
+
+ if ($parsed === false) {
+ return false;
+ }
+
+ if ($parsed['wildcard']) {
+ // Use "www." in place of the star
+ if ($parsed['host'][0] != '.') {
+ return false;
+ }
+
+ $www_domain = 'www' . $parsed['host'];
+
+ return sprintf('%s://%s%s', $parsed['scheme'],
+ $www_domain, $parsed['path']);
+ } else {
+ return $parsed['unparsed'];
+ }
+ }
+
+ /**
+ * Parse a URL into its trust_root parts.
+ *
+ * @static
+ *
+ * @access private
+ *
+ * @param string $trust_root The url to parse
+ *
+ * @return mixed $parsed Either an associative array of trust root
+ * parts or false if parsing failed.
+ */
+ static function _parse($trust_root)
+ {
+ $trust_root = Auth_OpenID_urinorm($trust_root);
+ if ($trust_root === null) {
+ return false;
+ }
+
+ if (preg_match("/:\/\/[^:]+(:\d+){2,}(\/|$)/", $trust_root)) {
+ return false;
+ }
+
+ $parts = @parse_url($trust_root);
+ if ($parts === false) {
+ return false;
+ }
+
+ $required_parts = array('scheme', 'host');
+ $forbidden_parts = array('user', 'pass', 'fragment');
+ $keys = array_keys($parts);
+ if (array_intersect($keys, $required_parts) != $required_parts) {
+ return false;
+ }
+
+ if (array_intersect($keys, $forbidden_parts) != array()) {
+ return false;
+ }
+
+ if (!preg_match(Auth_OpenID___HostSegmentRe, $parts['host'])) {
+ return false;
+ }
+
+ $scheme = strtolower($parts['scheme']);
+ $allowed_schemes = array('http', 'https');
+ if (!in_array($scheme, $allowed_schemes)) {
+ return false;
+ }
+ $parts['scheme'] = $scheme;
+
+ $host = strtolower($parts['host']);
+ $hostparts = explode('*', $host);
+ switch (count($hostparts)) {
+ case 1:
+ $parts['wildcard'] = false;
+ break;
+ case 2:
+ if ($hostparts[0] ||
+ ($hostparts[1] && substr($hostparts[1], 0, 1) != '.')) {
+ return false;
+ }
+ $host = $hostparts[1];
+ $parts['wildcard'] = true;
+ break;
+ default:
+ return false;
+ }
+ if (strpos($host, ':') !== false) {
+ return false;
+ }
+
+ $parts['host'] = $host;
+
+ if (isset($parts['path'])) {
+ $path = strtolower($parts['path']);
+ if (substr($path, 0, 1) != '/') {
+ return false;
+ }
+ } else {
+ $path = '/';
+ }
+
+ $parts['path'] = $path;
+ if (!isset($parts['port'])) {
+ $parts['port'] = false;
+ }
+
+
+ $parts['unparsed'] = $trust_root;
+
+ return $parts;
+ }
+
+ /**
+ * Is this trust root sane?
+ *
+ * A trust root is sane if it is syntactically valid and it has a
+ * reasonable domain name. Specifically, the domain name must be
+ * more than one level below a standard TLD or more than two
+ * levels below a two-letter tld.
+ *
+ * For example, '*.com' is not a sane trust root, but '*.foo.com'
+ * is. '*.co.uk' is not sane, but '*.bbc.co.uk' is.
+ *
+ * This check is not always correct, but it attempts to err on the
+ * side of marking sane trust roots insane instead of marking
+ * insane trust roots sane. For example, 'kink.fm' is marked as
+ * insane even though it "should" (for some meaning of should) be
+ * marked sane.
+ *
+ * This function should be used when creating OpenID servers to
+ * alert the users of the server when a consumer attempts to get
+ * the user to accept a suspicious trust root.
+ *
+ * @static
+ * @param string $trust_root The trust root to check
+ * @return bool $sanity Whether the trust root looks OK
+ */
+ static function isSane($trust_root)
+ {
+ $parts = Auth_OpenID_TrustRoot::_parse($trust_root);
+ if ($parts === false) {
+ return false;
+ }
+
+ // Localhost is a special case
+ if ($parts['host'] == 'localhost') {
+ return true;
+ }
+
+ $host_parts = explode('.', $parts['host']);
+ if ($parts['wildcard']) {
+ // Remove the empty string from the beginning of the array
+ array_shift($host_parts);
+ }
+
+ if ($host_parts && !$host_parts[count($host_parts) - 1]) {
+ array_pop($host_parts);
+ }
+
+ if (!$host_parts) {
+ return false;
+ }
+
+ // Don't allow adjacent dots
+ if (in_array('', $host_parts, true)) {
+ return false;
+ }
+
+ // Get the top-level domain of the host. If it is not a valid TLD,
+ // it's not sane.
+ preg_match(Auth_OpenID___TLDs, $parts['host'], $matches);
+ if (!$matches) {
+ return false;
+ }
+ $tld = $matches[1];
+
+ if (count($host_parts) == 1) {
+ return false;
+ }
+
+ if ($parts['wildcard']) {
+ // It's a 2-letter tld with a short second to last segment
+ // so there needs to be more than two segments specified
+ // (e.g. *.co.uk is insane)
+ $second_level = $host_parts[count($host_parts) - 2];
+ if (strlen($tld) == 2 && strlen($second_level) <= 3) {
+ return count($host_parts) > 2;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Does this URL match the given trust root?
+ *
+ * Return whether the URL falls under the given trust root. This
+ * does not check whether the trust root is sane. If the URL or
+ * trust root do not parse, this function will return false.
+ *
+ * @param string $trust_root The trust root to match against
+ *
+ * @param string $url The URL to check
+ *
+ * @return bool $matches Whether the URL matches against the
+ * trust root
+ */
+ static function match($trust_root, $url)
+ {
+ $trust_root_parsed = Auth_OpenID_TrustRoot::_parse($trust_root);
+ $url_parsed = Auth_OpenID_TrustRoot::_parse($url);
+ if (!$trust_root_parsed || !$url_parsed) {
+ return false;
+ }
+
+ // Check hosts matching
+ if ($url_parsed['wildcard']) {
+ return false;
+ }
+ if ($trust_root_parsed['wildcard']) {
+ $host_tail = $trust_root_parsed['host'];
+ $host = $url_parsed['host'];
+ if ($host_tail &&
+ substr($host, -(strlen($host_tail))) != $host_tail &&
+ substr($host_tail, 1) != $host) {
+ return false;
+ }
+ } else {
+ if ($trust_root_parsed['host'] != $url_parsed['host']) {
+ return false;
+ }
+ }
+
+ // Check path and query matching
+ $base_path = $trust_root_parsed['path'];
+ $path = $url_parsed['path'];
+ if (!isset($trust_root_parsed['query'])) {
+ if ($base_path != $path) {
+ if (substr($path, 0, strlen($base_path)) != $base_path) {
+ return false;
+ }
+ if (substr($base_path, strlen($base_path) - 1, 1) != '/' &&
+ substr($path, strlen($base_path), 1) != '/') {
+ return false;
+ }
+ }
+ } else {
+ $base_query = $trust_root_parsed['query'];
+ $query = @$url_parsed['query'];
+ $qplus = substr($query, 0, strlen($base_query) + 1);
+ $bqplus = $base_query . '&';
+ if ($base_path != $path ||
+ ($base_query != $query && $qplus != $bqplus)) {
+ return false;
+ }
+ }
+
+ // The port and scheme need to match exactly
+ return ($trust_root_parsed['scheme'] == $url_parsed['scheme'] &&
+ $url_parsed['port'] === $trust_root_parsed['port']);
+ }
+}
+
+/*
+ * If the endpoint is a relying party OpenID return_to endpoint,
+ * return the endpoint URL. Otherwise, return None.
+ *
+ * This function is intended to be used as a filter for the Yadis
+ * filtering interface.
+ *
+ * @see: C{L{openid.yadis.services}}
+ * @see: C{L{openid.yadis.filters}}
+ *
+ * @param endpoint: An XRDS BasicServiceEndpoint, as returned by
+ * performing Yadis dicovery.
+ *
+ * @returns: The endpoint URL or None if the endpoint is not a
+ * relying party endpoint.
+ */
+function filter_extractReturnURL($endpoint)
+{
+ if ($endpoint->matchTypes(array(Auth_OpenID_RP_RETURN_TO_URL_TYPE))) {
+ return $endpoint;
+ } else {
+ return null;
+ }
+}
+
+function &Auth_OpenID_extractReturnURL(&$endpoint_list)
+{
+ $result = array();
+
+ foreach ($endpoint_list as $endpoint) {
+ if (filter_extractReturnURL($endpoint)) {
+ $result[] = $endpoint;
+ }
+ }
+
+ return $result;
+}
+
+/*
+ * Is the return_to URL under one of the supplied allowed return_to
+ * URLs?
+ */
+function Auth_OpenID_returnToMatches($allowed_return_to_urls, $return_to)
+{
+ foreach ($allowed_return_to_urls as $allowed_return_to) {
+ // A return_to pattern works the same as a realm, except that
+ // it's not allowed to use a wildcard. We'll model this by
+ // parsing it as a realm, and not trying to match it if it has
+ // a wildcard.
+
+ $return_realm = Auth_OpenID_TrustRoot::_parse($allowed_return_to);
+ if (// Parses as a trust root
+ ($return_realm !== false) &&
+ // Does not have a wildcard
+ (!$return_realm['wildcard']) &&
+ // Matches the return_to that we passed in with it
+ (Auth_OpenID_TrustRoot::match($allowed_return_to, $return_to))) {
+ return true;
+ }
+ }
+
+ // No URL in the list matched
+ return false;
+}
+
+/*
+ * Given a relying party discovery URL return a list of return_to
+ * URLs.
+ */
+function Auth_OpenID_getAllowedReturnURLs($relying_party_url, $fetcher,
+ $discover_function=null)
+{
+ if ($discover_function === null) {
+ $discover_function = array('Auth_Yadis_Yadis', 'discover');
+ }
+
+ $xrds_parse_cb = array('Auth_OpenID_ServiceEndpoint', 'consumerFromXRDS');
+
+ list($rp_url_after_redirects, $endpoints) =
+ Auth_Yadis_getServiceEndpoints($relying_party_url, $xrds_parse_cb,
+ $discover_function, $fetcher);
+
+ if ($rp_url_after_redirects != $relying_party_url) {
+ // Verification caused a redirect
+ return false;
+ }
+
+ call_user_func_array($discover_function,
+ array($relying_party_url, &$fetcher));
+
+ $return_to_urls = array();
+ $matching_endpoints = Auth_OpenID_extractReturnURL($endpoints);
+
+ foreach ($matching_endpoints as $e) {
+ $return_to_urls[] = $e->server_url;
+ }
+
+ return $return_to_urls;
+}
+
+/*
+ * Verify that a return_to URL is valid for the given realm.
+ *
+ * This function builds a discovery URL, performs Yadis discovery on
+ * it, makes sure that the URL does not redirect, parses out the
+ * return_to URLs, and finally checks to see if the current return_to
+ * URL matches the return_to.
+ *
+ * @return true if the return_to URL is valid for the realm
+ */
+function Auth_OpenID_verifyReturnTo($realm_str, $return_to, $fetcher,
+ $_vrfy='Auth_OpenID_getAllowedReturnURLs')
+{
+ $disco_url = Auth_OpenID_TrustRoot::buildDiscoveryURL($realm_str);
+
+ if ($disco_url === false) {
+ return false;
+ }
+
+ $allowable_urls = call_user_func_array($_vrfy,
+ array($disco_url, $fetcher));
+
+ // The realm_str could not be parsed.
+ if ($allowable_urls === false) {
+ return false;
+ }
+
+ if (Auth_OpenID_returnToMatches($allowable_urls, $return_to)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/OpenID/URINorm.php b/plugins/openid/lib/Auth/OpenID/URINorm.php
new file mode 100644
index 00000000..c051b550
--- /dev/null
+++ b/plugins/openid/lib/Auth/OpenID/URINorm.php
@@ -0,0 +1,249 @@
+<?php
+
+/**
+ * URI normalization routines.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+require_once 'Auth/Yadis/Misc.php';
+
+// from appendix B of rfc 3986 (http://www.ietf.org/rfc/rfc3986.txt)
+function Auth_OpenID_getURIPattern()
+{
+ return '&^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?&';
+}
+
+function Auth_OpenID_getAuthorityPattern()
+{
+ return '/^([^@]*@)?([^:]*)(:.*)?/';
+}
+
+function Auth_OpenID_getEncodedPattern()
+{
+ return '/%([0-9A-Fa-f]{2})/';
+}
+
+# gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+#
+# sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+# / "*" / "+" / "," / ";" / "="
+#
+# unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+function Auth_OpenID_getURLIllegalCharRE()
+{
+ return "/([^-A-Za-z0-9:\/\?#\[\]@\!\$&'\(\)\*\+,;=\._~\%])/";
+}
+
+function Auth_OpenID_getUnreserved()
+{
+ $_unreserved = array();
+ for ($i = 0; $i < 256; $i++) {
+ $_unreserved[$i] = false;
+ }
+
+ for ($i = ord('A'); $i <= ord('Z'); $i++) {
+ $_unreserved[$i] = true;
+ }
+
+ for ($i = ord('0'); $i <= ord('9'); $i++) {
+ $_unreserved[$i] = true;
+ }
+
+ for ($i = ord('a'); $i <= ord('z'); $i++) {
+ $_unreserved[$i] = true;
+ }
+
+ $_unreserved[ord('-')] = true;
+ $_unreserved[ord('.')] = true;
+ $_unreserved[ord('_')] = true;
+ $_unreserved[ord('~')] = true;
+
+ return $_unreserved;
+}
+
+function Auth_OpenID_getEscapeRE()
+{
+ $parts = array();
+ foreach (array_merge(Auth_Yadis_getUCSChars(),
+ Auth_Yadis_getIPrivateChars()) as $pair) {
+ list($m, $n) = $pair;
+ $parts[] = sprintf("%s-%s", chr($m), chr($n));
+ }
+
+ return sprintf('[%s]', implode('', $parts));
+}
+
+function Auth_OpenID_pct_encoded_replace_unreserved($mo)
+{
+ $_unreserved = Auth_OpenID_getUnreserved();
+
+ $i = intval($mo[1], 16);
+ if ($_unreserved[$i]) {
+ return chr($i);
+ } else {
+ return strtoupper($mo[0]);
+ }
+
+ return $mo[0];
+}
+
+function Auth_OpenID_pct_encoded_replace($mo)
+{
+ return chr(intval($mo[1], 16));
+}
+
+function Auth_OpenID_remove_dot_segments($path)
+{
+ $result_segments = array();
+
+ while ($path) {
+ if (Auth_Yadis_startswith($path, '../')) {
+ $path = substr($path, 3);
+ } else if (Auth_Yadis_startswith($path, './')) {
+ $path = substr($path, 2);
+ } else if (Auth_Yadis_startswith($path, '/./')) {
+ $path = substr($path, 2);
+ } else if ($path == '/.') {
+ $path = '/';
+ } else if (Auth_Yadis_startswith($path, '/../')) {
+ $path = substr($path, 3);
+ if ($result_segments) {
+ array_pop($result_segments);
+ }
+ } else if ($path == '/..') {
+ $path = '/';
+ if ($result_segments) {
+ array_pop($result_segments);
+ }
+ } else if (($path == '..') ||
+ ($path == '.')) {
+ $path = '';
+ } else {
+ $i = 0;
+ if ($path[0] == '/') {
+ $i = 1;
+ }
+ $i = strpos($path, '/', $i);
+ if ($i === false) {
+ $i = strlen($path);
+ }
+ $result_segments[] = substr($path, 0, $i);
+ $path = substr($path, $i);
+ }
+ }
+
+ return implode('', $result_segments);
+}
+
+function Auth_OpenID_urinorm($uri)
+{
+ $uri_matches = array();
+ preg_match(Auth_OpenID_getURIPattern(), $uri, $uri_matches);
+
+ if (count($uri_matches) < 9) {
+ for ($i = count($uri_matches); $i <= 9; $i++) {
+ $uri_matches[] = '';
+ }
+ }
+
+ $illegal_matches = array();
+ preg_match(Auth_OpenID_getURLIllegalCharRE(),
+ $uri, $illegal_matches);
+ if ($illegal_matches) {
+ return null;
+ }
+
+ $scheme = $uri_matches[2];
+ if ($scheme) {
+ $scheme = strtolower($scheme);
+ }
+
+ $scheme = $uri_matches[2];
+ if ($scheme === '') {
+ // No scheme specified
+ return null;
+ }
+
+ $scheme = strtolower($scheme);
+ if (!in_array($scheme, array('http', 'https'))) {
+ // Not an absolute HTTP or HTTPS URI
+ return null;
+ }
+
+ $authority = $uri_matches[4];
+ if ($authority === '') {
+ // Not an absolute URI
+ return null;
+ }
+
+ $authority_matches = array();
+ preg_match(Auth_OpenID_getAuthorityPattern(),
+ $authority, $authority_matches);
+ if (count($authority_matches) === 0) {
+ // URI does not have a valid authority
+ return null;
+ }
+
+ if (count($authority_matches) < 4) {
+ for ($i = count($authority_matches); $i <= 4; $i++) {
+ $authority_matches[] = '';
+ }
+ }
+
+ list($_whole, $userinfo, $host, $port) = $authority_matches;
+
+ if ($userinfo === null) {
+ $userinfo = '';
+ }
+
+ if (strpos($host, '%') !== -1) {
+ $host = strtolower($host);
+ $host = preg_replace_callback(
+ Auth_OpenID_getEncodedPattern(),
+ 'Auth_OpenID_pct_encoded_replace', $host);
+ // NO IDNA.
+ // $host = unicode($host, 'utf-8').encode('idna');
+ } else {
+ $host = strtolower($host);
+ }
+
+ if ($port) {
+ if (($port == ':') ||
+ ($scheme == 'http' && $port == ':80') ||
+ ($scheme == 'https' && $port == ':443')) {
+ $port = '';
+ }
+ } else {
+ $port = '';
+ }
+
+ $authority = $userinfo . $host . $port;
+
+ $path = $uri_matches[5];
+ $path = preg_replace_callback(
+ Auth_OpenID_getEncodedPattern(),
+ 'Auth_OpenID_pct_encoded_replace_unreserved', $path);
+
+ $path = Auth_OpenID_remove_dot_segments($path);
+ if (!$path) {
+ $path = '/';
+ }
+
+ $query = $uri_matches[6];
+ if ($query === null) {
+ $query = '';
+ }
+
+ $fragment = $uri_matches[8];
+ if ($fragment === null) {
+ $fragment = '';
+ }
+
+ return $scheme . '://' . $authority . $path . $query . $fragment;
+}
+
+
diff --git a/plugins/openid/lib/Auth/Yadis/HTTPFetcher.php b/plugins/openid/lib/Auth/Yadis/HTTPFetcher.php
new file mode 100644
index 00000000..148cde1b
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/HTTPFetcher.php
@@ -0,0 +1,174 @@
+<?php
+
+/**
+ * This module contains the HTTP fetcher interface
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Require logging functionality
+ */
+require_once "Auth/OpenID.php";
+
+define('Auth_OpenID_FETCHER_MAX_RESPONSE_KB', 1024);
+define('Auth_OpenID_USER_AGENT',
+ 'php-openid/'.Auth_OpenID_VERSION.' (php/'.phpversion().')');
+
+class Auth_Yadis_HTTPResponse {
+ function Auth_Yadis_HTTPResponse($final_url = null, $status = null,
+ $headers = null, $body = null)
+ {
+ $this->final_url = $final_url;
+ $this->status = $status;
+ $this->headers = $headers;
+ $this->body = $body;
+ }
+}
+
+/**
+ * This class is the interface for HTTP fetchers the Yadis library
+ * uses. This interface is only important if you need to write a new
+ * fetcher for some reason.
+ *
+ * @access private
+ * @package OpenID
+ */
+class Auth_Yadis_HTTPFetcher {
+
+ var $timeout = 20; // timeout in seconds.
+
+ /**
+ * Return whether a URL can be fetched. Returns false if the URL
+ * scheme is not allowed or is not supported by this fetcher
+ * implementation; returns true otherwise.
+ *
+ * @return bool
+ */
+ function canFetchURL($url)
+ {
+ if ($this->isHTTPS($url) && !$this->supportsSSL()) {
+ Auth_OpenID::log("HTTPS URL unsupported fetching %s",
+ $url);
+ return false;
+ }
+
+ if (!$this->allowedURL($url)) {
+ Auth_OpenID::log("URL fetching not allowed for '%s'",
+ $url);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return whether a URL should be allowed. Override this method to
+ * conform to your local policy.
+ *
+ * By default, will attempt to fetch any http or https URL.
+ */
+ function allowedURL($url)
+ {
+ return $this->URLHasAllowedScheme($url);
+ }
+
+ /**
+ * Does this fetcher implementation (and runtime) support fetching
+ * HTTPS URLs? May inspect the runtime environment.
+ *
+ * @return bool $support True if this fetcher supports HTTPS
+ * fetching; false if not.
+ */
+ function supportsSSL()
+ {
+ trigger_error("not implemented", E_USER_ERROR);
+ }
+
+ /**
+ * Is this an https URL?
+ *
+ * @access private
+ */
+ function isHTTPS($url)
+ {
+ return (bool)preg_match('/^https:\/\//i', $url);
+ }
+
+ /**
+ * Is this an http or https URL?
+ *
+ * @access private
+ */
+ function URLHasAllowedScheme($url)
+ {
+ return (bool)preg_match('/^https?:\/\//i', $url);
+ }
+
+ /**
+ * @access private
+ */
+ function _findRedirect($headers, $url)
+ {
+ foreach ($headers as $line) {
+ if (strpos(strtolower($line), "location: ") === 0) {
+ $parts = explode(" ", $line, 2);
+ $loc = $parts[1];
+ $ppos = strpos($loc, "://");
+ if ($ppos === false || $ppos > strpos($loc, "/")) {
+ /* no host; add it */
+ $hpos = strpos($url, "://");
+ $prt = substr($url, 0, $hpos+3);
+ $url = substr($url, $hpos+3);
+ if (substr($loc, 0, 1) == "/") {
+ /* absolute path */
+ $fspos = strpos($url, "/");
+ if ($fspos) $loc = $prt.substr($url, 0, $fspos).$loc;
+ else $loc = $prt.$url.$loc;
+ } else {
+ /* relative path */
+ $pp = $prt;
+ while (1) {
+ $xpos = strpos($url, "/");
+ if ($xpos === false) break;
+ $apos = strpos($url, "?");
+ if ($apos !== false && $apos < $xpos) break;
+ $apos = strpos($url, "&");
+ if ($apos !== false && $apos < $xpos) break;
+ $pp .= substr($url, 0, $xpos+1);
+ $url = substr($url, $xpos+1);
+ }
+ $loc = $pp.$loc;
+ }
+ }
+ return $loc;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Fetches the specified URL using optional extra headers and
+ * returns the server's response.
+ *
+ * @param string $url The URL to be fetched.
+ * @param array $extra_headers An array of header strings
+ * (e.g. "Accept: text/html").
+ * @return mixed $result An array of ($code, $url, $headers,
+ * $body) if the URL could be fetched; null if the URL does not
+ * pass the URLHasAllowedScheme check or if the server's response
+ * is malformed.
+ */
+ function get($url, $headers = null)
+ {
+ trigger_error("not implemented", E_USER_ERROR);
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/Yadis/Manager.php b/plugins/openid/lib/Auth/Yadis/Manager.php
new file mode 100644
index 00000000..3f54fd0b
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/Manager.php
@@ -0,0 +1,523 @@
+<?php
+
+/**
+ * Yadis service manager to be used during yadis-driven authentication
+ * attempts.
+ *
+ * @package OpenID
+ */
+
+/**
+ * The base session class used by the Auth_Yadis_Manager. This
+ * class wraps the default PHP session machinery and should be
+ * subclassed if your application doesn't use PHP sessioning.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_PHPSession {
+ /**
+ * Set a session key/value pair.
+ *
+ * @param string $name The name of the session key to add.
+ * @param string $value The value to add to the session.
+ */
+ function set($name, $value)
+ {
+ $_SESSION[$name] = $value;
+ }
+
+ /**
+ * Get a key's value from the session.
+ *
+ * @param string $name The name of the key to retrieve.
+ * @param string $default The optional value to return if the key
+ * is not found in the session.
+ * @return string $result The key's value in the session or
+ * $default if it isn't found.
+ */
+ function get($name, $default=null)
+ {
+ if (array_key_exists($name, $_SESSION)) {
+ return $_SESSION[$name];
+ } else {
+ return $default;
+ }
+ }
+
+ /**
+ * Remove a key/value pair from the session.
+ *
+ * @param string $name The name of the key to remove.
+ */
+ function del($name)
+ {
+ unset($_SESSION[$name]);
+ }
+
+ /**
+ * Return the contents of the session in array form.
+ */
+ function contents()
+ {
+ return $_SESSION;
+ }
+}
+
+/**
+ * A session helper class designed to translate between arrays and
+ * objects. Note that the class used must have a constructor that
+ * takes no parameters. This is not a general solution, but it works
+ * for dumb objects that just need to have attributes set. The idea
+ * is that you'll subclass this and override $this->check($data) ->
+ * bool to implement your own session data validation.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_SessionLoader {
+ /**
+ * Override this.
+ *
+ * @access private
+ */
+ function check($data)
+ {
+ return true;
+ }
+
+ /**
+ * Given a session data value (an array), this creates an object
+ * (returned by $this->newObject()) whose attributes and values
+ * are those in $data. Returns null if $data lacks keys found in
+ * $this->requiredKeys(). Returns null if $this->check($data)
+ * evaluates to false. Returns null if $this->newObject()
+ * evaluates to false.
+ *
+ * @access private
+ */
+ function fromSession($data)
+ {
+ if (!$data) {
+ return null;
+ }
+
+ $required = $this->requiredKeys();
+
+ foreach ($required as $k) {
+ if (!array_key_exists($k, $data)) {
+ return null;
+ }
+ }
+
+ if (!$this->check($data)) {
+ return null;
+ }
+
+ $data = array_merge($data, $this->prepareForLoad($data));
+ $obj = $this->newObject($data);
+
+ if (!$obj) {
+ return null;
+ }
+
+ foreach ($required as $k) {
+ $obj->$k = $data[$k];
+ }
+
+ return $obj;
+ }
+
+ /**
+ * Prepares the data array by making any necessary changes.
+ * Returns an array whose keys and values will be used to update
+ * the original data array before calling $this->newObject($data).
+ *
+ * @access private
+ */
+ function prepareForLoad($data)
+ {
+ return array();
+ }
+
+ /**
+ * Returns a new instance of this loader's class, using the
+ * session data to construct it if necessary. The object need
+ * only be created; $this->fromSession() will take care of setting
+ * the object's attributes.
+ *
+ * @access private
+ */
+ function newObject($data)
+ {
+ return null;
+ }
+
+ /**
+ * Returns an array of keys and values built from the attributes
+ * of $obj. If $this->prepareForSave($obj) returns an array, its keys
+ * and values are used to update the $data array of attributes
+ * from $obj.
+ *
+ * @access private
+ */
+ function toSession($obj)
+ {
+ $data = array();
+ foreach ($obj as $k => $v) {
+ $data[$k] = $v;
+ }
+
+ $extra = $this->prepareForSave($obj);
+
+ if ($extra && is_array($extra)) {
+ foreach ($extra as $k => $v) {
+ $data[$k] = $v;
+ }
+ }
+
+ return $data;
+ }
+
+ /**
+ * Override this.
+ *
+ * @access private
+ */
+ function prepareForSave($obj)
+ {
+ return array();
+ }
+}
+
+/**
+ * A concrete loader implementation for Auth_OpenID_ServiceEndpoints.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_ServiceEndpointLoader extends Auth_Yadis_SessionLoader {
+ function newObject($data)
+ {
+ return new Auth_OpenID_ServiceEndpoint();
+ }
+
+ function requiredKeys()
+ {
+ $obj = new Auth_OpenID_ServiceEndpoint();
+ $data = array();
+ foreach ($obj as $k => $v) {
+ $data[] = $k;
+ }
+ return $data;
+ }
+
+ function check($data)
+ {
+ return is_array($data['type_uris']);
+ }
+}
+
+/**
+ * A concrete loader implementation for Auth_Yadis_Managers.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_ManagerLoader extends Auth_Yadis_SessionLoader {
+ function requiredKeys()
+ {
+ return array('starting_url',
+ 'yadis_url',
+ 'services',
+ 'session_key',
+ '_current',
+ 'stale');
+ }
+
+ function newObject($data)
+ {
+ return new Auth_Yadis_Manager($data['starting_url'],
+ $data['yadis_url'],
+ $data['services'],
+ $data['session_key']);
+ }
+
+ function check($data)
+ {
+ return is_array($data['services']);
+ }
+
+ function prepareForLoad($data)
+ {
+ $loader = new Auth_OpenID_ServiceEndpointLoader();
+ $services = array();
+ foreach ($data['services'] as $s) {
+ $services[] = $loader->fromSession($s);
+ }
+ return array('services' => $services);
+ }
+
+ function prepareForSave($obj)
+ {
+ $loader = new Auth_OpenID_ServiceEndpointLoader();
+ $services = array();
+ foreach ($obj->services as $s) {
+ $services[] = $loader->toSession($s);
+ }
+ return array('services' => $services);
+ }
+}
+
+/**
+ * The Yadis service manager which stores state in a session and
+ * iterates over <Service> elements in a Yadis XRDS document and lets
+ * a caller attempt to use each one. This is used by the Yadis
+ * library internally.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_Manager {
+
+ /**
+ * Intialize a new yadis service manager.
+ *
+ * @access private
+ */
+ function Auth_Yadis_Manager($starting_url, $yadis_url,
+ $services, $session_key)
+ {
+ // The URL that was used to initiate the Yadis protocol
+ $this->starting_url = $starting_url;
+
+ // The URL after following redirects (the identifier)
+ $this->yadis_url = $yadis_url;
+
+ // List of service elements
+ $this->services = $services;
+
+ $this->session_key = $session_key;
+
+ // Reference to the current service object
+ $this->_current = null;
+
+ // Stale flag for cleanup if PHP lib has trouble.
+ $this->stale = false;
+ }
+
+ /**
+ * @access private
+ */
+ function length()
+ {
+ // How many untried services remain?
+ return count($this->services);
+ }
+
+ /**
+ * Return the next service
+ *
+ * $this->current() will continue to return that service until the
+ * next call to this method.
+ */
+ function nextService()
+ {
+
+ if ($this->services) {
+ $this->_current = array_shift($this->services);
+ } else {
+ $this->_current = null;
+ }
+
+ return $this->_current;
+ }
+
+ /**
+ * @access private
+ */
+ function current()
+ {
+ // Return the current service.
+ // Returns None if there are no services left.
+ return $this->_current;
+ }
+
+ /**
+ * @access private
+ */
+ function forURL($url)
+ {
+ return in_array($url, array($this->starting_url, $this->yadis_url));
+ }
+
+ /**
+ * @access private
+ */
+ function started()
+ {
+ // Has the first service been returned?
+ return $this->_current !== null;
+ }
+}
+
+/**
+ * State management for discovery.
+ *
+ * High-level usage pattern is to call .getNextService(discover) in
+ * order to find the next available service for this user for this
+ * session. Once a request completes, call .cleanup() to clean up the
+ * session state.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_Discovery {
+
+ /**
+ * @access private
+ */
+ var $DEFAULT_SUFFIX = 'auth';
+
+ /**
+ * @access private
+ */
+ var $PREFIX = '_yadis_services_';
+
+ /**
+ * Initialize a discovery object.
+ *
+ * @param Auth_Yadis_PHPSession $session An object which
+ * implements the Auth_Yadis_PHPSession API.
+ * @param string $url The URL on which to attempt discovery.
+ * @param string $session_key_suffix The optional session key
+ * suffix override.
+ */
+ function Auth_Yadis_Discovery($session, $url,
+ $session_key_suffix = null)
+ {
+ /// Initialize a discovery object
+ $this->session = $session;
+ $this->url = $url;
+ if ($session_key_suffix === null) {
+ $session_key_suffix = $this->DEFAULT_SUFFIX;
+ }
+
+ $this->session_key_suffix = $session_key_suffix;
+ $this->session_key = $this->PREFIX . $this->session_key_suffix;
+ }
+
+ /**
+ * Return the next authentication service for the pair of
+ * user_input and session. This function handles fallback.
+ */
+ function getNextService($discover_cb, $fetcher)
+ {
+ $manager = $this->getManager();
+ if (!$manager || (!$manager->services)) {
+ $this->destroyManager();
+
+ list($yadis_url, $services) = call_user_func_array($discover_cb,
+ array(
+ $this->url,
+ &$fetcher,
+ ));
+
+ $manager = $this->createManager($services, $yadis_url);
+ }
+
+ if ($manager) {
+ $loader = new Auth_Yadis_ManagerLoader();
+ $service = $manager->nextService();
+ $this->session->set($this->session_key,
+ serialize($loader->toSession($manager)));
+ } else {
+ $service = null;
+ }
+
+ return $service;
+ }
+
+ /**
+ * Clean up Yadis-related services in the session and return the
+ * most-recently-attempted service from the manager, if one
+ * exists.
+ *
+ * @param $force True if the manager should be deleted regardless
+ * of whether it's a manager for $this->url.
+ */
+ function cleanup($force=false)
+ {
+ $manager = $this->getManager($force);
+ if ($manager) {
+ $service = $manager->current();
+ $this->destroyManager($force);
+ } else {
+ $service = null;
+ }
+
+ return $service;
+ }
+
+ /**
+ * @access private
+ */
+ function getSessionKey()
+ {
+ // Get the session key for this starting URL and suffix
+ return $this->PREFIX . $this->session_key_suffix;
+ }
+
+ /**
+ * @access private
+ *
+ * @param $force True if the manager should be returned regardless
+ * of whether it's a manager for $this->url.
+ */
+ function getManager($force=false)
+ {
+ // Extract the YadisServiceManager for this object's URL and
+ // suffix from the session.
+
+ $manager_str = $this->session->get($this->getSessionKey());
+ $manager = null;
+
+ if ($manager_str !== null) {
+ $loader = new Auth_Yadis_ManagerLoader();
+ $manager = $loader->fromSession(unserialize($manager_str));
+ }
+
+ if ($manager && ($manager->forURL($this->url) || $force)) {
+ return $manager;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function createManager($services, $yadis_url = null)
+ {
+ $key = $this->getSessionKey();
+ if ($this->getManager()) {
+ return $this->getManager();
+ }
+
+ if ($services) {
+ $loader = new Auth_Yadis_ManagerLoader();
+ $manager = new Auth_Yadis_Manager($this->url, $yadis_url,
+ $services, $key);
+ $this->session->set($this->session_key,
+ serialize($loader->toSession($manager)));
+ return $manager;
+ }
+ }
+
+ /**
+ * @access private
+ *
+ * @param $force True if the manager should be deleted regardless
+ * of whether it's a manager for $this->url.
+ */
+ function destroyManager($force=false)
+ {
+ if ($this->getManager($force) !== null) {
+ $key = $this->getSessionKey();
+ $this->session->del($key);
+ }
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/Yadis/Misc.php b/plugins/openid/lib/Auth/Yadis/Misc.php
new file mode 100644
index 00000000..a5afa8e9
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/Misc.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * Miscellaneous utility values and functions for OpenID and Yadis.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+function Auth_Yadis_getUCSChars()
+{
+ return array(
+ array(0xA0, 0xD7FF),
+ array(0xF900, 0xFDCF),
+ array(0xFDF0, 0xFFEF),
+ array(0x10000, 0x1FFFD),
+ array(0x20000, 0x2FFFD),
+ array(0x30000, 0x3FFFD),
+ array(0x40000, 0x4FFFD),
+ array(0x50000, 0x5FFFD),
+ array(0x60000, 0x6FFFD),
+ array(0x70000, 0x7FFFD),
+ array(0x80000, 0x8FFFD),
+ array(0x90000, 0x9FFFD),
+ array(0xA0000, 0xAFFFD),
+ array(0xB0000, 0xBFFFD),
+ array(0xC0000, 0xCFFFD),
+ array(0xD0000, 0xDFFFD),
+ array(0xE1000, 0xEFFFD)
+ );
+}
+
+function Auth_Yadis_getIPrivateChars()
+{
+ return array(
+ array(0xE000, 0xF8FF),
+ array(0xF0000, 0xFFFFD),
+ array(0x100000, 0x10FFFD)
+ );
+}
+
+function Auth_Yadis_pct_escape_unicode($char_match)
+{
+ $c = $char_match[0];
+ $result = "";
+ for ($i = 0; $i < strlen($c); $i++) {
+ $result .= "%".sprintf("%X", ord($c[$i]));
+ }
+ return $result;
+}
+
+function Auth_Yadis_startswith($s, $stuff)
+{
+ return strpos($s, $stuff) === 0;
+}
+
diff --git a/plugins/openid/lib/Auth/Yadis/ParanoidHTTPFetcher.php b/plugins/openid/lib/Auth/Yadis/ParanoidHTTPFetcher.php
new file mode 100644
index 00000000..4848a2bd
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/ParanoidHTTPFetcher.php
@@ -0,0 +1,273 @@
+<?php
+
+/**
+ * This module contains the CURL-based HTTP fetcher implementation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Interface import
+ */
+require_once "Auth/Yadis/HTTPFetcher.php";
+
+require_once "Auth/OpenID.php";
+
+/**
+ * A paranoid {@link Auth_Yadis_HTTPFetcher} class which uses CURL
+ * for fetching.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_ParanoidHTTPFetcher extends Auth_Yadis_HTTPFetcher {
+ function Auth_Yadis_ParanoidHTTPFetcher()
+ {
+ $this->reset();
+ }
+
+ function reset()
+ {
+ $this->headers = array();
+ $this->data = "";
+ }
+
+ /**
+ * @access private
+ */
+ function _writeHeader($ch, $header)
+ {
+ array_push($this->headers, rtrim($header));
+ return strlen($header);
+ }
+
+ /**
+ * @access private
+ */
+ function _writeData($ch, $data)
+ {
+ if (strlen($this->data) > 1024*Auth_OpenID_FETCHER_MAX_RESPONSE_KB) {
+ return 0;
+ } else {
+ $this->data .= $data;
+ return strlen($data);
+ }
+ }
+
+ /**
+ * Does this fetcher support SSL URLs?
+ */
+ function supportsSSL()
+ {
+ $v = curl_version();
+ if(is_array($v)) {
+ return in_array('https', $v['protocols']);
+ } elseif (is_string($v)) {
+ return preg_match('/OpenSSL/i', $v);
+ } else {
+ return 0;
+ }
+ }
+
+ function get($url, $extra_headers = null)
+ {
+ if (!$this->canFetchURL($url)) {
+ return null;
+ }
+
+ $stop = time() + $this->timeout;
+ $off = $this->timeout;
+
+ $redir = true;
+
+ while ($redir && ($off > 0)) {
+ $this->reset();
+
+ $c = curl_init();
+
+ if ($c === false) {
+ Auth_OpenID::log(
+ "curl_init returned false; could not " .
+ "initialize for URL '%s'", $url);
+ return null;
+ }
+
+ if (defined('CURLOPT_NOSIGNAL')) {
+ curl_setopt($c, CURLOPT_NOSIGNAL, true);
+ }
+
+ if (!$this->allowedURL($url)) {
+ Auth_OpenID::log("Fetching URL not allowed: %s",
+ $url);
+ return null;
+ }
+
+ curl_setopt($c, CURLOPT_WRITEFUNCTION,
+ array($this, "_writeData"));
+ curl_setopt($c, CURLOPT_HEADERFUNCTION,
+ array($this, "_writeHeader"));
+
+ if ($extra_headers) {
+ curl_setopt($c, CURLOPT_HTTPHEADER, $extra_headers);
+ }
+
+ $cv = curl_version();
+ if(is_array($cv)) {
+ $curl_user_agent = 'curl/'.$cv['version'];
+ } else {
+ $curl_user_agent = $cv;
+ }
+ curl_setopt($c, CURLOPT_USERAGENT,
+ Auth_OpenID_USER_AGENT.' '.$curl_user_agent);
+ curl_setopt($c, CURLOPT_TIMEOUT, $off);
+ curl_setopt($c, CURLOPT_URL, $url);
+
+ if (defined('Auth_OpenID_VERIFY_HOST')) {
+ // set SSL verification options only if Auth_OpenID_VERIFY_HOST
+ // is explicitly set, otherwise use system default.
+ if (Auth_OpenID_VERIFY_HOST) {
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
+ if (defined('Auth_OpenID_CAINFO')) {
+ curl_setopt($c, CURLOPT_CAINFO, Auth_OpenID_CAINFO);
+ }
+ } else {
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
+ }
+ }
+ if (defined('Auth_OpenID_HTTP_PROXY')) {
+ curl_setopt($c, CURLOPT_PROXY, Auth_OpenID_HTTP_PROXY);
+ }
+ curl_exec($c);
+
+ $code = curl_getinfo($c, CURLINFO_HTTP_CODE);
+ $body = $this->data;
+ $headers = $this->headers;
+
+ if (!$code) {
+ Auth_OpenID::log("Got no response code when fetching %s", $url);
+ Auth_OpenID::log("CURL error (%s): %s",
+ curl_errno($c), curl_error($c));
+ return null;
+ }
+
+ if (in_array($code, array(301, 302, 303, 307))) {
+ $url = $this->_findRedirect($headers, $url);
+ $redir = true;
+ } else {
+ $redir = false;
+ curl_close($c);
+
+ if (defined('Auth_OpenID_VERIFY_HOST') &&
+ Auth_OpenID_VERIFY_HOST == true &&
+ $this->isHTTPS($url)) {
+ Auth_OpenID::log('OpenID: Verified SSL host %s using '.
+ 'curl/get', $url);
+ }
+ $new_headers = array();
+
+ foreach ($headers as $header) {
+ if (strpos($header, ': ')) {
+ list($name, $value) = explode(': ', $header, 2);
+ $new_headers[$name] = $value;
+ }
+ }
+
+ Auth_OpenID::log(
+ "Successfully fetched '%s': GET response code %s",
+ $url, $code);
+
+ return new Auth_Yadis_HTTPResponse($url, $code,
+ $new_headers, $body);
+ }
+
+ $off = $stop - time();
+ }
+
+ return null;
+ }
+
+ function post($url, $body, $extra_headers = null)
+ {
+ if (!$this->canFetchURL($url)) {
+ return null;
+ }
+
+ $this->reset();
+
+ $c = curl_init();
+
+ if (defined('CURLOPT_NOSIGNAL')) {
+ curl_setopt($c, CURLOPT_NOSIGNAL, true);
+ }
+
+ if (defined('Auth_OpenID_HTTP_PROXY')) {
+ curl_setopt($c, CURLOPT_PROXY, Auth_OpenID_HTTP_PROXY);
+ }
+
+ curl_setopt($c, CURLOPT_POST, true);
+ curl_setopt($c, CURLOPT_POSTFIELDS, $body);
+ curl_setopt($c, CURLOPT_TIMEOUT, $this->timeout);
+ curl_setopt($c, CURLOPT_URL, $url);
+ curl_setopt($c, CURLOPT_WRITEFUNCTION,
+ array($this, "_writeData"));
+
+ if (defined('Auth_OpenID_VERIFY_HOST')) {
+ // set SSL verification options only if Auth_OpenID_VERIFY_HOST
+ // is explicitly set, otherwise use system default.
+ if (Auth_OpenID_VERIFY_HOST) {
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
+ if (defined('Auth_OpenID_CAINFO')) {
+ curl_setopt($c, CURLOPT_CAINFO, Auth_OpenID_CAINFO);
+ }
+ } else {
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
+ }
+ }
+
+ curl_exec($c);
+
+ $code = curl_getinfo($c, CURLINFO_HTTP_CODE);
+
+ if (!$code) {
+ Auth_OpenID::log("Got no response code when fetching %s", $url);
+ Auth_OpenID::log("CURL error (%s): %s",
+ curl_errno($c), curl_error($c));
+ return null;
+ }
+
+ if (defined('Auth_OpenID_VERIFY_HOST') &&
+ Auth_OpenID_VERIFY_HOST == true &&
+ $this->isHTTPS($url)) {
+ Auth_OpenID::log('OpenID: Verified SSL host %s using '.
+ 'curl/post', $url);
+ }
+ $body = $this->data;
+
+ curl_close($c);
+
+ $new_headers = $extra_headers;
+
+ foreach ($this->headers as $header) {
+ if (strpos($header, ': ')) {
+ list($name, $value) = explode(': ', $header, 2);
+ $new_headers[$name] = $value;
+ }
+
+ }
+
+ Auth_OpenID::log("Successfully fetched '%s': POST response code %s",
+ $url, $code);
+
+ return new Auth_Yadis_HTTPResponse($url, $code,
+ $new_headers, $body);
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/Yadis/ParseHTML.php b/plugins/openid/lib/Auth/Yadis/ParseHTML.php
new file mode 100644
index 00000000..6f0f8b7e
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/ParseHTML.php
@@ -0,0 +1,258 @@
+<?php
+
+/**
+ * This is the HTML pseudo-parser for the Yadis library.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * This class is responsible for scanning an HTML string to find META
+ * tags and their attributes. This is used by the Yadis discovery
+ * process. This class must be instantiated to be used.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_ParseHTML {
+
+ /**
+ * @access private
+ */
+ var $_re_flags = "si";
+
+ /**
+ * @access private
+ */
+ var $_removed_re =
+ "<!--.*?-->|<!\[CDATA\[.*?\]\]>|<script\b(?!:)[^>]*>.*?<\/script>";
+
+ /**
+ * @access private
+ */
+ var $_tag_expr = "<%s%s(?:\s.*?)?%s>";
+
+ /**
+ * @access private
+ */
+ var $_attr_find = '\b([-\w]+)=(".*?"|\'.*?\'|.+?)[\/\s>]';
+
+ function Auth_Yadis_ParseHTML()
+ {
+ $this->_attr_find = sprintf("/%s/%s",
+ $this->_attr_find,
+ $this->_re_flags);
+
+ $this->_removed_re = sprintf("/%s/%s",
+ $this->_removed_re,
+ $this->_re_flags);
+
+ $this->_entity_replacements = array(
+ 'amp' => '&',
+ 'lt' => '<',
+ 'gt' => '>',
+ 'quot' => '"'
+ );
+
+ $this->_ent_replace =
+ sprintf("&(%s);", implode("|",
+ $this->_entity_replacements));
+ }
+
+ /**
+ * Replace HTML entities (amp, lt, gt, and quot) as well as
+ * numeric entities (e.g. #x9f;) with their actual values and
+ * return the new string.
+ *
+ * @access private
+ * @param string $str The string in which to look for entities
+ * @return string $new_str The new string entities decoded
+ */
+ function replaceEntities($str)
+ {
+ foreach ($this->_entity_replacements as $old => $new) {
+ $str = preg_replace(sprintf("/&%s;/", $old), $new, $str);
+ }
+
+ // Replace numeric entities because html_entity_decode doesn't
+ // do it for us.
+ $str = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $str);
+ $str = preg_replace('~&#([0-9]+);~e', 'chr(\\1)', $str);
+
+ return $str;
+ }
+
+ /**
+ * Strip single and double quotes off of a string, if they are
+ * present.
+ *
+ * @access private
+ * @param string $str The original string
+ * @return string $new_str The new string with leading and
+ * trailing quotes removed
+ */
+ function removeQuotes($str)
+ {
+ $matches = array();
+ $double = '/^"(.*)"$/';
+ $single = "/^\'(.*)\'$/";
+
+ if (preg_match($double, $str, $matches)) {
+ return $matches[1];
+ } else if (preg_match($single, $str, $matches)) {
+ return $matches[1];
+ } else {
+ return $str;
+ }
+ }
+
+ /**
+ * Create a regular expression that will match an opening
+ * or closing tag from a set of names.
+ *
+ * @access private
+ * @param mixed $tag_names Tag names to match
+ * @param mixed $close false/0 = no, true/1 = yes, other = maybe
+ * @param mixed $self_close false/0 = no, true/1 = yes, other = maybe
+ * @return string $regex A regular expression string to be used
+ * in, say, preg_match.
+ */
+ function tagPattern($tag_names, $close, $self_close)
+ {
+ if (is_array($tag_names)) {
+ $tag_names = '(?:'.implode('|',$tag_names).')';
+ }
+ if ($close) {
+ $close = '\/' . (($close == 1)? '' : '?');
+ } else {
+ $close = '';
+ }
+ if ($self_close) {
+ $self_close = '(?:\/\s*)' . (($self_close == 1)? '' : '?');
+ } else {
+ $self_close = '';
+ }
+ $expr = sprintf($this->_tag_expr, $close, $tag_names, $self_close);
+
+ return sprintf("/%s/%s", $expr, $this->_re_flags);
+ }
+
+ /**
+ * Given an HTML document string, this finds all the META tags in
+ * the document, provided they are found in the
+ * <HTML><HEAD>...</HEAD> section of the document. The <HTML> tag
+ * may be missing.
+ *
+ * @access private
+ * @param string $html_string An HTMl document string
+ * @return array $tag_list Array of tags; each tag is an array of
+ * attribute -> value.
+ */
+ function getMetaTags($html_string)
+ {
+ $html_string = preg_replace($this->_removed_re,
+ "",
+ $html_string);
+
+ $key_tags = array($this->tagPattern('html', false, false),
+ $this->tagPattern('head', false, false),
+ $this->tagPattern('head', true, false),
+ $this->tagPattern('html', true, false),
+ $this->tagPattern(array(
+ 'body', 'frameset', 'frame', 'p', 'div',
+ 'table','span','a'), 'maybe', 'maybe'));
+ $key_tags_pos = array();
+ foreach ($key_tags as $pat) {
+ $matches = array();
+ preg_match($pat, $html_string, $matches, PREG_OFFSET_CAPTURE);
+ if($matches) {
+ $key_tags_pos[] = $matches[0][1];
+ } else {
+ $key_tags_pos[] = null;
+ }
+ }
+ // no opening head tag
+ if (is_null($key_tags_pos[1])) {
+ return array();
+ }
+ // the effective </head> is the min of the following
+ if (is_null($key_tags_pos[2])) {
+ $key_tags_pos[2] = strlen($html_string);
+ }
+ foreach (array($key_tags_pos[3], $key_tags_pos[4]) as $pos) {
+ if (!is_null($pos) && $pos < $key_tags_pos[2]) {
+ $key_tags_pos[2] = $pos;
+ }
+ }
+ // closing head tag comes before opening head tag
+ if ($key_tags_pos[1] > $key_tags_pos[2]) {
+ return array();
+ }
+ // if there is an opening html tag, make sure the opening head tag
+ // comes after it
+ if (!is_null($key_tags_pos[0]) && $key_tags_pos[1] < $key_tags_pos[0]) {
+ return array();
+ }
+ $html_string = substr($html_string, $key_tags_pos[1],
+ ($key_tags_pos[2]-$key_tags_pos[1]));
+
+ $link_data = array();
+ $link_matches = array();
+
+ if (!preg_match_all($this->tagPattern('meta', false, 'maybe'),
+ $html_string, $link_matches)) {
+ return array();
+ }
+
+ foreach ($link_matches[0] as $link) {
+ $attr_matches = array();
+ preg_match_all($this->_attr_find, $link, $attr_matches);
+ $link_attrs = array();
+ foreach ($attr_matches[0] as $index => $full_match) {
+ $name = $attr_matches[1][$index];
+ $value = $this->replaceEntities(
+ $this->removeQuotes($attr_matches[2][$index]));
+
+ $link_attrs[strtolower($name)] = $value;
+ }
+ $link_data[] = $link_attrs;
+ }
+
+ return $link_data;
+ }
+
+ /**
+ * Looks for a META tag with an "http-equiv" attribute whose value
+ * is one of ("x-xrds-location", "x-yadis-location"), ignoring
+ * case. If such a META tag is found, its "content" attribute
+ * value is returned.
+ *
+ * @param string $html_string An HTML document in string format
+ * @return mixed $content The "content" attribute value of the
+ * META tag, if found, or null if no such tag was found.
+ */
+ function getHTTPEquiv($html_string)
+ {
+ $meta_tags = $this->getMetaTags($html_string);
+
+ if ($meta_tags) {
+ foreach ($meta_tags as $tag) {
+ if (array_key_exists('http-equiv', $tag) &&
+ (in_array(strtolower($tag['http-equiv']),
+ array('x-xrds-location', 'x-yadis-location'))) &&
+ array_key_exists('content', $tag)) {
+ return $tag['content'];
+ }
+ }
+ }
+
+ return null;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/Yadis/PlainHTTPFetcher.php b/plugins/openid/lib/Auth/Yadis/PlainHTTPFetcher.php
new file mode 100644
index 00000000..26890539
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/PlainHTTPFetcher.php
@@ -0,0 +1,248 @@
+<?php
+
+/**
+ * This module contains the plain non-curl HTTP fetcher
+ * implementation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Interface import
+ */
+require_once "Auth/Yadis/HTTPFetcher.php";
+
+/**
+ * This class implements a plain, hand-built socket-based fetcher
+ * which will be used in the event that CURL is unavailable.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_PlainHTTPFetcher extends Auth_Yadis_HTTPFetcher {
+ /**
+ * Does this fetcher support SSL URLs?
+ */
+ function supportsSSL()
+ {
+ return function_exists('openssl_open');
+ }
+
+ function get($url, $extra_headers = null)
+ {
+ if (!$this->canFetchURL($url)) {
+ return null;
+ }
+
+ $redir = true;
+
+ $stop = time() + $this->timeout;
+ $off = $this->timeout;
+
+ while ($redir && ($off > 0)) {
+
+ $parts = parse_url($url);
+
+ $specify_port = true;
+
+ // Set a default port.
+ if (!array_key_exists('port', $parts)) {
+ $specify_port = false;
+ if ($parts['scheme'] == 'http') {
+ $parts['port'] = 80;
+ } elseif ($parts['scheme'] == 'https') {
+ $parts['port'] = 443;
+ } else {
+ return null;
+ }
+ }
+
+ if (!array_key_exists('path', $parts)) {
+ $parts['path'] = '/';
+ }
+
+ $host = $parts['host'];
+
+ if ($parts['scheme'] == 'https') {
+ $host = 'ssl://' . $host;
+ }
+
+ $user_agent = Auth_OpenID_USER_AGENT;
+
+ $headers = array(
+ "GET ".$parts['path'].
+ (array_key_exists('query', $parts) ?
+ "?".$parts['query'] : "").
+ " HTTP/1.0",
+ "User-Agent: $user_agent",
+ "Host: ".$parts['host'].
+ ($specify_port ? ":".$parts['port'] : ""),
+ "Port: ".$parts['port']);
+
+ $errno = 0;
+ $errstr = '';
+
+ if ($extra_headers) {
+ foreach ($extra_headers as $h) {
+ $headers[] = $h;
+ }
+ }
+
+ @$sock = fsockopen($host, $parts['port'], $errno, $errstr,
+ $this->timeout);
+ if ($sock === false) {
+ return false;
+ }
+
+ stream_set_timeout($sock, $this->timeout);
+
+ fputs($sock, implode("\r\n", $headers) . "\r\n\r\n");
+
+ $data = "";
+ $kilobytes = 0;
+ while (!feof($sock) &&
+ $kilobytes < Auth_OpenID_FETCHER_MAX_RESPONSE_KB ) {
+ $data .= fgets($sock, 1024);
+ $kilobytes += 1;
+ }
+
+ fclose($sock);
+
+ // Split response into header and body sections
+ list($headers, $body) = explode("\r\n\r\n", $data, 2);
+ $headers = explode("\r\n", $headers);
+
+ $http_code = explode(" ", $headers[0]);
+ $code = $http_code[1];
+
+ if (in_array($code, array('301', '302'))) {
+ $url = $this->_findRedirect($headers, $url);
+ $redir = true;
+ } else {
+ $redir = false;
+ }
+
+ $off = $stop - time();
+ }
+
+ $new_headers = array();
+
+ foreach ($headers as $header) {
+ if (preg_match("/:/", $header)) {
+ $parts = explode(": ", $header, 2);
+
+ if (count($parts) == 2) {
+ list($name, $value) = $parts;
+ $new_headers[$name] = $value;
+ }
+ }
+
+ }
+
+ return new Auth_Yadis_HTTPResponse($url, $code, $new_headers, $body);
+ }
+
+ function post($url, $body, $extra_headers = null)
+ {
+ if (!$this->canFetchURL($url)) {
+ return null;
+ }
+
+ $parts = parse_url($url);
+
+ $headers = array();
+
+ $post_path = $parts['path'];
+ if (isset($parts['query'])) {
+ $post_path .= '?' . $parts['query'];
+ }
+
+ $headers[] = "POST ".$post_path." HTTP/1.0";
+ $headers[] = "Host: " . $parts['host'];
+ $headers[] = "Content-type: application/x-www-form-urlencoded";
+ $headers[] = "Content-length: " . strval(strlen($body));
+
+ if ($extra_headers &&
+ is_array($extra_headers)) {
+ $headers = array_merge($headers, $extra_headers);
+ }
+
+ // Join all headers together.
+ $all_headers = implode("\r\n", $headers);
+
+ // Add headers, two newlines, and request body.
+ $request = $all_headers . "\r\n\r\n" . $body;
+
+ // Set a default port.
+ if (!array_key_exists('port', $parts)) {
+ if ($parts['scheme'] == 'http') {
+ $parts['port'] = 80;
+ } elseif ($parts['scheme'] == 'https') {
+ $parts['port'] = 443;
+ } else {
+ return null;
+ }
+ }
+
+ if ($parts['scheme'] == 'https') {
+ $parts['host'] = sprintf("ssl://%s", $parts['host']);
+ }
+
+ // Connect to the remote server.
+ $errno = 0;
+ $errstr = '';
+
+ $sock = fsockopen($parts['host'], $parts['port'], $errno, $errstr,
+ $this->timeout);
+
+ if ($sock === false) {
+ return null;
+ }
+
+ stream_set_timeout($sock, $this->timeout);
+
+ // Write the POST request.
+ fputs($sock, $request);
+
+ // Get the response from the server.
+ $response = "";
+ while (!feof($sock)) {
+ if ($data = fgets($sock, 128)) {
+ $response .= $data;
+ } else {
+ break;
+ }
+ }
+
+ // Split the request into headers and body.
+ list($headers, $response_body) = explode("\r\n\r\n", $response, 2);
+
+ $headers = explode("\r\n", $headers);
+
+ // Expect the first line of the headers data to be something
+ // like HTTP/1.1 200 OK. Split the line on spaces and take
+ // the second token, which should be the return code.
+ $http_code = explode(" ", $headers[0]);
+ $code = $http_code[1];
+
+ $new_headers = array();
+
+ foreach ($headers as $header) {
+ if (preg_match("/:/", $header)) {
+ list($name, $value) = explode(": ", $header, 2);
+ $new_headers[$name] = $value;
+ }
+
+ }
+
+ return new Auth_Yadis_HTTPResponse($url, $code,
+ $new_headers, $response_body);
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/Yadis/XML.php b/plugins/openid/lib/Auth/Yadis/XML.php
new file mode 100644
index 00000000..cf1f5c41
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/XML.php
@@ -0,0 +1,352 @@
+<?php
+
+/**
+ * XML-parsing classes to wrap the domxml and DOM extensions for PHP 4
+ * and 5, respectively.
+ *
+ * @package OpenID
+ */
+
+/**
+ * The base class for wrappers for available PHP XML-parsing
+ * extensions. To work with this Yadis library, subclasses of this
+ * class MUST implement the API as defined in the remarks for this
+ * class. Subclasses of Auth_Yadis_XMLParser are used to wrap
+ * particular PHP XML extensions such as 'domxml'. These are used
+ * internally by the library depending on the availability of
+ * supported PHP XML extensions.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_XMLParser {
+ /**
+ * Initialize an instance of Auth_Yadis_XMLParser with some
+ * XML and namespaces. This SHOULD NOT be overridden by
+ * subclasses.
+ *
+ * @param string $xml_string A string of XML to be parsed.
+ * @param array $namespace_map An array of ($ns_name => $ns_uri)
+ * to be registered with the XML parser. May be empty.
+ * @return boolean $result True if the initialization and
+ * namespace registration(s) succeeded; false otherwise.
+ */
+ function init($xml_string, $namespace_map)
+ {
+ if (!$this->setXML($xml_string)) {
+ return false;
+ }
+
+ foreach ($namespace_map as $prefix => $uri) {
+ if (!$this->registerNamespace($prefix, $uri)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Register a namespace with the XML parser. This should be
+ * overridden by subclasses.
+ *
+ * @param string $prefix The namespace prefix to appear in XML tag
+ * names.
+ *
+ * @param string $uri The namespace URI to be used to identify the
+ * namespace in the XML.
+ *
+ * @return boolean $result True if the registration succeeded;
+ * false otherwise.
+ */
+ function registerNamespace($prefix, $uri)
+ {
+ // Not implemented.
+ }
+
+ /**
+ * Set this parser object's XML payload. This should be
+ * overridden by subclasses.
+ *
+ * @param string $xml_string The XML string to pass to this
+ * object's XML parser.
+ *
+ * @return boolean $result True if the initialization succeeded;
+ * false otherwise.
+ */
+ function setXML($xml_string)
+ {
+ // Not implemented.
+ }
+
+ /**
+ * Evaluate an XPath expression and return the resulting node
+ * list. This should be overridden by subclasses.
+ *
+ * @param string $xpath The XPath expression to be evaluated.
+ *
+ * @param mixed $node A node object resulting from a previous
+ * evalXPath call. This node, if specified, provides the context
+ * for the evaluation of this xpath expression.
+ *
+ * @return array $node_list An array of matching opaque node
+ * objects to be used with other methods of this parser class.
+ */
+ function &evalXPath($xpath, $node = null)
+ {
+ // Not implemented.
+ }
+
+ /**
+ * Return the textual content of a specified node.
+ *
+ * @param mixed $node A node object from a previous call to
+ * $this->evalXPath().
+ *
+ * @return string $content The content of this node.
+ */
+ function content($node)
+ {
+ // Not implemented.
+ }
+
+ /**
+ * Return the attributes of a specified node.
+ *
+ * @param mixed $node A node object from a previous call to
+ * $this->evalXPath().
+ *
+ * @return array $attrs An array mapping attribute names to
+ * values.
+ */
+ function attributes($node)
+ {
+ // Not implemented.
+ }
+}
+
+/**
+ * This concrete implementation of Auth_Yadis_XMLParser implements
+ * the appropriate API for the 'domxml' extension which is typically
+ * packaged with PHP 4. This class will be used whenever the 'domxml'
+ * extension is detected. See the Auth_Yadis_XMLParser class for
+ * details on this class's methods.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_domxml extends Auth_Yadis_XMLParser {
+ function Auth_Yadis_domxml()
+ {
+ $this->xml = null;
+ $this->doc = null;
+ $this->xpath = null;
+ $this->errors = array();
+ }
+
+ function setXML($xml_string)
+ {
+ $this->xml = $xml_string;
+ $this->doc = @domxml_open_mem($xml_string, DOMXML_LOAD_PARSING,
+ $this->errors);
+
+ if (!$this->doc) {
+ return false;
+ }
+
+ $this->xpath = $this->doc->xpath_new_context();
+
+ return true;
+ }
+
+ function registerNamespace($prefix, $uri)
+ {
+ return xpath_register_ns($this->xpath, $prefix, $uri);
+ }
+
+ function &evalXPath($xpath, $node = null)
+ {
+ if ($node) {
+ $result = @$this->xpath->xpath_eval($xpath, $node);
+ } else {
+ $result = @$this->xpath->xpath_eval($xpath);
+ }
+
+ if (!$result) {
+ $n = array();
+ return $n;
+ }
+
+ if (!$result->nodeset) {
+ $n = array();
+ return $n;
+ }
+
+ return $result->nodeset;
+ }
+
+ function content($node)
+ {
+ if ($node) {
+ return $node->get_content();
+ }
+ }
+
+ function attributes($node)
+ {
+ if ($node) {
+ $arr = $node->attributes();
+ $result = array();
+
+ if ($arr) {
+ foreach ($arr as $attrnode) {
+ $result[$attrnode->name] = $attrnode->value;
+ }
+ }
+
+ return $result;
+ }
+ }
+}
+
+/**
+ * This concrete implementation of Auth_Yadis_XMLParser implements
+ * the appropriate API for the 'dom' extension which is typically
+ * packaged with PHP 5. This class will be used whenever the 'dom'
+ * extension is detected. See the Auth_Yadis_XMLParser class for
+ * details on this class's methods.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_dom extends Auth_Yadis_XMLParser {
+ function Auth_Yadis_dom()
+ {
+ $this->xml = null;
+ $this->doc = null;
+ $this->xpath = null;
+ $this->errors = array();
+ }
+
+ function setXML($xml_string)
+ {
+ $this->xml = $xml_string;
+ $this->doc = new DOMDocument;
+
+ if (!$this->doc) {
+ return false;
+ }
+
+ if (!@$this->doc->loadXML($xml_string)) {
+ return false;
+ }
+
+ $this->xpath = new DOMXPath($this->doc);
+
+ if ($this->xpath) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function registerNamespace($prefix, $uri)
+ {
+ return $this->xpath->registerNamespace($prefix, $uri);
+ }
+
+ function &evalXPath($xpath, $node = null)
+ {
+ if ($node) {
+ $result = @$this->xpath->query($xpath, $node);
+ } else {
+ $result = @$this->xpath->query($xpath);
+ }
+
+ $n = array();
+
+ if (!$result) {
+ return $n;
+ }
+
+ for ($i = 0; $i < $result->length; $i++) {
+ $n[] = $result->item($i);
+ }
+
+ return $n;
+ }
+
+ function content($node)
+ {
+ if ($node) {
+ return $node->textContent;
+ }
+ }
+
+ function attributes($node)
+ {
+ if ($node) {
+ $arr = $node->attributes;
+ $result = array();
+
+ if ($arr) {
+ for ($i = 0; $i < $arr->length; $i++) {
+ $node = $arr->item($i);
+ $result[$node->nodeName] = $node->nodeValue;
+ }
+ }
+
+ return $result;
+ }
+ }
+}
+
+global $__Auth_Yadis_defaultParser;
+$__Auth_Yadis_defaultParser = null;
+
+/**
+ * Set a default parser to override the extension-driven selection of
+ * available parser classes. This is helpful in a test environment or
+ * one in which multiple parsers can be used but one is more
+ * desirable.
+ *
+ * @param Auth_Yadis_XMLParser $parser An instance of a
+ * Auth_Yadis_XMLParser subclass.
+ */
+function Auth_Yadis_setDefaultParser($parser)
+{
+ global $__Auth_Yadis_defaultParser;
+ $__Auth_Yadis_defaultParser = $parser;
+}
+
+function Auth_Yadis_getSupportedExtensions()
+{
+ return array('dom' => 'Auth_Yadis_dom',
+ 'domxml' => 'Auth_Yadis_domxml');
+}
+
+/**
+ * Returns an instance of a Auth_Yadis_XMLParser subclass based on
+ * the availability of PHP extensions for XML parsing. If
+ * Auth_Yadis_setDefaultParser has been called, the parser used in
+ * that call will be returned instead.
+ */
+function Auth_Yadis_getXMLParser()
+{
+ global $__Auth_Yadis_defaultParser;
+
+ if (isset($__Auth_Yadis_defaultParser)) {
+ return $__Auth_Yadis_defaultParser;
+ }
+
+ foreach(Auth_Yadis_getSupportedExtensions() as $extension => $classname)
+ {
+ if (extension_loaded($extension))
+ {
+ $p = new $classname();
+ Auth_Yadis_setDefaultParser($p);
+ return $p;
+ }
+ }
+
+ return false;
+}
+
+
diff --git a/plugins/openid/lib/Auth/Yadis/XRDS.php b/plugins/openid/lib/Auth/Yadis/XRDS.php
new file mode 100644
index 00000000..1f5af96f
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/XRDS.php
@@ -0,0 +1,478 @@
+<?php
+
+/**
+ * This module contains the XRDS parsing code.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Require the XPath implementation.
+ */
+require_once 'Auth/Yadis/XML.php';
+
+/**
+ * This match mode means a given service must match ALL filters passed
+ * to the Auth_Yadis_XRDS::services() call.
+ */
+define('SERVICES_YADIS_MATCH_ALL', 101);
+
+/**
+ * This match mode means a given service must match ANY filters (at
+ * least one) passed to the Auth_Yadis_XRDS::services() call.
+ */
+define('SERVICES_YADIS_MATCH_ANY', 102);
+
+/**
+ * The priority value used for service elements with no priority
+ * specified.
+ */
+define('SERVICES_YADIS_MAX_PRIORITY', pow(2, 30));
+
+/**
+ * XRD XML namespace
+ */
+define('Auth_Yadis_XMLNS_XRD_2_0', 'xri://$xrd*($v*2.0)');
+
+/**
+ * XRDS XML namespace
+ */
+define('Auth_Yadis_XMLNS_XRDS', 'xri://$xrds');
+
+function Auth_Yadis_getNSMap()
+{
+ return array('xrds' => Auth_Yadis_XMLNS_XRDS,
+ 'xrd' => Auth_Yadis_XMLNS_XRD_2_0);
+}
+
+/**
+ * @access private
+ */
+function Auth_Yadis_array_scramble($arr)
+{
+ $result = array();
+
+ while (count($arr)) {
+ $index = array_rand($arr, 1);
+ $result[] = $arr[$index];
+ unset($arr[$index]);
+ }
+
+ return $result;
+}
+
+/**
+ * This class represents a <Service> element in an XRDS document.
+ * Objects of this type are returned by
+ * Auth_Yadis_XRDS::services() and
+ * Auth_Yadis_Yadis::services(). Each object corresponds directly
+ * to a <Service> element in the XRDS and supplies a
+ * getElements($name) method which you should use to inspect the
+ * element's contents. See {@link Auth_Yadis_Yadis} for more
+ * information on the role this class plays in Yadis discovery.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_Service {
+
+ /**
+ * Creates an empty service object.
+ */
+ function Auth_Yadis_Service()
+ {
+ $this->element = null;
+ $this->parser = null;
+ }
+
+ /**
+ * Return the URIs in the "Type" elements, if any, of this Service
+ * element.
+ *
+ * @return array $type_uris An array of Type URI strings.
+ */
+ function getTypes()
+ {
+ $t = array();
+ foreach ($this->getElements('xrd:Type') as $elem) {
+ $c = $this->parser->content($elem);
+ if ($c) {
+ $t[] = $c;
+ }
+ }
+ return $t;
+ }
+
+ function matchTypes($type_uris)
+ {
+ $result = array();
+
+ foreach ($this->getTypes() as $typ) {
+ if (in_array($typ, $type_uris)) {
+ $result[] = $typ;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Return the URIs in the "URI" elements, if any, of this Service
+ * element. The URIs are returned sorted in priority order.
+ *
+ * @return array $uris An array of URI strings.
+ */
+ function getURIs()
+ {
+ $uris = array();
+ $last = array();
+
+ foreach ($this->getElements('xrd:URI') as $elem) {
+ $uri_string = $this->parser->content($elem);
+ $attrs = $this->parser->attributes($elem);
+ if ($attrs &&
+ array_key_exists('priority', $attrs)) {
+ $priority = intval($attrs['priority']);
+ if (!array_key_exists($priority, $uris)) {
+ $uris[$priority] = array();
+ }
+
+ $uris[$priority][] = $uri_string;
+ } else {
+ $last[] = $uri_string;
+ }
+ }
+
+ $keys = array_keys($uris);
+ sort($keys);
+
+ // Rebuild array of URIs.
+ $result = array();
+ foreach ($keys as $k) {
+ $new_uris = Auth_Yadis_array_scramble($uris[$k]);
+ $result = array_merge($result, $new_uris);
+ }
+
+ $result = array_merge($result,
+ Auth_Yadis_array_scramble($last));
+
+ return $result;
+ }
+
+ /**
+ * Returns the "priority" attribute value of this <Service>
+ * element, if the attribute is present. Returns null if not.
+ *
+ * @return mixed $result Null or integer, depending on whether
+ * this Service element has a 'priority' attribute.
+ */
+ function getPriority()
+ {
+ $attributes = $this->parser->attributes($this->element);
+
+ if (array_key_exists('priority', $attributes)) {
+ return intval($attributes['priority']);
+ }
+
+ return null;
+ }
+
+ /**
+ * Used to get XML elements from this object's <Service> element.
+ *
+ * This is what you should use to get all custom information out
+ * of this element. This is used by service filter functions to
+ * determine whether a service element contains specific tags,
+ * etc. NOTE: this only considers elements which are direct
+ * children of the <Service> element for this object.
+ *
+ * @param string $name The name of the element to look for
+ * @return array $list An array of elements with the specified
+ * name which are direct children of the <Service> element. The
+ * nodes returned by this function can be passed to $this->parser
+ * methods (see {@link Auth_Yadis_XMLParser}).
+ */
+ function getElements($name)
+ {
+ return $this->parser->evalXPath($name, $this->element);
+ }
+}
+
+/*
+ * Return the expiration date of this XRD element, or None if no
+ * expiration was specified.
+ *
+ * @param $default The value to use as the expiration if no expiration
+ * was specified in the XRD.
+ */
+function Auth_Yadis_getXRDExpiration($xrd_element, $default=null)
+{
+ $expires_element = $xrd_element->$parser->evalXPath('/xrd:Expires');
+ if ($expires_element === null) {
+ return $default;
+ } else {
+ $expires_string = $expires_element->text;
+
+ // Will raise ValueError if the string is not the expected
+ // format
+ $t = strptime($expires_string, "%Y-%m-%dT%H:%M:%SZ");
+
+ if ($t === false) {
+ return false;
+ }
+
+ // [int $hour [, int $minute [, int $second [,
+ // int $month [, int $day [, int $year ]]]]]]
+ return mktime($t['tm_hour'], $t['tm_min'], $t['tm_sec'],
+ $t['tm_mon'], $t['tm_day'], $t['tm_year']);
+ }
+}
+
+/**
+ * This class performs parsing of XRDS documents.
+ *
+ * You should not instantiate this class directly; rather, call
+ * parseXRDS statically:
+ *
+ * <pre> $xrds = Auth_Yadis_XRDS::parseXRDS($xml_string);</pre>
+ *
+ * If the XRDS can be parsed and is valid, an instance of
+ * Auth_Yadis_XRDS will be returned. Otherwise, null will be
+ * returned. This class is used by the Auth_Yadis_Yadis::discover
+ * method.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_XRDS {
+
+ /**
+ * Instantiate a Auth_Yadis_XRDS object. Requires an XPath
+ * instance which has been used to parse a valid XRDS document.
+ */
+ function Auth_Yadis_XRDS($xmlParser, $xrdNodes)
+ {
+ $this->parser = $xmlParser;
+ $this->xrdNode = $xrdNodes[count($xrdNodes) - 1];
+ $this->allXrdNodes = $xrdNodes;
+ $this->serviceList = array();
+ $this->_parse();
+ }
+
+ /**
+ * Parse an XML string (XRDS document) and return either a
+ * Auth_Yadis_XRDS object or null, depending on whether the
+ * XRDS XML is valid.
+ *
+ * @param string $xml_string An XRDS XML string.
+ * @return mixed $xrds An instance of Auth_Yadis_XRDS or null,
+ * depending on the validity of $xml_string
+ */
+ static function parseXRDS($xml_string, $extra_ns_map = null)
+ {
+ $_null = null;
+
+ if (!$xml_string) {
+ return $_null;
+ }
+
+ $parser = Auth_Yadis_getXMLParser();
+
+ $ns_map = Auth_Yadis_getNSMap();
+
+ if ($extra_ns_map && is_array($extra_ns_map)) {
+ $ns_map = array_merge($ns_map, $extra_ns_map);
+ }
+
+ if (!($parser && $parser->init($xml_string, $ns_map))) {
+ return $_null;
+ }
+
+ // Try to get root element.
+ $root = $parser->evalXPath('/xrds:XRDS[1]');
+ if (!$root) {
+ return $_null;
+ }
+
+ if (is_array($root)) {
+ $root = $root[0];
+ }
+
+ $attrs = $parser->attributes($root);
+
+ if (array_key_exists('xmlns:xrd', $attrs) &&
+ $attrs['xmlns:xrd'] != Auth_Yadis_XMLNS_XRDS) {
+ return $_null;
+ } else if (array_key_exists('xmlns', $attrs) &&
+ preg_match('/xri/', $attrs['xmlns']) &&
+ $attrs['xmlns'] != Auth_Yadis_XMLNS_XRD_2_0) {
+ return $_null;
+ }
+
+ // Get the last XRD node.
+ $xrd_nodes = $parser->evalXPath('/xrds:XRDS[1]/xrd:XRD');
+
+ if (!$xrd_nodes) {
+ return $_null;
+ }
+
+ $xrds = new Auth_Yadis_XRDS($parser, $xrd_nodes);
+ return $xrds;
+ }
+
+ /**
+ * @access private
+ */
+ function _addService($priority, $service)
+ {
+ $priority = intval($priority);
+
+ if (!array_key_exists($priority, $this->serviceList)) {
+ $this->serviceList[$priority] = array();
+ }
+
+ $this->serviceList[$priority][] = $service;
+ }
+
+ /**
+ * Creates the service list using nodes from the XRDS XML
+ * document.
+ *
+ * @access private
+ */
+ function _parse()
+ {
+ $this->serviceList = array();
+
+ $services = $this->parser->evalXPath('xrd:Service', $this->xrdNode);
+
+ foreach ($services as $node) {
+ $s = new Auth_Yadis_Service();
+ $s->element = $node;
+ $s->parser = $this->parser;
+
+ $priority = $s->getPriority();
+
+ if ($priority === null) {
+ $priority = SERVICES_YADIS_MAX_PRIORITY;
+ }
+
+ $this->_addService($priority, $s);
+ }
+ }
+
+ /**
+ * Returns a list of service objects which correspond to <Service>
+ * elements in the XRDS XML document for this object.
+ *
+ * Optionally, an array of filter callbacks may be given to limit
+ * the list of returned service objects. Furthermore, the default
+ * mode is to return all service objects which match ANY of the
+ * specified filters, but $filter_mode may be
+ * SERVICES_YADIS_MATCH_ALL if you want to be sure that the
+ * returned services match all the given filters. See {@link
+ * Auth_Yadis_Yadis} for detailed usage information on filter
+ * functions.
+ *
+ * @param mixed $filters An array of callbacks to filter the
+ * returned services, or null if all services are to be returned.
+ * @param integer $filter_mode SERVICES_YADIS_MATCH_ALL or
+ * SERVICES_YADIS_MATCH_ANY, depending on whether the returned
+ * services should match ALL or ANY of the specified filters,
+ * respectively.
+ * @return mixed $services An array of {@link
+ * Auth_Yadis_Service} objects if $filter_mode is a valid
+ * mode; null if $filter_mode is an invalid mode (i.e., not
+ * SERVICES_YADIS_MATCH_ANY or SERVICES_YADIS_MATCH_ALL).
+ */
+ function services($filters = null,
+ $filter_mode = SERVICES_YADIS_MATCH_ANY)
+ {
+
+ $pri_keys = array_keys($this->serviceList);
+ sort($pri_keys, SORT_NUMERIC);
+
+ // If no filters are specified, return the entire service
+ // list, ordered by priority.
+ if (!$filters ||
+ (!is_array($filters))) {
+
+ $result = array();
+ foreach ($pri_keys as $pri) {
+ $result = array_merge($result, $this->serviceList[$pri]);
+ }
+
+ return $result;
+ }
+
+ // If a bad filter mode is specified, return null.
+ if (!in_array($filter_mode, array(SERVICES_YADIS_MATCH_ANY,
+ SERVICES_YADIS_MATCH_ALL))) {
+ return null;
+ }
+
+ // Otherwise, use the callbacks in the filter list to
+ // determine which services are returned.
+ $filtered = array();
+
+ foreach ($pri_keys as $priority_value) {
+ $service_obj_list = $this->serviceList[$priority_value];
+
+ foreach ($service_obj_list as $service) {
+
+ $matches = 0;
+
+ foreach ($filters as $filter) {
+
+ if (call_user_func_array($filter, array(&$service))) {
+ $matches++;
+
+ if ($filter_mode == SERVICES_YADIS_MATCH_ANY) {
+ $pri = $service->getPriority();
+ if ($pri === null) {
+ $pri = SERVICES_YADIS_MAX_PRIORITY;
+ }
+
+ if (!array_key_exists($pri, $filtered)) {
+ $filtered[$pri] = array();
+ }
+
+ $filtered[$pri][] = $service;
+ break;
+ }
+ }
+ }
+
+ if (($filter_mode == SERVICES_YADIS_MATCH_ALL) &&
+ ($matches == count($filters))) {
+
+ $pri = $service->getPriority();
+ if ($pri === null) {
+ $pri = SERVICES_YADIS_MAX_PRIORITY;
+ }
+
+ if (!array_key_exists($pri, $filtered)) {
+ $filtered[$pri] = array();
+ }
+ $filtered[$pri][] = $service;
+ }
+ }
+ }
+
+ $pri_keys = array_keys($filtered);
+ sort($pri_keys, SORT_NUMERIC);
+
+ $result = array();
+ foreach ($pri_keys as $pri) {
+ $result = array_merge($result, $filtered[$pri]);
+ }
+
+ return $result;
+ }
+}
+
diff --git a/plugins/openid/lib/Auth/Yadis/XRI.php b/plugins/openid/lib/Auth/Yadis/XRI.php
new file mode 100644
index 00000000..0143a692
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/XRI.php
@@ -0,0 +1,234 @@
+<?php
+
+/**
+ * Routines for XRI resolution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+require_once 'Auth/Yadis/Misc.php';
+require_once 'Auth/Yadis/Yadis.php';
+require_once 'Auth/OpenID.php';
+
+function Auth_Yadis_getDefaultProxy()
+{
+ return 'http://xri.net/';
+}
+
+function Auth_Yadis_getXRIAuthorities()
+{
+ return array('!', '=', '@', '+', '$', '(');
+}
+
+function Auth_Yadis_getEscapeRE()
+{
+ $parts = array();
+ foreach (array_merge(Auth_Yadis_getUCSChars(),
+ Auth_Yadis_getIPrivateChars()) as $pair) {
+ list($m, $n) = $pair;
+ $parts[] = sprintf("%s-%s", chr($m), chr($n));
+ }
+
+ return sprintf('/[%s]/', implode('', $parts));
+}
+
+function Auth_Yadis_getXrefRE()
+{
+ return '/\((.*?)\)/';
+}
+
+function Auth_Yadis_identifierScheme($identifier)
+{
+ if (Auth_Yadis_startswith($identifier, 'xri://') ||
+ ($identifier &&
+ in_array($identifier[0], Auth_Yadis_getXRIAuthorities()))) {
+ return "XRI";
+ } else {
+ return "URI";
+ }
+}
+
+function Auth_Yadis_toIRINormal($xri)
+{
+ if (!Auth_Yadis_startswith($xri, 'xri://')) {
+ $xri = 'xri://' . $xri;
+ }
+
+ return Auth_Yadis_escapeForIRI($xri);
+}
+
+function _escape_xref($xref_match)
+{
+ $xref = $xref_match[0];
+ $xref = str_replace('/', '%2F', $xref);
+ $xref = str_replace('?', '%3F', $xref);
+ $xref = str_replace('#', '%23', $xref);
+ return $xref;
+}
+
+function Auth_Yadis_escapeForIRI($xri)
+{
+ $xri = str_replace('%', '%25', $xri);
+ $xri = preg_replace_callback(Auth_Yadis_getXrefRE(),
+ '_escape_xref', $xri);
+ return $xri;
+}
+
+function Auth_Yadis_toURINormal($xri)
+{
+ return Auth_Yadis_iriToURI(Auth_Yadis_toIRINormal($xri));
+}
+
+function Auth_Yadis_iriToURI($iri)
+{
+ if (1) {
+ return $iri;
+ } else {
+ // According to RFC 3987, section 3.1, "Mapping of IRIs to URIs"
+ return preg_replace_callback(Auth_Yadis_getEscapeRE(),
+ 'Auth_Yadis_pct_escape_unicode', $iri);
+ }
+}
+
+
+function Auth_Yadis_XRIAppendArgs($url, $args)
+{
+ // Append some arguments to an HTTP query. Yes, this is just like
+ // OpenID's appendArgs, but with special seasoning for XRI
+ // queries.
+
+ if (count($args) == 0) {
+ return $url;
+ }
+
+ // Non-empty array; if it is an array of arrays, use multisort;
+ // otherwise use sort.
+ if (array_key_exists(0, $args) &&
+ is_array($args[0])) {
+ // Do nothing here.
+ } else {
+ $keys = array_keys($args);
+ sort($keys);
+ $new_args = array();
+ foreach ($keys as $key) {
+ $new_args[] = array($key, $args[$key]);
+ }
+ $args = $new_args;
+ }
+
+ // According to XRI Resolution section "QXRI query parameters":
+ //
+ // "If the original QXRI had a null query component (only a
+ // leading question mark), or a query component consisting of
+ // only question marks, one additional leading question mark MUST
+ // be added when adding any XRI resolution parameters."
+ if (strpos(rtrim($url, '?'), '?') !== false) {
+ $sep = '&';
+ } else {
+ $sep = '?';
+ }
+
+ return $url . $sep . Auth_OpenID::httpBuildQuery($args);
+}
+
+function Auth_Yadis_providerIsAuthoritative($providerID, $canonicalID)
+{
+ $lastbang = strrpos($canonicalID, '!');
+ $p = substr($canonicalID, 0, $lastbang);
+ return $p == $providerID;
+}
+
+function Auth_Yadis_rootAuthority($xri)
+{
+ // Return the root authority for an XRI.
+
+ $root = null;
+
+ if (Auth_Yadis_startswith($xri, 'xri://')) {
+ $xri = substr($xri, 6);
+ }
+
+ $authority = explode('/', $xri, 2);
+ $authority = $authority[0];
+ if ($authority[0] == '(') {
+ // Cross-reference.
+ // XXX: This is incorrect if someone nests cross-references so
+ // there is another close-paren in there. Hopefully nobody
+ // does that before we have a real xriparse function.
+ // Hopefully nobody does that *ever*.
+ $root = substr($authority, 0, strpos($authority, ')') + 1);
+ } else if (in_array($authority[0], Auth_Yadis_getXRIAuthorities())) {
+ // Other XRI reference.
+ $root = $authority[0];
+ } else {
+ // IRI reference.
+ $_segments = explode("!", $authority);
+ $segments = array();
+ foreach ($_segments as $s) {
+ $segments = array_merge($segments, explode("*", $s));
+ }
+ $root = $segments[0];
+ }
+
+ return Auth_Yadis_XRI($root);
+}
+
+function Auth_Yadis_XRI($xri)
+{
+ if (!Auth_Yadis_startswith($xri, 'xri://')) {
+ $xri = 'xri://' . $xri;
+ }
+ return $xri;
+}
+
+function Auth_Yadis_getCanonicalID($iname, $xrds)
+{
+ // Returns false or a canonical ID value.
+
+ // Now nodes are in reverse order.
+ $xrd_list = array_reverse($xrds->allXrdNodes);
+ $parser = $xrds->parser;
+ $node = $xrd_list[0];
+
+ $canonicalID_nodes = $parser->evalXPath('xrd:CanonicalID', $node);
+
+ if (!$canonicalID_nodes) {
+ return false;
+ }
+
+ $canonicalID = $canonicalID_nodes[0];
+ $canonicalID = Auth_Yadis_XRI($parser->content($canonicalID));
+
+ $childID = $canonicalID;
+
+ for ($i = 1; $i < count($xrd_list); $i++) {
+ $xrd = $xrd_list[$i];
+
+ $parent_sought = substr($childID, 0, strrpos($childID, '!'));
+ $parentCID = $parser->evalXPath('xrd:CanonicalID', $xrd);
+ if (!$parentCID) {
+ return false;
+ }
+ $parentCID = Auth_Yadis_XRI($parser->content($parentCID[0]));
+
+ if (strcasecmp($parent_sought, $parentCID)) {
+ // raise XRDSFraud.
+ return false;
+ }
+
+ $childID = $parent_sought;
+ }
+
+ $root = Auth_Yadis_rootAuthority($iname);
+ if (!Auth_Yadis_providerIsAuthoritative($root, $childID)) {
+ // raise XRDSFraud.
+ return false;
+ }
+
+ return $canonicalID;
+}
+
+
diff --git a/plugins/openid/lib/Auth/Yadis/XRIRes.php b/plugins/openid/lib/Auth/Yadis/XRIRes.php
new file mode 100644
index 00000000..5e115873
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/XRIRes.php
@@ -0,0 +1,72 @@
+<?php
+
+/**
+ * Code for using a proxy XRI resolver.
+ */
+
+require_once 'Auth/Yadis/XRDS.php';
+require_once 'Auth/Yadis/XRI.php';
+
+class Auth_Yadis_ProxyResolver {
+ function Auth_Yadis_ProxyResolver($fetcher, $proxy_url = null)
+ {
+ $this->fetcher = $fetcher;
+ $this->proxy_url = $proxy_url;
+ if (!$this->proxy_url) {
+ $this->proxy_url = Auth_Yadis_getDefaultProxy();
+ }
+ }
+
+ function queryURL($xri, $service_type = null)
+ {
+ // trim off the xri:// prefix
+ $qxri = substr(Auth_Yadis_toURINormal($xri), 6);
+ $hxri = $this->proxy_url . $qxri;
+ $args = array(
+ '_xrd_r' => 'application/xrds+xml'
+ );
+
+ if ($service_type) {
+ $args['_xrd_t'] = $service_type;
+ } else {
+ // Don't perform service endpoint selection.
+ $args['_xrd_r'] .= ';sep=false';
+ }
+
+ $query = Auth_Yadis_XRIAppendArgs($hxri, $args);
+ return $query;
+ }
+
+ function query($xri, $service_types, $filters = array())
+ {
+ $services = array();
+ $canonicalID = null;
+ foreach ($service_types as $service_type) {
+ $url = $this->queryURL($xri, $service_type);
+ $response = $this->fetcher->get($url);
+ if ($response->status != 200 and $response->status != 206) {
+ continue;
+ }
+ $xrds = Auth_Yadis_XRDS::parseXRDS($response->body);
+ if (!$xrds) {
+ continue;
+ }
+ $canonicalID = Auth_Yadis_getCanonicalID($xri,
+ $xrds);
+
+ if ($canonicalID === false) {
+ return null;
+ }
+
+ $some_services = $xrds->services($filters);
+ $services = array_merge($services, $some_services);
+ // TODO:
+ // * If we do get hits for multiple service_types, we're
+ // almost certainly going to have duplicated service
+ // entries and broken priority ordering.
+ }
+ return array($canonicalID, $services);
+ }
+}
+
+
diff --git a/plugins/openid/lib/Auth/Yadis/Yadis.php b/plugins/openid/lib/Auth/Yadis/Yadis.php
new file mode 100644
index 00000000..9ea2db7f
--- /dev/null
+++ b/plugins/openid/lib/Auth/Yadis/Yadis.php
@@ -0,0 +1,382 @@
+<?php
+
+/**
+ * The core PHP Yadis implementation.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005-2008 Janrain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ */
+
+/**
+ * Need both fetcher types so we can use the right one based on the
+ * presence or absence of CURL.
+ */
+require_once "Auth/Yadis/PlainHTTPFetcher.php";
+require_once "Auth/Yadis/ParanoidHTTPFetcher.php";
+
+/**
+ * Need this for parsing HTML (looking for META tags).
+ */
+require_once "Auth/Yadis/ParseHTML.php";
+
+/**
+ * Need this to parse the XRDS document during Yadis discovery.
+ */
+require_once "Auth/Yadis/XRDS.php";
+
+/**
+ * XRDS (yadis) content type
+ */
+define('Auth_Yadis_CONTENT_TYPE', 'application/xrds+xml');
+
+/**
+ * Yadis header
+ */
+define('Auth_Yadis_HEADER_NAME', 'X-XRDS-Location');
+
+/**
+ * Contains the result of performing Yadis discovery on a URI.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_DiscoveryResult {
+
+ // The URI that was passed to the fetcher
+ var $request_uri = null;
+
+ // The result of following redirects from the request_uri
+ var $normalized_uri = null;
+
+ // The URI from which the response text was returned (set to
+ // None if there was no XRDS document found)
+ var $xrds_uri = null;
+
+ var $xrds = null;
+
+ // The content-type returned with the response_text
+ var $content_type = null;
+
+ // The document returned from the xrds_uri
+ var $response_text = null;
+
+ // Did the discovery fail miserably?
+ var $failed = false;
+
+ function Auth_Yadis_DiscoveryResult($request_uri)
+ {
+ // Initialize the state of the object
+ // sets all attributes to None except the request_uri
+ $this->request_uri = $request_uri;
+ }
+
+ function fail()
+ {
+ $this->failed = true;
+ }
+
+ function isFailure()
+ {
+ return $this->failed;
+ }
+
+ /**
+ * Returns the list of service objects as described by the XRDS
+ * document, if this yadis object represents a successful Yadis
+ * discovery.
+ *
+ * @return array $services An array of {@link Auth_Yadis_Service}
+ * objects
+ */
+ function services()
+ {
+ if ($this->xrds) {
+ return $this->xrds->services();
+ }
+
+ return null;
+ }
+
+ function usedYadisLocation()
+ {
+ // Was the Yadis protocol's indirection used?
+ return ($this->xrds_uri && $this->normalized_uri != $this->xrds_uri);
+ }
+
+ function isXRDS()
+ {
+ // Is the response text supposed to be an XRDS document?
+ return ($this->usedYadisLocation() ||
+ $this->content_type == Auth_Yadis_CONTENT_TYPE);
+ }
+}
+
+/**
+ *
+ * Perform the Yadis protocol on the input URL and return an iterable
+ * of resulting endpoint objects.
+ *
+ * input_url: The URL on which to perform the Yadis protocol
+ *
+ * @return: The normalized identity URL and an iterable of endpoint
+ * objects generated by the filter function.
+ *
+ * xrds_parse_func: a callback which will take (uri, xrds_text) and
+ * return an array of service endpoint objects or null. Usually
+ * array('Auth_OpenID_ServiceEndpoint', 'fromXRDS').
+ *
+ * discover_func: if not null, a callback which should take (uri) and
+ * return an Auth_Yadis_Yadis object or null.
+ */
+function Auth_Yadis_getServiceEndpoints($input_url, $xrds_parse_func,
+ $discover_func=null, $fetcher=null)
+{
+ if ($discover_func === null) {
+ $discover_function = array('Auth_Yadis_Yadis', 'discover');
+ }
+
+ $yadis_result = call_user_func_array($discover_func,
+ array($input_url, &$fetcher));
+
+ if ($yadis_result === null) {
+ return array($input_url, array());
+ }
+
+ $endpoints = call_user_func_array($xrds_parse_func,
+ array($yadis_result->normalized_uri,
+ $yadis_result->response_text));
+
+ if ($endpoints === null) {
+ $endpoints = array();
+ }
+
+ return array($yadis_result->normalized_uri, $endpoints);
+}
+
+/**
+ * This is the core of the PHP Yadis library. This is the only class
+ * a user needs to use to perform Yadis discovery. This class
+ * performs the discovery AND stores the result of the discovery.
+ *
+ * First, require this library into your program source:
+ *
+ * <pre> require_once "Auth/Yadis/Yadis.php";</pre>
+ *
+ * To perform Yadis discovery, first call the "discover" method
+ * statically with a URI parameter:
+ *
+ * <pre> $http_response = array();
+ * $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
+ * $yadis_object = Auth_Yadis_Yadis::discover($uri,
+ * $http_response, $fetcher);</pre>
+ *
+ * If the discovery succeeds, $yadis_object will be an instance of
+ * {@link Auth_Yadis_Yadis}. If not, it will be null. The XRDS
+ * document found during discovery should have service descriptions,
+ * which can be accessed by calling
+ *
+ * <pre> $service_list = $yadis_object->services();</pre>
+ *
+ * which returns an array of objects which describe each service.
+ * These objects are instances of Auth_Yadis_Service. Each object
+ * describes exactly one whole Service element, complete with all of
+ * its Types and URIs (no expansion is performed). The common use
+ * case for using the service objects returned by services() is to
+ * write one or more filter functions and pass those to services():
+ *
+ * <pre> $service_list = $yadis_object->services(
+ * array("filterByURI",
+ * "filterByExtension"));</pre>
+ *
+ * The filter functions (whose names appear in the array passed to
+ * services()) take the following form:
+ *
+ * <pre> function myFilter($service) {
+ * // Query $service object here. Return true if the service
+ * // matches your query; false if not.
+ * }</pre>
+ *
+ * This is an example of a filter which uses a regular expression to
+ * match the content of URI tags (note that the Auth_Yadis_Service
+ * class provides a getURIs() method which you should use instead of
+ * this contrived example):
+ *
+ * <pre>
+ * function URIMatcher($service) {
+ * foreach ($service->getElements('xrd:URI') as $uri) {
+ * if (preg_match("/some_pattern/",
+ * $service->parser->content($uri))) {
+ * return true;
+ * }
+ * }
+ * return false;
+ * }</pre>
+ *
+ * The filter functions you pass will be called for each service
+ * object to determine which ones match the criteria your filters
+ * specify. The default behavior is that if a given service object
+ * matches ANY of the filters specified in the services() call, it
+ * will be returned. You can specify that a given service object will
+ * be returned ONLY if it matches ALL specified filters by changing
+ * the match mode of services():
+ *
+ * <pre> $yadis_object->services(array("filter1", "filter2"),
+ * SERVICES_YADIS_MATCH_ALL);</pre>
+ *
+ * See {@link SERVICES_YADIS_MATCH_ALL} and {@link
+ * SERVICES_YADIS_MATCH_ANY}.
+ *
+ * Services described in an XRDS should have a library which you'll
+ * probably be using. Those libraries are responsible for defining
+ * filters that can be used with the "services()" call. If you need
+ * to write your own filter, see the documentation for {@link
+ * Auth_Yadis_Service}.
+ *
+ * @package OpenID
+ */
+class Auth_Yadis_Yadis {
+
+ /**
+ * Returns an HTTP fetcher object. If the CURL extension is
+ * present, an instance of {@link Auth_Yadis_ParanoidHTTPFetcher}
+ * is returned. If not, an instance of
+ * {@link Auth_Yadis_PlainHTTPFetcher} is returned.
+ *
+ * If Auth_Yadis_CURL_OVERRIDE is defined, this method will always
+ * return a {@link Auth_Yadis_PlainHTTPFetcher}.
+ */
+ static function getHTTPFetcher($timeout = 20)
+ {
+ if (Auth_Yadis_Yadis::curlPresent() &&
+ (!defined('Auth_Yadis_CURL_OVERRIDE'))) {
+ $fetcher = new Auth_Yadis_ParanoidHTTPFetcher($timeout);
+ } else {
+ $fetcher = new Auth_Yadis_PlainHTTPFetcher($timeout);
+ }
+ return $fetcher;
+ }
+
+ static function curlPresent()
+ {
+ return function_exists('curl_init');
+ }
+
+ /**
+ * @access private
+ */
+ static function _getHeader($header_list, $names)
+ {
+ foreach ($header_list as $name => $value) {
+ foreach ($names as $n) {
+ if (strtolower($name) == strtolower($n)) {
+ return $value;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @access private
+ */
+ static function _getContentType($content_type_header)
+ {
+ if ($content_type_header) {
+ $parts = explode(";", $content_type_header);
+ return strtolower($parts[0]);
+ }
+ }
+
+ /**
+ * This should be called statically and will build a Yadis
+ * instance if the discovery process succeeds. This implements
+ * Yadis discovery as specified in the Yadis specification.
+ *
+ * @param string $uri The URI on which to perform Yadis discovery.
+ *
+ * @param array $http_response An array reference where the HTTP
+ * response object will be stored (see {@link
+ * Auth_Yadis_HTTPResponse}.
+ *
+ * @param Auth_Yadis_HTTPFetcher $fetcher An instance of a
+ * Auth_Yadis_HTTPFetcher subclass.
+ *
+ * @param array $extra_ns_map An array which maps namespace names
+ * to namespace URIs to be used when parsing the Yadis XRDS
+ * document.
+ *
+ * @param integer $timeout An optional fetcher timeout, in seconds.
+ *
+ * @return mixed $obj Either null or an instance of
+ * Auth_Yadis_Yadis, depending on whether the discovery
+ * succeeded.
+ */
+ static function discover($uri, $fetcher,
+ $extra_ns_map = null, $timeout = 20)
+ {
+ $result = new Auth_Yadis_DiscoveryResult($uri);
+
+ $request_uri = $uri;
+ $headers = array("Accept: " . Auth_Yadis_CONTENT_TYPE .
+ ', text/html; q=0.3, application/xhtml+xml; q=0.5');
+
+ if ($fetcher === null) {
+ $fetcher = Auth_Yadis_Yadis::getHTTPFetcher($timeout);
+ }
+
+ $response = $fetcher->get($uri, $headers);
+
+ if (!$response || ($response->status != 200 and
+ $response->status != 206)) {
+ $result->fail();
+ return $result;
+ }
+
+ $result->normalized_uri = $response->final_url;
+ $result->content_type = Auth_Yadis_Yadis::_getHeader(
+ $response->headers,
+ array('content-type'));
+
+ if ($result->content_type &&
+ (Auth_Yadis_Yadis::_getContentType($result->content_type) ==
+ Auth_Yadis_CONTENT_TYPE)) {
+ $result->xrds_uri = $result->normalized_uri;
+ } else {
+ $yadis_location = Auth_Yadis_Yadis::_getHeader(
+ $response->headers,
+ array(Auth_Yadis_HEADER_NAME));
+
+ if (!$yadis_location) {
+ $parser = new Auth_Yadis_ParseHTML();
+ $yadis_location = $parser->getHTTPEquiv($response->body);
+ }
+
+ if ($yadis_location) {
+ $result->xrds_uri = $yadis_location;
+
+ $response = $fetcher->get($yadis_location);
+
+ if ((!$response) || ($response->status != 200 and
+ $response->status != 206)) {
+ $result->fail();
+ return $result;
+ }
+
+ $result->content_type = Auth_Yadis_Yadis::_getHeader(
+ $response->headers,
+ array('content-type'));
+ }
+ }
+
+ $result->response_text = $response->body;
+ return $result;
+ }
+}
+
+
diff --git a/plugins/openid/openid.php b/plugins/openid/openid.php
index 6ea0dac0..fe7feb4b 100644
--- a/plugins/openid/openid.php
+++ b/plugins/openid/openid.php
@@ -5,7 +5,7 @@
Description: Allows the use of OpenID for account registration, authentication, and commenting. Also includes an OpenID provider which can turn WordPress author URLs into OpenIDs.
Author: DiSo Development Team
Author URI: http://diso-project.org/
- Version: 3.3.3
+ Version: 3.3.4
License: Dual GPL (http://www.fsf.org/licensing/licenses/info/GPLv2.html) and Modified BSD (http://www.fsf.org/licensing/licenses/index_html#ModifiedBSD)
Text Domain: openid
*/
@@ -16,8 +16,7 @@ define ( 'OPENID_PLUGIN_REVISION', preg_replace( '/\$Rev: (.+) \$/', '\\1',
// last plugin revision that required database schema changes
define ( 'OPENID_DB_REVISION', 24426);
-
-$openid_include_path = dirname(__FILE__);
+$openid_include_path = dirname(__FILE__) . '/lib';
// check source of randomness
if ( !@is_readable('/dev/urandom') ) {
@@ -25,14 +24,14 @@ if ( !@is_readable('/dev/urandom') ) {
}
set_include_path( $openid_include_path . PATH_SEPARATOR . get_include_path() );
-require_once 'common.php';
-require_once 'consumer.php';
-require_once 'admin_panels.php';
-require_once 'comments.php';
-require_once 'login.php';
-require_once 'server.php';
-require_once 'store.php';
-restore_include_path();
+
+require_once dirname(__FILE__) . '/common.php';
+require_once dirname(__FILE__) . '/consumer.php';
+require_once dirname(__FILE__) . '/admin_panels.php';
+require_once dirname(__FILE__) . '/comments.php';
+require_once dirname(__FILE__) . '/login.php';
+require_once dirname(__FILE__) . '/server.php';
+require_once dirname(__FILE__) . '/store.php';
// register activation (and similar) hooks
register_activation_hook('openid/openid.php', 'openid_activate_plugin');
@@ -150,9 +149,9 @@ function get_userdata_by_various($id_or_name = null) {
if ($user == null) return false;
return $user->data;
} else if ( is_numeric($id_or_name) ) {
- return get_userdata($id_or_name);
+ return get_user_by('id', $id_or_name);
} else {
- return get_userdatabylogin($id_or_name);
+ return get_user_by('login', $id_or_name);
}
}
endif;
diff --git a/plugins/openid/readme.txt b/plugins/openid/readme.txt
index 5b12bfdb..abada5cd 100644
--- a/plugins/openid/readme.txt
+++ b/plugins/openid/readme.txt
@@ -3,7 +3,7 @@ Contributors: willnorris, factoryjoe
Tags: openid, authentication, login, comments
Requires at least: 2.8
Tested up to: 2.8.5
-Stable tag: 3.3.3
+Stable tag: 3.3.4
Allows WordPress to provide and consumer OpenIDs for authentication of users and comments.
@@ -100,6 +100,13 @@ report at <http://code.google.com/p/diso/issues/list>.
== Changelog ==
+Project maintined on github at
+[diso/wordpress-openid](https://github.com/diso/wordpress-openid).
+
+= version 3.3.4 (Nov 16, 2012) =
+ - update to latest OpenID library (includes lots of bug fixes, particularly with PHP 5.3). Full changelog [on github](https://github.com/openid/php-openid).
+ - various bug fixes. Full changelog [on github](https://github.com/diso/wordpress-openid).
+
= version 3.3.3 (Aug 24, 2010) =
- add/update danish, japanese, and spanish translations
- update to latest version of php-openid library
diff --git a/plugins/openid/server.php b/plugins/openid/server.php
index 4a553a78..f2ccf5f2 100644
--- a/plugins/openid/server.php
+++ b/plugins/openid/server.php
@@ -1,7 +1,7 @@
<?php
require_once 'Auth/OpenID/Server.php';
-require_once 'server_ext.php';
+require_once dirname(__FILE__) . '/server_ext.php';
add_filter( 'xrds_simple', 'openid_provider_xrds_simple');
add_action( 'wp_head', 'openid_provider_link_tags');
@@ -44,7 +44,8 @@ function openid_provider_xrds_simple($xrds) {
if (!$user && get_option('openid_blog_owner')) {
$url_parts = parse_url(get_option('home'));
- $path = trailingslashit($url_parts['path']);
+ $path = array_key_exists('path', $url_parts) ? $url_parts['path'] : '';
+ $path = trailingslashit($path);
$script = preg_replace('/index.php$/', '', $_SERVER['SCRIPT_NAME']);
$script = trailingslashit($script);
@@ -54,7 +55,7 @@ function openid_provider_xrds_simple($xrds) {
}
if (!defined('OPENID_DISALLOW_OWNER') || !OPENID_DISALLOW_OWNER) {
- $user = get_userdatabylogin(get_option('openid_blog_owner'));
+ $user = get_user_by('login', get_option('openid_blog_owner'));
}
}
@@ -120,17 +121,19 @@ function openid_provider_xrds_simple($xrds) {
function openid_server_requested_user() {
global $wp_rewrite;
- if ($_REQUEST['author']) {
+ if (array_key_exists('author', $_REQUEST) && $_REQUEST['author']) {
if (is_numeric($_REQUEST['author'])) {
- return get_userdata($_REQUEST['author']);
+ return get_user_by('id', $_REQUEST['author']);
} else {
- return get_userdatabylogin($_REQUEST['author']);
+ return get_user_by('login', $_REQUEST['author']);
}
} else {
$regex = preg_replace('/%author%/', '(.+)', $wp_rewrite->get_author_permastruct());
preg_match('|'.$regex.'|', $_SERVER['REQUEST_URI'], $matches);
- $username = sanitize_user($matches[1], true);
- return get_userdatabylogin($username);
+ if ($matches) {
+ $username = sanitize_user($matches[1], true);
+ return get_user_by('login', $username);
+ }
}
}
@@ -340,7 +343,7 @@ function openid_provider_link_tags() {
if (is_front_page()) {
if (!defined('OPENID_DISALLOW_OWNER') || !OPENID_DISALLOW_OWNER) {
- $user = get_userdatabylogin(get_option('openid_blog_owner'));
+ $user = get_user_by('login', get_option('openid_blog_owner'));
}
} else if (is_author()) {
global $wp_query;
diff --git a/plugins/wp-syntax/README.txt b/plugins/wp-syntax/README.txt
index 174ac431..2187a72b 100644
--- a/plugins/wp-syntax/README.txt
+++ b/plugins/wp-syntax/README.txt
@@ -1,10 +1,10 @@
=== WP-Syntax ===
-Contributors: shazahm1@hotmail.com, rmm5t
-Donate link: http://connections-pro.com
-Tags: syntax highlighting, syntax, highlight, code, formatting
+Contributors: shazahm1@hotmail.com
+Donate link: http://wp-syntax.com/send-donation/
+Tags: syntax highlighting, syntax, highlight, code, formatting, code, CSS, html, php, sourcecode
Requires at least: 3.0
-Tested up to: 3.2.1
-Stable tag: 0.9.12
+Tested up to: 3.5.1
+Stable tag: 1.0
WP-Syntax provides clean syntax highlighting for embedding source code within pages or posts.
@@ -12,8 +12,7 @@ WP-Syntax provides clean syntax highlighting for embedding source code within pa
WP-Syntax provides clean syntax highlighting using
[GeSHi](http://qbnz.com/highlighter/) -- supporting a wide range of popular
-languages. It supports highlighting with or
-without line numbers and maintains formatting while copying snippets of code
+languages. It supports highlighting with or without line numbers and maintains formatting while copying snippets of code
from the browser.
It avoids conflicts with other 3rd party plugins by running an early
@@ -21,23 +20,16 @@ pre-filter and a late post-filter that substitutes and pulls the code snippets
out first and then pushes them back in with highlighting at the end. The
result is source code formatted and highlighted the way you intended.
-This plugin was originally written for use with
-[EmacsBlog](http://www.emacsblog.org). To see it in action, scroll through
-this [particular
-post](http://www.emacsblog.org/2007/02/22/maximize-on-startup-part-2/) or
-visit the
-[screenshots](http://wordpress.org/extend/plugins/wp-syntax/screenshots/).
-
Usage, Supported Languages, Styling Guidelines, and Release Notes are availabe
-in the [Other
-Notes](http://wordpress.org/extend/plugins/wp-syntax/other_notes/) section.
+in the [Other Notes](http://wordpress.org/extend/plugins/wp-syntax/other_notes/) section.
+
+Want to contribute? WP-Sytax can be found on Github. Fork and submit your pull requests today!
= Basic Usage =
-Wrap code blocks with `<pre lang="LANGUAGE" line="1">` and `</pre>` where
-`LANGUAGE` is a [GeSHi](http://qbnz.com/highlighter/) supported language
-syntax. The `line` attribute is optional. [More usage
-examples](http://wordpress.org/extend/plugins/wp-syntax/other_notes/)
+Wrap code blocks with `<pre lang="LANGUAGE" line="1">` and `</pre>` where **"LANGUAGE"**
+is a [GeSHi](http://qbnz.com/highlighter/) supported language syntax.
+The `line` attribute is optional. [More usage examples](http://wordpress.org/extend/plugins/wp-syntax/other_notes/)
== Installation ==
@@ -69,10 +61,9 @@ plugin, and check "unfiltered HTML" for the roles that would like to post code s
== Usage ==
-Wrap code blocks with `<pre lang="LANGUAGE" line="1">` and `</pre>` where
-`LANGUAGE` is a [GeSHi](http://qbnz.com/highlighter/) supported language
-syntax. See below for a full list of supported languages. The `line`
-attribute is optional.
+Wrap code blocks with `<pre lang="LANGUAGE" line="1">` and `</pre>` where **"LANGUAGE"** is a [GeSHi](http://qbnz.com/highlighter/) supported
+language syntax. See below for a full list of supported languages.
+The `line` attribute is optional.
**Example 1: PHP, no line numbers**
@@ -113,9 +104,33 @@ attribute is optional.
&lt;xml&gt;Hello&lt;/xml&gt;
</pre>
+**Example 5: PHP, with line numbers and highlighting a specific line**
+
+ <pre lang="php" line="1" highlight="3">
+ <div id="foo">
+ <?php
+ function foo() {
+ echo "Hello World!\\n";
+ }
+ ?>
+ </div>
+ </pre>
+
+**Example 6: PHP, with a caption (file and/or file path of the source file)**
+
+ <pre lang="php" src"https://github.com/shazahm1/Connections/blob/master/connections.php">
+ <div id="foo">
+ <?php
+ function foo() {
+ echo "Hello World!\\n";
+ }
+ ?>
+ </div>
+ </pre>
+
== Supported Languages ==
-The following languages are supported in the `lang` attribute:
+The following languages are most supported in the `lang` attribute:
abap, actionscript, actionscript3, ada, apache, applescript, apt_sources, asm,
**asp**, autoit, avisynth, **bash**, bf, bibtex, blitzbasic, bnf, boo, **c**,
@@ -134,6 +149,9 @@ text, thinbasic, tsql, typoscript, **vb**, **vbnet**, verilog, vhdl, vim,
visualfoxpro, visualprolog, whitespace, whois, winbatch, **xml**, xorg_conf,
xpp, z80
+See the [GeSHi Documentation](http://qbnz.com/highlighter/geshi-doc.html)
+for a full list of supported languages.
+
(Bold languages just highlight the more popular ones.)
== Styling Guidelines ==
@@ -162,12 +180,29 @@ or somewhere else like this:
}
?>
-This allows for a great possibility of different customizations. Be sure to
+This allows for a great possibility of different customizations. Be sure to
review the [GeSHi Documentation](http://qbnz.com/highlighter/geshi-doc.html).
== Changelog ==
-**0.9.12** : Fixed a range bug in the new highlight feature.
+= 1.0 02/09/2013 =
+* NEW: CSS3 for alternating background lines for easier reading.
+* OTHER: Completely refactor code to utilize current best practices for plugin development which will provide a solid foundation for further development.
+* OTHER: Remove GeSHi contrib and test folders.
+* OTHER: Move CSS to `css` subfolder.
+* OTHER: Move JavaScript to `js` subfolder.
+* OTHER: CSS fixes to keep theme from breaking output formatting.
+
+= 0.9.13 09/01/12 =
+* FEATURE: Added a new "src" shortcode option to allow reference of the source filename. Props: Steffen Vogel
+* BUG: Properly enqueue the CSS file.
+* BUG: Updated TinyMCE whitelist to allows required tags. Props: Steffen Vogel
+* OTHER: Updated GeSHi to 1.0.8.11
+* OTHER: Remove old unused code.
+* OTHER: Imporved line highlighting. Props: Steffen Vogel
+* OTHER: Added some additional CSS styles to help keep theme's from breaking the presentation of the code.
+
+**0.9.12** : Fixed a range bug in the new highlight feature.
**0.9.11** : Added line highlighting support. User submitted patch. [Thanks Flynsarmy && Chimo](http://www.flynsarmy.com/2011/06/how-to-add-line-highlight-support-to-wp-syntax/)
diff --git a/plugins/wp-syntax/css/wp-syntax.css b/plugins/wp-syntax/css/wp-syntax.css
new file mode 100644
index 00000000..2401f78e
--- /dev/null
+++ b/plugins/wp-syntax/css/wp-syntax.css
@@ -0,0 +1,98 @@
+.wp_syntax {
+ color : #100;
+ background-color: #f9f9f9;
+ border : 1px solid silver;
+ margin : 0 0 1.5em 0;
+ overflow : auto;
+}
+
+/* IE FIX */
+.wp_syntax {
+ overflow-x : auto;
+ overflow-y : hidden;
+ padding-bottom: expression(this.scrollWidth > this.offsetWidth ? 15 : 0);
+ width : 99%;
+}
+
+.wp_syntax table {
+ border : none !important;
+ border-collapse: collapse !important;
+ margin : 0 !important;
+ padding : 0 !important;
+ width : 100% !important
+}
+
+.wp_syntax caption {
+ margin : 0 !important;
+ padding : 2px !important;
+ width : 100% !important;
+ background-color: #def !important;
+ text-align : left !important;
+ font-family : monospace !important;
+ font-size : 12px !important;
+ line-height : 1.2em !important;
+}
+
+.wp_syntax caption a {
+ color : #1982d1 !important;
+ text-align : left !important;
+ font-family : monospace !important;
+ font-size : 12px !important;
+ line-height : 16px !important;
+ text-decoration: none !important;
+}
+
+.wp_syntax caption a:hover {
+ color : #1982d1 !important;
+ text-decoration: underline !important;
+}
+
+.wp_syntax div, .wp_syntax td {
+ border : none !important;
+ text-align : left !important;
+ padding : 0 !important;
+ vertical-align: top !important;
+}
+
+.wp_syntax td.code{
+ background-color: #EEE;
+ background-image: -webkit-linear-gradient( transparent 50%, rgba(255, 255, 255, .9) 50% );
+ background-image: -moz-linear-gradient( transparent 50%, rgba(255, 255, 255, .9) 50% );
+ background-image: -ms-linear-gradient( transparent 50%, rgba(255, 255, 255, .9) 50% );
+ background-image: -o-linear-gradient( transparent 50%, rgba(255, 255, 255, .9) 50% );
+ background-image: linear-gradient( transparent 50%, rgba(255, 255, 255, .9) 50% );
+ background-size : 1px 32px;
+ line-height : normal !important;
+ white-space : normal !important;
+ width : 100% !important;
+}
+
+/* potential overrides for other styles */
+.wp_syntax pre {
+ background : transparent !important;
+ border : none !important;
+ margin : 0 !important;
+ padding : 0 !important;
+ width : auto !important;
+ float : none !important;
+ clear : none !important;
+ overflow : visible !important;
+ font-family : monospace !important;
+ font-size : 12px !important;
+ line-height : 16px !important;
+ padding : 0 4px !important;
+ white-space : pre !important;
+ -moz-box-shadow : 0px 0px 0px rgba(0, 0, 0, 0) !important; /* FF3.5+ */
+ -webkit-box-shadow : 0px 0px 0px rgba(0, 0, 0, 0) !important; /* Saf3.0+, Chrome */
+ box-shadow : 0px 0px 0px rgba(0, 0, 0, 0) !important; /* Opera 10.5, IE 9.0 */
+ -webkit-border-radius: 0 !important;
+ -moz-border-radius : 0 !important;
+ border-radius : 0 !important;
+}
+
+.wp_syntax td.line_numbers pre {
+ background-color: #def !important;
+ color : gray !important;
+ text-align : right !important;
+ width : 16px !important;
+} \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi.php b/plugins/wp-syntax/geshi/geshi.php
index f7b5a51a..c6ff9ef7 100644
--- a/plugins/wp-syntax/geshi/geshi.php
+++ b/plugins/wp-syntax/geshi/geshi.php
@@ -1,4761 +1,4775 @@
-<?php
-/**
- * GeSHi - Generic Syntax Highlighter
- *
- * The GeSHi class for Generic Syntax Highlighting. Please refer to the
- * documentation at http://qbnz.com/highlighter/documentation.php for more
- * information about how to use this class.
- *
- * For changes, release notes, TODOs etc, see the relevant files in the docs/
- * directory.
- *
- * This file is part of GeSHi.
- *
- * GeSHi is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GeSHi is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GeSHi; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * @package geshi
- * @subpackage core
- * @author Nigel McNie <nigel@geshi.org>, Benny Baumann <BenBE@omorphia.de>
- * @copyright (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann
- * @license http://gnu.org/copyleft/gpl.html GNU GPL
- *
- */
-
-//
-// GeSHi Constants
-// You should use these constant names in your programs instead of
-// their values - you never know when a value may change in a future
-// version
-//
-
-/** The version of this GeSHi file */
-define('GESHI_VERSION', '1.0.8.9');
-
-// Define the root directory for the GeSHi code tree
-if (!defined('GESHI_ROOT')) {
- /** The root directory for GeSHi */
- define('GESHI_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR);
-}
-/** The language file directory for GeSHi
- @access private */
-define('GESHI_LANG_ROOT', GESHI_ROOT . 'geshi' . DIRECTORY_SEPARATOR);
-
-// Define if GeSHi should be paranoid about security
-if (!defined('GESHI_SECURITY_PARANOID')) {
- /** Tells GeSHi to be paranoid about security settings */
- define('GESHI_SECURITY_PARANOID', false);
-}
-
-// Line numbers - use with enable_line_numbers()
-/** Use no line numbers when building the result */
-define('GESHI_NO_LINE_NUMBERS', 0);
-/** Use normal line numbers when building the result */
-define('GESHI_NORMAL_LINE_NUMBERS', 1);
-/** Use fancy line numbers when building the result */
-define('GESHI_FANCY_LINE_NUMBERS', 2);
-
-// Container HTML type
-/** Use nothing to surround the source */
-define('GESHI_HEADER_NONE', 0);
-/** Use a "div" to surround the source */
-define('GESHI_HEADER_DIV', 1);
-/** Use a "pre" to surround the source */
-define('GESHI_HEADER_PRE', 2);
-/** Use a pre to wrap lines when line numbers are enabled or to wrap the whole code. */
-define('GESHI_HEADER_PRE_VALID', 3);
-/**
- * Use a "table" to surround the source:
- *
- * <table>
- * <thead><tr><td colspan="2">$header</td></tr></thead>
- * <tbody><tr><td><pre>$linenumbers</pre></td><td><pre>$code></pre></td></tr></tbody>
- * <tfooter><tr><td colspan="2">$footer</td></tr></tfoot>
- * </table>
- *
- * this is essentially only a workaround for Firefox, see sf#1651996 or take a look at
- * https://bugzilla.mozilla.org/show_bug.cgi?id=365805
- * @note when linenumbers are disabled this is essentially the same as GESHI_HEADER_PRE
- */
-define('GESHI_HEADER_PRE_TABLE', 4);
-
-// Capatalisation constants
-/** Lowercase keywords found */
-define('GESHI_CAPS_NO_CHANGE', 0);
-/** Uppercase keywords found */
-define('GESHI_CAPS_UPPER', 1);
-/** Leave keywords found as the case that they are */
-define('GESHI_CAPS_LOWER', 2);
-
-// Link style constants
-/** Links in the source in the :link state */
-define('GESHI_LINK', 0);
-/** Links in the source in the :hover state */
-define('GESHI_HOVER', 1);
-/** Links in the source in the :active state */
-define('GESHI_ACTIVE', 2);
-/** Links in the source in the :visited state */
-define('GESHI_VISITED', 3);
-
-// Important string starter/finisher
-// Note that if you change these, they should be as-is: i.e., don't
-// write them as if they had been run through htmlentities()
-/** The starter for important parts of the source */
-define('GESHI_START_IMPORTANT', '<BEGIN GeSHi>');
-/** The ender for important parts of the source */
-define('GESHI_END_IMPORTANT', '<END GeSHi>');
-
-/**#@+
- * @access private
- */
-// When strict mode applies for a language
-/** Strict mode never applies (this is the most common) */
-define('GESHI_NEVER', 0);
-/** Strict mode *might* apply, and can be enabled or
- disabled by {@link GeSHi->enable_strict_mode()} */
-define('GESHI_MAYBE', 1);
-/** Strict mode always applies */
-define('GESHI_ALWAYS', 2);
-
-// Advanced regexp handling constants, used in language files
-/** The key of the regex array defining what to search for */
-define('GESHI_SEARCH', 0);
-/** The key of the regex array defining what bracket group in a
- matched search to use as a replacement */
-define('GESHI_REPLACE', 1);
-/** The key of the regex array defining any modifiers to the regular expression */
-define('GESHI_MODIFIERS', 2);
-/** The key of the regex array defining what bracket group in a
- matched search to put before the replacement */
-define('GESHI_BEFORE', 3);
-/** The key of the regex array defining what bracket group in a
- matched search to put after the replacement */
-define('GESHI_AFTER', 4);
-/** The key of the regex array defining a custom keyword to use
- for this regexp's html tag class */
-define('GESHI_CLASS', 5);
-
-/** Used in language files to mark comments */
-define('GESHI_COMMENTS', 0);
-
-/** Used to work around missing PHP features **/
-define('GESHI_PHP_PRE_433', !(version_compare(PHP_VERSION, '4.3.3') === 1));
-
-/** make sure we can call stripos **/
-if (!function_exists('stripos')) {
- // the offset param of preg_match is not supported below PHP 4.3.3
- if (GESHI_PHP_PRE_433) {
- /**
- * @ignore
- */
- function stripos($haystack, $needle, $offset = null) {
- if (!is_null($offset)) {
- $haystack = substr($haystack, $offset);
- }
- if (preg_match('/'. preg_quote($needle, '/') . '/', $haystack, $match, PREG_OFFSET_CAPTURE)) {
- return $match[0][1];
- }
- return false;
- }
- }
- else {
- /**
- * @ignore
- */
- function stripos($haystack, $needle, $offset = null) {
- if (preg_match('/'. preg_quote($needle, '/') . '/', $haystack, $match, PREG_OFFSET_CAPTURE, $offset)) {
- return $match[0][1];
- }
- return false;
- }
- }
-}
-
-/** some old PHP / PCRE subpatterns only support up to xxx subpatterns in
- regular expressions. Set this to false if your PCRE lib is up to date
- @see GeSHi->optimize_regexp_list()
- **/
-define('GESHI_MAX_PCRE_SUBPATTERNS', 500);
-/** it's also important not to generate too long regular expressions
- be generous here... but keep in mind, that when reaching this limit we
- still have to close open patterns. 12k should do just fine on a 16k limit.
- @see GeSHi->optimize_regexp_list()
- **/
-define('GESHI_MAX_PCRE_LENGTH', 12288);
-
-//Number format specification
-/** Basic number format for integers */
-define('GESHI_NUMBER_INT_BASIC', 1); //Default integers \d+
-/** Enhanced number format for integers like seen in C */
-define('GESHI_NUMBER_INT_CSTYLE', 2); //Default C-Style \d+[lL]?
-/** Number format to highlight binary numbers with a suffix "b" */
-define('GESHI_NUMBER_BIN_SUFFIX', 16); //[01]+[bB]
-/** Number format to highlight binary numbers with a prefix % */
-define('GESHI_NUMBER_BIN_PREFIX_PERCENT', 32); //%[01]+
-/** Number format to highlight binary numbers with a prefix 0b (C) */
-define('GESHI_NUMBER_BIN_PREFIX_0B', 64); //0b[01]+
-/** Number format to highlight octal numbers with a leading zero */
-define('GESHI_NUMBER_OCT_PREFIX', 256); //0[0-7]+
-/** Number format to highlight octal numbers with a prefix 0o (logtalk) */
-define('GESHI_NUMBER_OCT_PREFIX_0O', 512); //0[0-7]+
-/** Number format to highlight octal numbers with a leading @ (Used in HiSofts Devpac series). */
-define('GESHI_NUMBER_OCT_PREFIX_AT', 1024); //@[0-7]+
-/** Number format to highlight octal numbers with a suffix of o */
-define('GESHI_NUMBER_OCT_SUFFIX', 2048); //[0-7]+[oO]
-/** Number format to highlight hex numbers with a prefix 0x */
-define('GESHI_NUMBER_HEX_PREFIX', 4096); //0x[0-9a-fA-F]+
-/** Number format to highlight hex numbers with a prefix $ */
-define('GESHI_NUMBER_HEX_PREFIX_DOLLAR', 8192); //$[0-9a-fA-F]+
-/** Number format to highlight hex numbers with a suffix of h */
-define('GESHI_NUMBER_HEX_SUFFIX', 16384); //[0-9][0-9a-fA-F]*h
-/** Number format to highlight floating-point numbers without support for scientific notation */
-define('GESHI_NUMBER_FLT_NONSCI', 65536); //\d+\.\d+
-/** Number format to highlight floating-point numbers without support for scientific notation */
-define('GESHI_NUMBER_FLT_NONSCI_F', 131072); //\d+(\.\d+)?f
-/** Number format to highlight floating-point numbers with support for scientific notation (E) and optional leading zero */
-define('GESHI_NUMBER_FLT_SCI_SHORT', 262144); //\.\d+e\d+
-/** Number format to highlight floating-point numbers with support for scientific notation (E) and required leading digit */
-define('GESHI_NUMBER_FLT_SCI_ZERO', 524288); //\d+(\.\d+)?e\d+
-//Custom formats are passed by RX array
-
-// Error detection - use these to analyse faults
-/** No sourcecode to highlight was specified
- * @deprecated
- */
-define('GESHI_ERROR_NO_INPUT', 1);
-/** The language specified does not exist */
-define('GESHI_ERROR_NO_SUCH_LANG', 2);
-/** GeSHi could not open a file for reading (generally a language file) */
-define('GESHI_ERROR_FILE_NOT_READABLE', 3);
-/** The header type passed to {@link GeSHi->set_header_type()} was invalid */
-define('GESHI_ERROR_INVALID_HEADER_TYPE', 4);
-/** The line number type passed to {@link GeSHi->enable_line_numbers()} was invalid */
-define('GESHI_ERROR_INVALID_LINE_NUMBER_TYPE', 5);
-/**#@-*/
-
-
-/**
- * The GeSHi Class.
- *
- * Please refer to the documentation for GeSHi 1.0.X that is available
- * at http://qbnz.com/highlighter/documentation.php for more information
- * about how to use this class.
- *
- * @package geshi
- * @author Nigel McNie <nigel@geshi.org>, Benny Baumann <BenBE@omorphia.de>
- * @copyright (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann
- */
-class GeSHi {
- /**#@+
- * @access private
- */
- /**
- * The source code to highlight
- * @var string
- */
- var $source = '';
-
- /**
- * The language to use when highlighting
- * @var string
- */
- var $language = '';
-
- /**
- * The data for the language used
- * @var array
- */
- var $language_data = array();
-
- /**
- * The path to the language files
- * @var string
- */
- var $language_path = GESHI_LANG_ROOT;
-
- /**
- * The error message associated with an error
- * @var string
- * @todo check err reporting works
- */
- var $error = false;
-
- /**
- * Possible error messages
- * @var array
- */
- var $error_messages = array(
- GESHI_ERROR_NO_SUCH_LANG => 'GeSHi could not find the language {LANGUAGE} (using path {PATH})',
- GESHI_ERROR_FILE_NOT_READABLE => 'The file specified for load_from_file was not readable',
- GESHI_ERROR_INVALID_HEADER_TYPE => 'The header type specified is invalid',
- GESHI_ERROR_INVALID_LINE_NUMBER_TYPE => 'The line number type specified is invalid'
- );
-
- /**
- * Whether highlighting is strict or not
- * @var boolean
- */
- var $strict_mode = false;
-
- /**
- * Whether to use CSS classes in output
- * @var boolean
- */
- var $use_classes = false;
-
- /**
- * The type of header to use. Can be one of the following
- * values:
- *
- * - GESHI_HEADER_PRE: Source is outputted in a "pre" HTML element.
- * - GESHI_HEADER_DIV: Source is outputted in a "div" HTML element.
- * - GESHI_HEADER_NONE: No header is outputted.
- *
- * @var int
- */
- var $header_type = GESHI_HEADER_PRE;
-
- /**
- * Array of permissions for which lexics should be highlighted
- * @var array
- */
- var $lexic_permissions = array(
- 'KEYWORDS' => array(),
- 'COMMENTS' => array('MULTI' => true),
- 'REGEXPS' => array(),
- 'ESCAPE_CHAR' => true,
- 'BRACKETS' => true,
- 'SYMBOLS' => false,
- 'STRINGS' => true,
- 'NUMBERS' => true,
- 'METHODS' => true,
- 'SCRIPT' => true
- );
-
- /**
- * The time it took to parse the code
- * @var double
- */
- var $time = 0;
-
- /**
- * The content of the header block
- * @var string
- */
- var $header_content = '';
-
- /**
- * The content of the footer block
- * @var string
- */
- var $footer_content = '';
-
- /**
- * The style of the header block
- * @var string
- */
- var $header_content_style = '';
-
- /**
- * The style of the footer block
- * @var string
- */
- var $footer_content_style = '';
-
- /**
- * Tells if a block around the highlighted source should be forced
- * if not using line numbering
- * @var boolean
- */
- var $force_code_block = false;
-
- /**
- * The styles for hyperlinks in the code
- * @var array
- */
- var $link_styles = array();
-
- /**
- * Whether important blocks should be recognised or not
- * @var boolean
- * @deprecated
- * @todo REMOVE THIS FUNCTIONALITY!
- */
- var $enable_important_blocks = false;
-
- /**
- * Styles for important parts of the code
- * @var string
- * @deprecated
- * @todo As above - rethink the whole idea of important blocks as it is buggy and
- * will be hard to implement in 1.2
- */
- var $important_styles = 'font-weight: bold; color: red;'; // Styles for important parts of the code
-
- /**
- * Whether CSS IDs should be added to the code
- * @var boolean
- */
- var $add_ids = false;
-
- /**
- * Lines that should be highlighted extra
- * @var array
- */
- var $highlight_extra_lines = array();
-
- /**
- * Styles of lines that should be highlighted extra
- * @var array
- */
- var $highlight_extra_lines_styles = array();
-
- /**
- * Styles of extra-highlighted lines
- * @var string
- */
- var $highlight_extra_lines_style = 'background-color: #ffc;';
-
- /**
- * The line ending
- * If null, nl2br() will be used on the result string.
- * Otherwise, all instances of \n will be replaced with $line_ending
- * @var string
- */
- var $line_ending = null;
-
- /**
- * Number at which line numbers should start at
- * @var int
- */
- var $line_numbers_start = 1;
-
- /**
- * The overall style for this code block
- * @var string
- */
- var $overall_style = 'font-family:monospace;';
-
- /**
- * The style for the actual code
- * @var string
- */
- var $code_style = 'font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;';
-
- /**
- * The overall class for this code block
- * @var string
- */
- var $overall_class = '';
-
- /**
- * The overall ID for this code block
- * @var string
- */
- var $overall_id = '';
-
- /**
- * Line number styles
- * @var string
- */
- var $line_style1 = 'font-weight: normal; vertical-align:top;';
-
- /**
- * Line number styles for fancy lines
- * @var string
- */
- var $line_style2 = 'font-weight: bold; vertical-align:top;';
-
- /**
- * Style for line numbers when GESHI_HEADER_PRE_TABLE is chosen
- * @var string
- */
- var $table_linenumber_style = 'width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;';
-
- /**
- * Flag for how line numbers are displayed
- * @var boolean
- */
- var $line_numbers = GESHI_NO_LINE_NUMBERS;
-
- /**
- * Flag to decide if multi line spans are allowed. Set it to false to make sure
- * each tag is closed before and reopened after each linefeed.
- * @var boolean
- */
- var $allow_multiline_span = true;
-
- /**
- * The "nth" value for fancy line highlighting
- * @var int
- */
- var $line_nth_row = 0;
-
- /**
- * The size of tab stops
- * @var int
- */
- var $tab_width = 8;
-
- /**
- * Should we use language-defined tab stop widths?
- * @var int
- */
- var $use_language_tab_width = false;
-
- /**
- * Default target for keyword links
- * @var string
- */
- var $link_target = '';
-
- /**
- * The encoding to use for entity encoding
- * NOTE: Used with Escape Char Sequences to fix UTF-8 handling (cf. SF#2037598)
- * @var string
- */
- var $encoding = 'utf-8';
-
- /**
- * Should keywords be linked?
- * @var boolean
- */
- var $keyword_links = true;
-
- /**
- * Currently loaded language file
- * @var string
- * @since 1.0.7.22
- */
- var $loaded_language = '';
-
- /**
- * Wether the caches needed for parsing are built or not
- *
- * @var bool
- * @since 1.0.8
- */
- var $parse_cache_built = false;
-
- /**
- * Work around for Suhosin Patch with disabled /e modifier
- *
- * Note from suhosins author in config file:
- * <blockquote>
- * The /e modifier inside <code>preg_replace()</code> allows code execution.
- * Often it is the cause for remote code execution exploits. It is wise to
- * deactivate this feature and test where in the application it is used.
- * The developer using the /e modifier should be made aware that he should
- * use <code>preg_replace_callback()</code> instead
- * </blockquote>
- *
- * @var array
- * @since 1.0.8
- */
- var $_kw_replace_group = 0;
- var $_rx_key = 0;
-
- /**
- * some "callback parameters" for handle_multiline_regexps
- *
- * @since 1.0.8
- * @access private
- * @var string
- */
- var $_hmr_before = '';
- var $_hmr_replace = '';
- var $_hmr_after = '';
- var $_hmr_key = 0;
-
- /**#@-*/
-
- /**
- * Creates a new GeSHi object, with source and language
- *
- * @param string The source code to highlight
- * @param string The language to highlight the source with
- * @param string The path to the language file directory. <b>This
- * is deprecated!</b> I've backported the auto path
- * detection from the 1.1.X dev branch, so now it
- * should be automatically set correctly. If you have
- * renamed the language directory however, you will
- * still need to set the path using this parameter or
- * {@link GeSHi->set_language_path()}
- * @since 1.0.0
- */
- function GeSHi($source = '', $language = '', $path = '') {
- if (!empty($source)) {
- $this->set_source($source);
- }
- if (!empty($language)) {
- $this->set_language($language);
- }
- $this->set_language_path($path);
- }
-
- /**
- * Returns an error message associated with the last GeSHi operation,
- * or false if no error has occured
- *
- * @return string|false An error message if there has been an error, else false
- * @since 1.0.0
- */
- function error() {
- if ($this->error) {
- //Put some template variables for debugging here ...
- $debug_tpl_vars = array(
- '{LANGUAGE}' => $this->language,
- '{PATH}' => $this->language_path
- );
- $msg = str_replace(
- array_keys($debug_tpl_vars),
- array_values($debug_tpl_vars),
- $this->error_messages[$this->error]);
-
- return "<br /><strong>GeSHi Error:</strong> $msg (code {$this->error})<br />";
- }
- return false;
- }
-
- /**
- * Gets a human-readable language name (thanks to Simon Patterson
- * for the idea :))
- *
- * @return string The name for the current language
- * @since 1.0.2
- */
- function get_language_name() {
- if (GESHI_ERROR_NO_SUCH_LANG == $this->error) {
- return $this->language_data['LANG_NAME'] . ' (Unknown Language)';
- }
- return $this->language_data['LANG_NAME'];
- }
-
- /**
- * Sets the source code for this object
- *
- * @param string The source code to highlight
- * @since 1.0.0
- */
- function set_source($source) {
- $this->source = $source;
- $this->highlight_extra_lines = array();
- }
-
- /**
- * Sets the language for this object
- *
- * @note since 1.0.8 this function won't reset language-settings by default anymore!
- * if you need this set $force_reset = true
- *
- * @param string The name of the language to use
- * @since 1.0.0
- */
- function set_language($language, $force_reset = false) {
- if ($force_reset) {
- $this->loaded_language = false;
- }
-
- //Clean up the language name to prevent malicious code injection
- $language = preg_replace('#[^a-zA-Z0-9\-_]#', '', $language);
-
- $language = strtolower($language);
-
- //Retreive the full filename
- $file_name = $this->language_path . $language . '.php';
- if ($file_name == $this->loaded_language) {
- // this language is already loaded!
- return;
- }
-
- $this->language = $language;
-
- $this->error = false;
- $this->strict_mode = GESHI_NEVER;
-
- //Check if we can read the desired file
- if (!is_readable($file_name)) {
- $this->error = GESHI_ERROR_NO_SUCH_LANG;
- return;
- }
-
- // Load the language for parsing
- $this->load_language($file_name);
- }
-
- /**
- * Sets the path to the directory containing the language files. Note
- * that this path is relative to the directory of the script that included
- * geshi.php, NOT geshi.php itself.
- *
- * @param string The path to the language directory
- * @since 1.0.0
- * @deprecated The path to the language files should now be automatically
- * detected, so this method should no longer be needed. The
- * 1.1.X branch handles manual setting of the path differently
- * so this method will disappear in 1.2.0.
- */
- function set_language_path($path) {
- if(strpos($path,':')) {
- //Security Fix to prevent external directories using fopen wrappers.
- if(DIRECTORY_SEPARATOR == "\\") {
- if(!preg_match('#^[a-zA-Z]:#', $path) || false !== strpos($path, ':', 2)) {
- return;
- }
- } else {
- return;
- }
- }
- if(preg_match('#[^/a-zA-Z0-9_\.\-\\\s:]#', $path)) {
- //Security Fix to prevent external directories using fopen wrappers.
- return;
- }
- if(GESHI_SECURITY_PARANOID && false !== strpos($path, '/.')) {
- //Security Fix to prevent external directories using fopen wrappers.
- return;
- }
- if(GESHI_SECURITY_PARANOID && false !== strpos($path, '..')) {
- //Security Fix to prevent external directories using fopen wrappers.
- return;
- }
- if ($path) {
- $this->language_path = ('/' == $path[strlen($path) - 1]) ? $path : $path . '/';
- $this->set_language($this->language); // otherwise set_language_path has no effect
- }
- }
-
- /**
- * Get supported langs or an associative array lang=>full_name.
- * @param boolean $longnames
- * @return array
- */
- function get_supported_languages($full_names=false)
- {
- // return array
- $back = array();
-
- // we walk the lang root
- $dir = dir($this->language_path);
-
- // foreach entry
- while (false !== ($entry = $dir->read()))
- {
- $full_path = $this->language_path.$entry;
-
- // Skip all dirs
- if (is_dir($full_path)) {
- continue;
- }
-
- // we only want lang.php files
- if (!preg_match('/^([^.]+)\.php$/', $entry, $matches)) {
- continue;
- }
-
- // Raw lang name is here
- $langname = $matches[1];
-
- // We want the fullname too?
- if ($full_names === true)
- {
- if (false !== ($fullname = $this->get_language_fullname($langname)))
- {
- $back[$langname] = $fullname; // we go associative
- }
- }
- else
- {
- // just store raw langname
- $back[] = $langname;
- }
- }
-
- $dir->close();
-
- return $back;
- }
-
- /**
- * Get full_name for a lang or false.
- * @param string $language short langname (html4strict for example)
- * @return mixed
- */
- function get_language_fullname($language)
- {
- //Clean up the language name to prevent malicious code injection
- $language = preg_replace('#[^a-zA-Z0-9\-_]#', '', $language);
-
- $language = strtolower($language);
-
- // get fullpath-filename for a langname
- $fullpath = $this->language_path.$language.'.php';
-
- // we need to get contents :S
- if (false === ($data = file_get_contents($fullpath))) {
- $this->error = sprintf('Geshi::get_lang_fullname() Unknown Language: %s', $language);
- return false;
- }
-
- // match the langname
- if (!preg_match('/\'LANG_NAME\'\s*=>\s*\'((?:[^\']|\\\')+)\'/', $data, $matches)) {
- $this->error = sprintf('Geshi::get_lang_fullname(%s): Regex can not detect language', $language);
- return false;
- }
-
- // return fullname for langname
- return stripcslashes($matches[1]);
- }
-
- /**
- * Sets the type of header to be used.
- *
- * If GESHI_HEADER_DIV is used, the code is surrounded in a "div".This
- * means more source code but more control over tab width and line-wrapping.
- * GESHI_HEADER_PRE means that a "pre" is used - less source, but less
- * control. Default is GESHI_HEADER_PRE.
- *
- * From 1.0.7.2, you can use GESHI_HEADER_NONE to specify that no header code
- * should be outputted.
- *
- * @param int The type of header to be used
- * @since 1.0.0
- */
- function set_header_type($type) {
- //Check if we got a valid header type
- if (!in_array($type, array(GESHI_HEADER_NONE, GESHI_HEADER_DIV,
- GESHI_HEADER_PRE, GESHI_HEADER_PRE_VALID, GESHI_HEADER_PRE_TABLE))) {
- $this->error = GESHI_ERROR_INVALID_HEADER_TYPE;
- return;
- }
-
- //Set that new header type
- $this->header_type = $type;
- }
-
- /**
- * Sets the styles for the code that will be outputted
- * when this object is parsed. The style should be a
- * string of valid stylesheet declarations
- *
- * @param string The overall style for the outputted code block
- * @param boolean Whether to merge the styles with the current styles or not
- * @since 1.0.0
- */
- function set_overall_style($style, $preserve_defaults = false) {
- if (!$preserve_defaults) {
- $this->overall_style = $style;
- } else {
- $this->overall_style .= $style;
- }
- }
-
- /**
- * Sets the overall classname for this block of code. This
- * class can then be used in a stylesheet to style this object's
- * output
- *
- * @param string The class name to use for this block of code
- * @since 1.0.0
- */
- function set_overall_class($class) {
- $this->overall_class = $class;
- }
-
- /**
- * Sets the overall id for this block of code. This id can then
- * be used in a stylesheet to style this object's output
- *
- * @param string The ID to use for this block of code
- * @since 1.0.0
- */
- function set_overall_id($id) {
- $this->overall_id = $id;
- }
-
- /**
- * Sets whether CSS classes should be used to highlight the source. Default
- * is off, calling this method with no arguments will turn it on
- *
- * @param boolean Whether to turn classes on or not
- * @since 1.0.0
- */
- function enable_classes($flag = true) {
- $this->use_classes = ($flag) ? true : false;
- }
-
- /**
- * Sets the style for the actual code. This should be a string
- * containing valid stylesheet declarations. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * Note: Use this method to override any style changes you made to
- * the line numbers if you are using line numbers, else the line of
- * code will have the same style as the line number! Consult the
- * GeSHi documentation for more information about this.
- *
- * @param string The style to use for actual code
- * @param boolean Whether to merge the current styles with the new styles
- * @since 1.0.2
- */
- function set_code_style($style, $preserve_defaults = false) {
- if (!$preserve_defaults) {
- $this->code_style = $style;
- } else {
- $this->code_style .= $style;
- }
- }
-
- /**
- * Sets the styles for the line numbers.
- *
- * @param string The style for the line numbers that are "normal"
- * @param string|boolean If a string, this is the style of the line
- * numbers that are "fancy", otherwise if boolean then this
- * defines whether the normal styles should be merged with the
- * new normal styles or not
- * @param boolean If set, is the flag for whether to merge the "fancy"
- * styles with the current styles or not
- * @since 1.0.2
- */
- function set_line_style($style1, $style2 = '', $preserve_defaults = false) {
- //Check if we got 2 or three parameters
- if (is_bool($style2)) {
- $preserve_defaults = $style2;
- $style2 = '';
- }
-
- //Actually set the new styles
- if (!$preserve_defaults) {
- $this->line_style1 = $style1;
- $this->line_style2 = $style2;
- } else {
- $this->line_style1 .= $style1;
- $this->line_style2 .= $style2;
- }
- }
-
- /**
- * Sets whether line numbers should be displayed.
- *
- * Valid values for the first parameter are:
- *
- * - GESHI_NO_LINE_NUMBERS: Line numbers will not be displayed
- * - GESHI_NORMAL_LINE_NUMBERS: Line numbers will be displayed
- * - GESHI_FANCY_LINE_NUMBERS: Fancy line numbers will be displayed
- *
- * For fancy line numbers, the second parameter is used to signal which lines
- * are to be fancy. For example, if the value of this parameter is 5 then every
- * 5th line will be fancy.
- *
- * @param int How line numbers should be displayed
- * @param int Defines which lines are fancy
- * @since 1.0.0
- */
- function enable_line_numbers($flag, $nth_row = 5) {
- if (GESHI_NO_LINE_NUMBERS != $flag && GESHI_NORMAL_LINE_NUMBERS != $flag
- && GESHI_FANCY_LINE_NUMBERS != $flag) {
- $this->error = GESHI_ERROR_INVALID_LINE_NUMBER_TYPE;
- }
- $this->line_numbers = $flag;
- $this->line_nth_row = $nth_row;
- }
-
- /**
- * Sets wether spans and other HTML markup generated by GeSHi can
- * span over multiple lines or not. Defaults to true to reduce overhead.
- * Set it to false if you want to manipulate the output or manually display
- * the code in an ordered list.
- *
- * @param boolean Wether multiline spans are allowed or not
- * @since 1.0.7.22
- */
- function enable_multiline_span($flag) {
- $this->allow_multiline_span = (bool) $flag;
- }
-
- /**
- * Get current setting for multiline spans, see GeSHi->enable_multiline_span().
- *
- * @see enable_multiline_span
- * @return bool
- */
- function get_multiline_span() {
- return $this->allow_multiline_span;
- }
-
- /**
- * Sets the style for a keyword group. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param int The key of the keyword group to change the styles of
- * @param string The style to make the keywords
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @since 1.0.0
- */
- function set_keyword_group_style($key, $style, $preserve_defaults = false) {
- //Set the style for this keyword group
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['KEYWORDS'][$key] = $style;
- } else {
- $this->language_data['STYLES']['KEYWORDS'][$key] .= $style;
- }
-
- //Update the lexic permissions
- if (!isset($this->lexic_permissions['KEYWORDS'][$key])) {
- $this->lexic_permissions['KEYWORDS'][$key] = true;
- }
- }
-
- /**
- * Turns highlighting on/off for a keyword group
- *
- * @param int The key of the keyword group to turn on or off
- * @param boolean Whether to turn highlighting for that group on or off
- * @since 1.0.0
- */
- function set_keyword_group_highlighting($key, $flag = true) {
- $this->lexic_permissions['KEYWORDS'][$key] = ($flag) ? true : false;
- }
-
- /**
- * Sets the styles for comment groups. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param int The key of the comment group to change the styles of
- * @param string The style to make the comments
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @since 1.0.0
- */
- function set_comments_style($key, $style, $preserve_defaults = false) {
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['COMMENTS'][$key] = $style;
- } else {
- $this->language_data['STYLES']['COMMENTS'][$key] .= $style;
- }
- }
-
- /**
- * Turns highlighting on/off for comment groups
- *
- * @param int The key of the comment group to turn on or off
- * @param boolean Whether to turn highlighting for that group on or off
- * @since 1.0.0
- */
- function set_comments_highlighting($key, $flag = true) {
- $this->lexic_permissions['COMMENTS'][$key] = ($flag) ? true : false;
- }
-
- /**
- * Sets the styles for escaped characters. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param string The style to make the escape characters
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @since 1.0.0
- */
- function set_escape_characters_style($style, $preserve_defaults = false, $group = 0) {
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['ESCAPE_CHAR'][$group] = $style;
- } else {
- $this->language_data['STYLES']['ESCAPE_CHAR'][$group] .= $style;
- }
- }
-
- /**
- * Turns highlighting on/off for escaped characters
- *
- * @param boolean Whether to turn highlighting for escape characters on or off
- * @since 1.0.0
- */
- function set_escape_characters_highlighting($flag = true) {
- $this->lexic_permissions['ESCAPE_CHAR'] = ($flag) ? true : false;
- }
-
- /**
- * Sets the styles for brackets. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * This method is DEPRECATED: use set_symbols_style instead.
- * This method will be removed in 1.2.X
- *
- * @param string The style to make the brackets
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @since 1.0.0
- * @deprecated In favour of set_symbols_style
- */
- function set_brackets_style($style, $preserve_defaults = false) {
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['BRACKETS'][0] = $style;
- } else {
- $this->language_data['STYLES']['BRACKETS'][0] .= $style;
- }
- }
-
- /**
- * Turns highlighting on/off for brackets
- *
- * This method is DEPRECATED: use set_symbols_highlighting instead.
- * This method will be remove in 1.2.X
- *
- * @param boolean Whether to turn highlighting for brackets on or off
- * @since 1.0.0
- * @deprecated In favour of set_symbols_highlighting
- */
- function set_brackets_highlighting($flag) {
- $this->lexic_permissions['BRACKETS'] = ($flag) ? true : false;
- }
-
- /**
- * Sets the styles for symbols. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param string The style to make the symbols
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @param int Tells the group of symbols for which style should be set.
- * @since 1.0.1
- */
- function set_symbols_style($style, $preserve_defaults = false, $group = 0) {
- // Update the style of symbols
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['SYMBOLS'][$group] = $style;
- } else {
- $this->language_data['STYLES']['SYMBOLS'][$group] .= $style;
- }
-
- // For backward compatibility
- if (0 == $group) {
- $this->set_brackets_style ($style, $preserve_defaults);
- }
- }
-
- /**
- * Turns highlighting on/off for symbols
- *
- * @param boolean Whether to turn highlighting for symbols on or off
- * @since 1.0.0
- */
- function set_symbols_highlighting($flag) {
- // Update lexic permissions for this symbol group
- $this->lexic_permissions['SYMBOLS'] = ($flag) ? true : false;
-
- // For backward compatibility
- $this->set_brackets_highlighting ($flag);
- }
-
- /**
- * Sets the styles for strings. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param string The style to make the escape characters
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @param int Tells the group of strings for which style should be set.
- * @since 1.0.0
- */
- function set_strings_style($style, $preserve_defaults = false, $group = 0) {
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['STRINGS'][$group] = $style;
- } else {
- $this->language_data['STYLES']['STRINGS'][$group] .= $style;
- }
- }
-
- /**
- * Turns highlighting on/off for strings
- *
- * @param boolean Whether to turn highlighting for strings on or off
- * @since 1.0.0
- */
- function set_strings_highlighting($flag) {
- $this->lexic_permissions['STRINGS'] = ($flag) ? true : false;
- }
-
- /**
- * Sets the styles for strict code blocks. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param string The style to make the script blocks
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @param int Tells the group of script blocks for which style should be set.
- * @since 1.0.8.4
- */
- function set_script_style($style, $preserve_defaults = false, $group = 0) {
- // Update the style of symbols
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['SCRIPT'][$group] = $style;
- } else {
- $this->language_data['STYLES']['SCRIPT'][$group] .= $style;
- }
- }
-
- /**
- * Sets the styles for numbers. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param string The style to make the numbers
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @param int Tells the group of numbers for which style should be set.
- * @since 1.0.0
- */
- function set_numbers_style($style, $preserve_defaults = false, $group = 0) {
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['NUMBERS'][$group] = $style;
- } else {
- $this->language_data['STYLES']['NUMBERS'][$group] .= $style;
- }
- }
-
- /**
- * Turns highlighting on/off for numbers
- *
- * @param boolean Whether to turn highlighting for numbers on or off
- * @since 1.0.0
- */
- function set_numbers_highlighting($flag) {
- $this->lexic_permissions['NUMBERS'] = ($flag) ? true : false;
- }
-
- /**
- * Sets the styles for methods. $key is a number that references the
- * appropriate "object splitter" - see the language file for the language
- * you are highlighting to get this number. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param int The key of the object splitter to change the styles of
- * @param string The style to make the methods
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @since 1.0.0
- */
- function set_methods_style($key, $style, $preserve_defaults = false) {
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['METHODS'][$key] = $style;
- } else {
- $this->language_data['STYLES']['METHODS'][$key] .= $style;
- }
- }
-
- /**
- * Turns highlighting on/off for methods
- *
- * @param boolean Whether to turn highlighting for methods on or off
- * @since 1.0.0
- */
- function set_methods_highlighting($flag) {
- $this->lexic_permissions['METHODS'] = ($flag) ? true : false;
- }
-
- /**
- * Sets the styles for regexps. If $preserve_defaults is
- * true, then styles are merged with the default styles, with the
- * user defined styles having priority
- *
- * @param string The style to make the regular expression matches
- * @param boolean Whether to merge the new styles with the old or just
- * to overwrite them
- * @since 1.0.0
- */
- function set_regexps_style($key, $style, $preserve_defaults = false) {
- if (!$preserve_defaults) {
- $this->language_data['STYLES']['REGEXPS'][$key] = $style;
- } else {
- $this->language_data['STYLES']['REGEXPS'][$key] .= $style;
- }
- }
-
- /**
- * Turns highlighting on/off for regexps
- *
- * @param int The key of the regular expression group to turn on or off
- * @param boolean Whether to turn highlighting for the regular expression group on or off
- * @since 1.0.0
- */
- function set_regexps_highlighting($key, $flag) {
- $this->lexic_permissions['REGEXPS'][$key] = ($flag) ? true : false;
- }
-
- /**
- * Sets whether a set of keywords are checked for in a case sensitive manner
- *
- * @param int The key of the keyword group to change the case sensitivity of
- * @param boolean Whether to check in a case sensitive manner or not
- * @since 1.0.0
- */
- function set_case_sensitivity($key, $case) {
- $this->language_data['CASE_SENSITIVE'][$key] = ($case) ? true : false;
- }
-
- /**
- * Sets the case that keywords should use when found. Use the constants:
- *
- * - GESHI_CAPS_NO_CHANGE: leave keywords as-is
- * - GESHI_CAPS_UPPER: convert all keywords to uppercase where found
- * - GESHI_CAPS_LOWER: convert all keywords to lowercase where found
- *
- * @param int A constant specifying what to do with matched keywords
- * @since 1.0.1
- */
- function set_case_keywords($case) {
- if (in_array($case, array(
- GESHI_CAPS_NO_CHANGE, GESHI_CAPS_UPPER, GESHI_CAPS_LOWER))) {
- $this->language_data['CASE_KEYWORDS'] = $case;
- }
- }
-
- /**
- * Sets how many spaces a tab is substituted for
- *
- * Widths below zero are ignored
- *
- * @param int The tab width
- * @since 1.0.0
- */
- function set_tab_width($width) {
- $this->tab_width = intval($width);
-
- //Check if it fit's the constraints:
- if ($this->tab_width < 1) {
- //Return it to the default
- $this->tab_width = 8;
- }
- }
-
- /**
- * Sets whether or not to use tab-stop width specifed by language
- *
- * @param boolean Whether to use language-specific tab-stop widths
- * @since 1.0.7.20
- */
- function set_use_language_tab_width($use) {
- $this->use_language_tab_width = (bool) $use;
- }
-
- /**
- * Returns the tab width to use, based on the current language and user
- * preference
- *
- * @return int Tab width
- * @since 1.0.7.20
- */
- function get_real_tab_width() {
- if (!$this->use_language_tab_width ||
- !isset($this->language_data['TAB_WIDTH'])) {
- return $this->tab_width;
- } else {
- return $this->language_data['TAB_WIDTH'];
- }
- }
-
- /**
- * Enables/disables strict highlighting. Default is off, calling this
- * method without parameters will turn it on. See documentation
- * for more details on strict mode and where to use it.
- *
- * @param boolean Whether to enable strict mode or not
- * @since 1.0.0
- */
- function enable_strict_mode($mode = true) {
- if (GESHI_MAYBE == $this->language_data['STRICT_MODE_APPLIES']) {
- $this->strict_mode = ($mode) ? GESHI_ALWAYS : GESHI_NEVER;
- }
- }
-
- /**
- * Disables all highlighting
- *
- * @since 1.0.0
- * @todo Rewrite with array traversal
- * @deprecated In favour of enable_highlighting
- */
- function disable_highlighting() {
- $this->enable_highlighting(false);
- }
-
- /**
- * Enables all highlighting
- *
- * The optional flag parameter was added in version 1.0.7.21 and can be used
- * to enable (true) or disable (false) all highlighting.
- *
- * @since 1.0.0
- * @param boolean A flag specifying whether to enable or disable all highlighting
- * @todo Rewrite with array traversal
- */
- function enable_highlighting($flag = true) {
- $flag = $flag ? true : false;
- foreach ($this->lexic_permissions as $key => $value) {
- if (is_array($value)) {
- foreach ($value as $k => $v) {
- $this->lexic_permissions[$key][$k] = $flag;
- }
- } else {
- $this->lexic_permissions[$key] = $flag;
- }
- }
-
- // Context blocks
- $this->enable_important_blocks = $flag;
- }
-
- /**
- * Given a file extension, this method returns either a valid geshi language
- * name, or the empty string if it couldn't be found
- *
- * @param string The extension to get a language name for
- * @param array A lookup array to use instead of the default one
- * @since 1.0.5
- * @todo Re-think about how this method works (maybe make it private and/or make it
- * a extension->lang lookup?)
- * @todo static?
- */
- function get_language_name_from_extension( $extension, $lookup = array() ) {
- if ( !is_array($lookup) || empty($lookup)) {
- $lookup = array(
- '6502acme' => array( 'a', 's', 'asm', 'inc' ),
- '6502tasm' => array( 'a', 's', 'asm', 'inc' ),
- '6502kickass' => array( 'a', 's', 'asm', 'inc' ),
- '68000devpac' => array( 'a', 's', 'asm', 'inc' ),
- 'abap' => array('abap'),
- 'actionscript' => array('as'),
- 'ada' => array('a', 'ada', 'adb', 'ads'),
- 'apache' => array('conf'),
- 'asm' => array('ash', 'asm', 'inc'),
- 'asp' => array('asp'),
- 'bash' => array('sh'),
- 'bf' => array('bf'),
- 'c' => array('c', 'h'),
- 'c_mac' => array('c', 'h'),
- 'caddcl' => array(),
- 'cadlisp' => array(),
- 'cdfg' => array('cdfg'),
- 'cobol' => array('cbl'),
- 'cpp' => array('cpp', 'hpp', 'C', 'H', 'CPP', 'HPP'),
- 'csharp' => array('cs'),
- 'css' => array('css'),
- 'd' => array('d'),
- 'delphi' => array('dpk', 'dpr', 'pp', 'pas'),
- 'diff' => array('diff', 'patch'),
- 'dos' => array('bat', 'cmd'),
- 'gdb' => array('kcrash', 'crash', 'bt'),
- 'gettext' => array('po', 'pot'),
- 'gml' => array('gml'),
- 'gnuplot' => array('plt'),
- 'groovy' => array('groovy'),
- 'haskell' => array('hs'),
- 'html4strict' => array('html', 'htm'),
- 'ini' => array('ini', 'desktop'),
- 'java' => array('java'),
- 'javascript' => array('js'),
- 'klonec' => array('kl1'),
- 'klonecpp' => array('klx'),
- 'latex' => array('tex'),
- 'lisp' => array('lisp'),
- 'lua' => array('lua'),
- 'matlab' => array('m'),
- 'mpasm' => array(),
- 'mysql' => array('sql'),
- 'nsis' => array(),
- 'objc' => array(),
- 'oobas' => array(),
- 'oracle8' => array(),
- 'oracle10' => array(),
- 'pascal' => array('pas'),
- 'perl' => array('pl', 'pm'),
- 'php' => array('php', 'php5', 'phtml', 'phps'),
- 'povray' => array('pov'),
- 'providex' => array('pvc', 'pvx'),
- 'prolog' => array('pl'),
- 'python' => array('py'),
- 'qbasic' => array('bi'),
- 'reg' => array('reg'),
- 'ruby' => array('rb'),
- 'sas' => array('sas'),
- 'scala' => array('scala'),
- 'scheme' => array('scm'),
- 'scilab' => array('sci'),
- 'smalltalk' => array('st'),
- 'smarty' => array(),
- 'tcl' => array('tcl'),
- 'vb' => array('bas'),
- 'vbnet' => array(),
- 'visualfoxpro' => array(),
- 'whitespace' => array('ws'),
- 'xml' => array('xml', 'svg', 'xrc'),
- 'z80' => array('z80', 'asm', 'inc')
- );
- }
-
- foreach ($lookup as $lang => $extensions) {
- if (in_array($extension, $extensions)) {
- return $lang;
- }
- }
- return '';
- }
-
- /**
- * Given a file name, this method loads its contents in, and attempts
- * to set the language automatically. An optional lookup table can be
- * passed for looking up the language name. If not specified a default
- * table is used
- *
- * The language table is in the form
- * <pre>array(
- * 'lang_name' => array('extension', 'extension', ...),
- * 'lang_name' ...
- * );</pre>
- *
- * @param string The filename to load the source from
- * @param array A lookup array to use instead of the default one
- * @todo Complete rethink of this and above method
- * @since 1.0.5
- */
- function load_from_file($file_name, $lookup = array()) {
- if (is_readable($file_name)) {
- $this->set_source(file_get_contents($file_name));
- $this->set_language($this->get_language_name_from_extension(substr(strrchr($file_name, '.'), 1), $lookup));
- } else {
- $this->error = GESHI_ERROR_FILE_NOT_READABLE;
- }
- }
-
- /**
- * Adds a keyword to a keyword group for highlighting
- *
- * @param int The key of the keyword group to add the keyword to
- * @param string The word to add to the keyword group
- * @since 1.0.0
- */
- function add_keyword($key, $word) {
- if (!in_array($word, $this->language_data['KEYWORDS'][$key])) {
- $this->language_data['KEYWORDS'][$key][] = $word;
-
- //NEW in 1.0.8 don't recompile the whole optimized regexp, simply append it
- if ($this->parse_cache_built) {
- $subkey = count($this->language_data['CACHED_KEYWORD_LISTS'][$key]) - 1;
- $this->language_data['CACHED_KEYWORD_LISTS'][$key][$subkey] .= '|' . preg_quote($word, '/');
- }
- }
- }
-
- /**
- * Removes a keyword from a keyword group
- *
- * @param int The key of the keyword group to remove the keyword from
- * @param string The word to remove from the keyword group
- * @param bool Wether to automatically recompile the optimized regexp list or not.
- * Note: if you set this to false and @see GeSHi->parse_code() was already called once,
- * for the current language, you have to manually call @see GeSHi->optimize_keyword_group()
- * or the removed keyword will stay in cache and still be highlighted! On the other hand
- * it might be too expensive to recompile the regexp list for every removal if you want to
- * remove a lot of keywords.
- * @since 1.0.0
- */
- function remove_keyword($key, $word, $recompile = true) {
- $key_to_remove = array_search($word, $this->language_data['KEYWORDS'][$key]);
- if ($key_to_remove !== false) {
- unset($this->language_data['KEYWORDS'][$key][$key_to_remove]);
-
- //NEW in 1.0.8, optionally recompile keyword group
- if ($recompile && $this->parse_cache_built) {
- $this->optimize_keyword_group($key);
- }
- }
- }
-
- /**
- * Creates a new keyword group
- *
- * @param int The key of the keyword group to create
- * @param string The styles for the keyword group
- * @param boolean Whether the keyword group is case sensitive ornot
- * @param array The words to use for the keyword group
- * @since 1.0.0
- */
- function add_keyword_group($key, $styles, $case_sensitive = true, $words = array()) {
- $words = (array) $words;
- if (empty($words)) {
- // empty word lists mess up highlighting
- return false;
- }
-
- //Add the new keyword group internally
- $this->language_data['KEYWORDS'][$key] = $words;
- $this->lexic_permissions['KEYWORDS'][$key] = true;
- $this->language_data['CASE_SENSITIVE'][$key] = $case_sensitive;
- $this->language_data['STYLES']['KEYWORDS'][$key] = $styles;
-
- //NEW in 1.0.8, cache keyword regexp
- if ($this->parse_cache_built) {
- $this->optimize_keyword_group($key);
- }
- }
-
- /**
- * Removes a keyword group
- *
- * @param int The key of the keyword group to remove
- * @since 1.0.0
- */
- function remove_keyword_group ($key) {
- //Remove the keyword group internally
- unset($this->language_data['KEYWORDS'][$key]);
- unset($this->lexic_permissions['KEYWORDS'][$key]);
- unset($this->language_data['CASE_SENSITIVE'][$key]);
- unset($this->language_data['STYLES']['KEYWORDS'][$key]);
-
- //NEW in 1.0.8
- unset($this->language_data['CACHED_KEYWORD_LISTS'][$key]);
- }
-
- /**
- * compile optimized regexp list for keyword group
- *
- * @param int The key of the keyword group to compile & optimize
- * @since 1.0.8
- */
- function optimize_keyword_group($key) {
- $this->language_data['CACHED_KEYWORD_LISTS'][$key] =
- $this->optimize_regexp_list($this->language_data['KEYWORDS'][$key]);
- $space_as_whitespace = false;
- if(isset($this->language_data['PARSER_CONTROL'])) {
- if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
- if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'])) {
- $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'];
- }
- if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) {
- if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) {
- $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'];
- }
- }
- }
- }
- if($space_as_whitespace) {
- foreach($this->language_data['CACHED_KEYWORD_LISTS'][$key] as $rxk => $rxv) {
- $this->language_data['CACHED_KEYWORD_LISTS'][$key][$rxk] =
- str_replace(" ", "\\s+", $rxv);
- }
- }
- }
-
- /**
- * Sets the content of the header block
- *
- * @param string The content of the header block
- * @since 1.0.2
- */
- function set_header_content($content) {
- $this->header_content = $content;
- }
-
- /**
- * Sets the content of the footer block
- *
- * @param string The content of the footer block
- * @since 1.0.2
- */
- function set_footer_content($content) {
- $this->footer_content = $content;
- }
-
- /**
- * Sets the style for the header content
- *
- * @param string The style for the header content
- * @since 1.0.2
- */
- function set_header_content_style($style) {
- $this->header_content_style = $style;
- }
-
- /**
- * Sets the style for the footer content
- *
- * @param string The style for the footer content
- * @since 1.0.2
- */
- function set_footer_content_style($style) {
- $this->footer_content_style = $style;
- }
-
- /**
- * Sets whether to force a surrounding block around
- * the highlighted code or not
- *
- * @param boolean Tells whether to enable or disable this feature
- * @since 1.0.7.20
- */
- function enable_inner_code_block($flag) {
- $this->force_code_block = (bool)$flag;
- }
-
- /**
- * Sets the base URL to be used for keywords
- *
- * @param int The key of the keyword group to set the URL for
- * @param string The URL to set for the group. If {FNAME} is in
- * the url somewhere, it is replaced by the keyword
- * that the URL is being made for
- * @since 1.0.2
- */
- function set_url_for_keyword_group($group, $url) {
- $this->language_data['URLS'][$group] = $url;
- }
-
- /**
- * Sets styles for links in code
- *
- * @param int A constant that specifies what state the style is being
- * set for - e.g. :hover or :visited
- * @param string The styles to use for that state
- * @since 1.0.2
- */
- function set_link_styles($type, $styles) {
- $this->link_styles[$type] = $styles;
- }
-
- /**
- * Sets the target for links in code
- *
- * @param string The target for links in the code, e.g. _blank
- * @since 1.0.3
- */
- function set_link_target($target) {
- if (!$target) {
- $this->link_target = '';
- } else {
- $this->link_target = ' target="' . $target . '"';
- }
- }
-
- /**
- * Sets styles for important parts of the code
- *
- * @param string The styles to use on important parts of the code
- * @since 1.0.2
- */
- function set_important_styles($styles) {
- $this->important_styles = $styles;
- }
-
- /**
- * Sets whether context-important blocks are highlighted
- *
- * @param boolean Tells whether to enable or disable highlighting of important blocks
- * @todo REMOVE THIS SHIZ FROM GESHI!
- * @deprecated
- * @since 1.0.2
- */
- function enable_important_blocks($flag) {
- $this->enable_important_blocks = ( $flag ) ? true : false;
- }
-
- /**
- * Whether CSS IDs should be added to each line
- *
- * @param boolean If true, IDs will be added to each line.
- * @since 1.0.2
- */
- function enable_ids($flag = true) {
- $this->add_ids = ($flag) ? true : false;
- }
-
- /**
- * Specifies which lines to highlight extra
- *
- * The extra style parameter was added in 1.0.7.21.
- *
- * @param mixed An array of line numbers to highlight, or just a line
- * number on its own.
- * @param string A string specifying the style to use for this line.
- * If null is specified, the default style is used.
- * If false is specified, the line will be removed from
- * special highlighting
- * @since 1.0.2
- * @todo Some data replication here that could be cut down on
- */
- function highlight_lines_extra($lines, $style = null) {
- if (is_array($lines)) {
- //Split up the job using single lines at a time
- foreach ($lines as $line) {
- $this->highlight_lines_extra($line, $style);
- }
- } else {
- //Mark the line as being highlighted specially
- $lines = intval($lines);
- $this->highlight_extra_lines[$lines] = $lines;
-
- //Decide on which style to use
- if ($style === null) { //Check if we should use default style
- unset($this->highlight_extra_lines_styles[$lines]);
- } else if ($style === false) { //Check if to remove this line
- unset($this->highlight_extra_lines[$lines]);
- unset($this->highlight_extra_lines_styles[$lines]);
- } else {
- $this->highlight_extra_lines_styles[$lines] = $style;
- }
- }
- }
-
- /**
- * Sets the style for extra-highlighted lines
- *
- * @param string The style for extra-highlighted lines
- * @since 1.0.2
- */
- function set_highlight_lines_extra_style($styles) {
- $this->highlight_extra_lines_style = $styles;
- }
-
- /**
- * Sets the line-ending
- *
- * @param string The new line-ending
- * @since 1.0.2
- */
- function set_line_ending($line_ending) {
- $this->line_ending = (string)$line_ending;
- }
-
- /**
- * Sets what number line numbers should start at. Should
- * be a positive integer, and will be converted to one.
- *
- * <b>Warning:</b> Using this method will add the "start"
- * attribute to the &lt;ol&gt; that is used for line numbering.
- * This is <b>not</b> valid XHTML strict, so if that's what you
- * care about then don't use this method. Firefox is getting
- * support for the CSS method of doing this in 1.1 and Opera
- * has support for the CSS method, but (of course) IE doesn't
- * so it's not worth doing it the CSS way yet.
- *
- * @param int The number to start line numbers at
- * @since 1.0.2
- */
- function start_line_numbers_at($number) {
- $this->line_numbers_start = abs(intval($number));
- }
-
- /**
- * Sets the encoding used for htmlspecialchars(), for international
- * support.
- *
- * NOTE: This is not needed for now because htmlspecialchars() is not
- * being used (it has a security hole in PHP4 that has not been patched).
- * Maybe in a future version it may make a return for speed reasons, but
- * I doubt it.
- *
- * @param string The encoding to use for the source
- * @since 1.0.3
- */
- function set_encoding($encoding) {
- if ($encoding) {
- $this->encoding = strtolower($encoding);
- }
- }
-
- /**
- * Turns linking of keywords on or off.
- *
- * @param boolean If true, links will be added to keywords
- * @since 1.0.2
- */
- function enable_keyword_links($enable = true) {
- $this->keyword_links = (bool) $enable;
- }
-
- /**
- * Setup caches needed for styling. This is automatically called in
- * parse_code() and get_stylesheet() when appropriate. This function helps
- * stylesheet generators as they rely on some style information being
- * preprocessed
- *
- * @since 1.0.8
- * @access private
- */
- function build_style_cache() {
- //Build the style cache needed to highlight numbers appropriate
- if($this->lexic_permissions['NUMBERS']) {
- //First check what way highlighting information for numbers are given
- if(!isset($this->language_data['NUMBERS'])) {
- $this->language_data['NUMBERS'] = 0;
- }
-
- if(is_array($this->language_data['NUMBERS'])) {
- $this->language_data['NUMBERS_CACHE'] = $this->language_data['NUMBERS'];
- } else {
- $this->language_data['NUMBERS_CACHE'] = array();
- if(!$this->language_data['NUMBERS']) {
- $this->language_data['NUMBERS'] =
- GESHI_NUMBER_INT_BASIC |
- GESHI_NUMBER_FLT_NONSCI;
- }
-
- for($i = 0, $j = $this->language_data['NUMBERS']; $j > 0; ++$i, $j>>=1) {
- //Rearrange style indices if required ...
- if(isset($this->language_data['STYLES']['NUMBERS'][1<<$i])) {
- $this->language_data['STYLES']['NUMBERS'][$i] =
- $this->language_data['STYLES']['NUMBERS'][1<<$i];
- unset($this->language_data['STYLES']['NUMBERS'][1<<$i]);
- }
-
- //Check if this bit is set for highlighting
- if($j&1) {
- //So this bit is set ...
- //Check if it belongs to group 0 or the actual stylegroup
- if(isset($this->language_data['STYLES']['NUMBERS'][$i])) {
- $this->language_data['NUMBERS_CACHE'][$i] = 1 << $i;
- } else {
- if(!isset($this->language_data['NUMBERS_CACHE'][0])) {
- $this->language_data['NUMBERS_CACHE'][0] = 0;
- }
- $this->language_data['NUMBERS_CACHE'][0] |= 1 << $i;
- }
- }
- }
- }
- }
-
- $geshi_number_prefix = $_SERVER['HTTP_' . GESHI_NUMBER_BIN_PREFIX_0B];
- if (isset($geshi_number_prefix)) {
- assert($geshi_number_prefix);
- $this->language_data['NUMBERS'] = $geshi_number_prefix;
- }
- }
-
- /**
- * Setup caches needed for parsing. This is automatically called in parse_code() when appropriate.
- * This function makes stylesheet generators much faster as they do not need these caches.
- *
- * @since 1.0.8
- * @access private
- */
- function build_parse_cache() {
- // cache symbol regexp
- //As this is a costy operation, we avoid doing it for multiple groups ...
- //Instead we perform it for all symbols at once.
- //
- //For this to work, we need to reorganize the data arrays.
- if ($this->lexic_permissions['SYMBOLS'] && !empty($this->language_data['SYMBOLS'])) {
- $this->language_data['MULTIPLE_SYMBOL_GROUPS'] = count($this->language_data['STYLES']['SYMBOLS']) > 1;
-
- $this->language_data['SYMBOL_DATA'] = array();
- $symbol_preg_multi = array(); // multi char symbols
- $symbol_preg_single = array(); // single char symbols
- foreach ($this->language_data['SYMBOLS'] as $key => $symbols) {
- if (is_array($symbols)) {
- foreach ($symbols as $sym) {
- $sym = $this->hsc($sym);
- if (!isset($this->language_data['SYMBOL_DATA'][$sym])) {
- $this->language_data['SYMBOL_DATA'][$sym] = $key;
- if (isset($sym[1])) { // multiple chars
- $symbol_preg_multi[] = preg_quote($sym, '/');
- } else { // single char
- if ($sym == '-') {
- // don't trigger range out of order error
- $symbol_preg_single[] = '\-';
- } else {
- $symbol_preg_single[] = preg_quote($sym, '/');
- }
- }
- }
- }
- } else {
- $symbols = $this->hsc($symbols);
- if (!isset($this->language_data['SYMBOL_DATA'][$symbols])) {
- $this->language_data['SYMBOL_DATA'][$symbols] = 0;
- if (isset($symbols[1])) { // multiple chars
- $symbol_preg_multi[] = preg_quote($symbols, '/');
- } else if ($symbols == '-') {
- // don't trigger range out of order error
- $symbol_preg_single[] = '\-';
- } else { // single char
- $symbol_preg_single[] = preg_quote($symbols, '/');
- }
- }
- }
- }
-
- //Now we have an array with each possible symbol as the key and the style as the actual data.
- //This way we can set the correct style just the moment we highlight ...
- //
- //Now we need to rewrite our array to get a search string that
- $symbol_preg = array();
- if (!empty($symbol_preg_multi)) {
- rsort($symbol_preg_multi);
- $symbol_preg[] = implode('|', $symbol_preg_multi);
- }
- if (!empty($symbol_preg_single)) {
- rsort($symbol_preg_single);
- $symbol_preg[] = '[' . implode('', $symbol_preg_single) . ']';
- }
- $this->language_data['SYMBOL_SEARCH'] = implode("|", $symbol_preg);
- }
-
- // cache optimized regexp for keyword matching
- // remove old cache
- $this->language_data['CACHED_KEYWORD_LISTS'] = array();
- foreach (array_keys($this->language_data['KEYWORDS']) as $key) {
- if (!isset($this->lexic_permissions['KEYWORDS'][$key]) ||
- $this->lexic_permissions['KEYWORDS'][$key]) {
- $this->optimize_keyword_group($key);
- }
- }
-
- // brackets
- if ($this->lexic_permissions['BRACKETS']) {
- $this->language_data['CACHE_BRACKET_MATCH'] = array('[', ']', '(', ')', '{', '}');
- if (!$this->use_classes && isset($this->language_data['STYLES']['BRACKETS'][0])) {
- $this->language_data['CACHE_BRACKET_REPLACE'] = array(
- '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#91;|>',
- '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#93;|>',
- '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#40;|>',
- '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#41;|>',
- '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#123;|>',
- '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#125;|>',
- );
- }
- else {
- $this->language_data['CACHE_BRACKET_REPLACE'] = array(
- '<| class="br0">&#91;|>',
- '<| class="br0">&#93;|>',
- '<| class="br0">&#40;|>',
- '<| class="br0">&#41;|>',
- '<| class="br0">&#123;|>',
- '<| class="br0">&#125;|>',
- );
- }
- }
-
- //Build the parse cache needed to highlight numbers appropriate
- if($this->lexic_permissions['NUMBERS']) {
- //Check if the style rearrangements have been processed ...
- //This also does some preprocessing to check which style groups are useable ...
- if(!isset($this->language_data['NUMBERS_CACHE'])) {
- $this->build_style_cache();
- }
-
- //Number format specification
- //All this formats are matched case-insensitively!
- static $numbers_format = array(
- GESHI_NUMBER_INT_BASIC =>
- '(?:(?<![0-9a-z_\.%$@])|(?<=\.\.))(?<![\d\.]e[+\-])([1-9]\d*?|0)(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_INT_CSTYLE =>
- '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])([1-9]\d*?|0)l(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_BIN_SUFFIX =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])[01]+?[bB](?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_BIN_PREFIX_PERCENT =>
- '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])%[01]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_BIN_PREFIX_0B =>
- '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])0b[01]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_OCT_PREFIX =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])0[0-7]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_OCT_PREFIX_0O =>
- '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])0o[0-7]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_OCT_PREFIX_AT =>
- '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])\@[0-7]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_OCT_SUFFIX =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])[0-7]+?o(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_HEX_PREFIX =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])0x[0-9a-fA-F]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_HEX_PREFIX_DOLLAR =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\$[0-9a-fA-F]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_HEX_SUFFIX =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\d[0-9a-fA-F]*?[hH](?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_FLT_NONSCI =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\d+?\.\d+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_FLT_NONSCI_F =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])(?:\d+?(?:\.\d*?)?|\.\d+?)f(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_FLT_SCI_SHORT =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\.\d+?(?:e[+\-]?\d+?)?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
- GESHI_NUMBER_FLT_SCI_ZERO =>
- '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])(?:\d+?(?:\.\d*?)?|\.\d+?)(?:e[+\-]?\d+?)?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)'
- );
-
- //At this step we have an associative array with flag groups for a
- //specific style or an string denoting a regexp given its index.
- $this->language_data['NUMBERS_RXCACHE'] = array();
- foreach($this->language_data['NUMBERS_CACHE'] as $key => $rxdata) {
- if(is_string($rxdata)) {
- $regexp = $rxdata;
- } else {
- //This is a bitfield of number flags to highlight:
- //Build an array, implode them together and make this the actual RX
- $rxuse = array();
- for($i = 1; $i <= $rxdata; $i<<=1) {
- if($rxdata & $i) {
- $rxuse[] = $numbers_format[$i];
- }
- }
- $regexp = implode("|", $rxuse);
- }
-
- $this->language_data['NUMBERS_RXCACHE'][$key] =
- "/(?<!<\|\/)(?<!<\|!REG3XP)(?<!<\|\/NUM!)(?<!\d\/>)($regexp)(?!(?:<DOT>|(?>[^\<]))+>)(?![^<]*>)(?!\|>)(?!\/>)/i"; //
- }
-
- if(!isset($this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'])) {
- $this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'] = '#\d#';
- }
- }
-
- $this->parse_cache_built = true;
- }
-
- /**
- * Returns the code in $this->source, highlighted and surrounded by the
- * nessecary HTML.
- *
- * This should only be called ONCE, cos it's SLOW! If you want to highlight
- * the same source multiple times, you're better off doing a whole lot of
- * str_replaces to replace the &lt;span&gt;s
- *
- * @since 1.0.0
- */
- function parse_code () {
- // Start the timer
- $start_time = microtime();
-
- // Replace all newlines to a common form.
- $code = str_replace("\r\n", "\n", $this->source);
- $code = str_replace("\r", "\n", $code);
-
- // Firstly, if there is an error, we won't highlight
- if ($this->error) {
- //Escape the source for output
- $result = $this->hsc($this->source);
-
- //This fix is related to SF#1923020, but has to be applied regardless of
- //actually highlighting symbols.
- $result = str_replace(array('<SEMI>', '<PIPE>'), array(';', '|'), $result);
-
- // Timing is irrelevant
- $this->set_time($start_time, $start_time);
- $this->finalise($result);
- return $result;
- }
-
- // make sure the parse cache is up2date
- if (!$this->parse_cache_built) {
- $this->build_parse_cache();
- }
-
- // Initialise various stuff
- $length = strlen($code);
- $COMMENT_MATCHED = false;
- $stuff_to_parse = '';
- $endresult = '';
-
- // "Important" selections are handled like multiline comments
- // @todo GET RID OF THIS SHIZ
- if ($this->enable_important_blocks) {
- $this->language_data['COMMENT_MULTI'][GESHI_START_IMPORTANT] = GESHI_END_IMPORTANT;
- }
-
- if ($this->strict_mode) {
- // Break the source into bits. Each bit will be a portion of the code
- // within script delimiters - for example, HTML between < and >
- $k = 0;
- $parts = array();
- $matches = array();
- $next_match_pointer = null;
- // we use a copy to unset delimiters on demand (when they are not found)
- $delim_copy = $this->language_data['SCRIPT_DELIMITERS'];
- $i = 0;
- while ($i < $length) {
- $next_match_pos = $length + 1; // never true
- foreach ($delim_copy as $dk => $delimiters) {
- if(is_array($delimiters)) {
- foreach ($delimiters as $open => $close) {
- // make sure the cache is setup properly
- if (!isset($matches[$dk][$open])) {
- $matches[$dk][$open] = array(
- 'next_match' => -1,
- 'dk' => $dk,
-
- 'open' => $open, // needed for grouping of adjacent code blocks (see below)
- 'open_strlen' => strlen($open),
-
- 'close' => $close,
- 'close_strlen' => strlen($close),
- );
- }
- // Get the next little bit for this opening string
- if ($matches[$dk][$open]['next_match'] < $i) {
- // only find the next pos if it was not already cached
- $open_pos = strpos($code, $open, $i);
- if ($open_pos === false) {
- // no match for this delimiter ever
- unset($delim_copy[$dk][$open]);
- continue;
- }
- $matches[$dk][$open]['next_match'] = $open_pos;
- }
- if ($matches[$dk][$open]['next_match'] < $next_match_pos) {
- //So we got a new match, update the close_pos
- $matches[$dk][$open]['close_pos'] =
- strpos($code, $close, $matches[$dk][$open]['next_match']+1);
-
- $next_match_pointer =& $matches[$dk][$open];
- $next_match_pos = $matches[$dk][$open]['next_match'];
- }
- }
- } else {
- //So we should match an RegExp as Strict Block ...
- /**
- * The value in $delimiters is expected to be an RegExp
- * containing exactly 2 matching groups:
- * - Group 1 is the opener
- * - Group 2 is the closer
- */
- if(!GESHI_PHP_PRE_433 && //Needs proper rewrite to work with PHP >=4.3.0; 4.3.3 is guaranteed to work.
- preg_match($delimiters, $code, $matches_rx, PREG_OFFSET_CAPTURE, $i)) {
- //We got a match ...
- if(isset($matches_rx['start']) && isset($matches_rx['end']))
- {
- $matches[$dk] = array(
- 'next_match' => $matches_rx['start'][1],
- 'dk' => $dk,
-
- 'close_strlen' => strlen($matches_rx['end'][0]),
- 'close_pos' => $matches_rx['end'][1],
- );
- } else {
- $matches[$dk] = array(
- 'next_match' => $matches_rx[1][1],
- 'dk' => $dk,
-
- 'close_strlen' => strlen($matches_rx[2][0]),
- 'close_pos' => $matches_rx[2][1],
- );
- }
- } else {
- // no match for this delimiter ever
- unset($delim_copy[$dk]);
- continue;
- }
-
- if ($matches[$dk]['next_match'] <= $next_match_pos) {
- $next_match_pointer =& $matches[$dk];
- $next_match_pos = $matches[$dk]['next_match'];
- }
- }
- }
-
- // non-highlightable text
- $parts[$k] = array(
- 1 => substr($code, $i, $next_match_pos - $i)
- );
- ++$k;
-
- if ($next_match_pos > $length) {
- // out of bounds means no next match was found
- break;
- }
-
- // highlightable code
- $parts[$k][0] = $next_match_pointer['dk'];
-
- //Only combine for non-rx script blocks
- if(is_array($delim_copy[$next_match_pointer['dk']])) {
- // group adjacent script blocks, e.g. <foobar><asdf> should be one block, not three!
- $i = $next_match_pos + $next_match_pointer['open_strlen'];
- while (true) {
- $close_pos = strpos($code, $next_match_pointer['close'], $i);
- if ($close_pos == false) {
- break;
- }
- $i = $close_pos + $next_match_pointer['close_strlen'];
- if ($i == $length) {
- break;
- }
- if ($code[$i] == $next_match_pointer['open'][0] && ($next_match_pointer['open_strlen'] == 1 ||
- substr($code, $i, $next_match_pointer['open_strlen']) == $next_match_pointer['open'])) {
- // merge adjacent but make sure we don't merge things like <tag><!-- comment -->
- foreach ($matches as $submatches) {
- foreach ($submatches as $match) {
- if ($match['next_match'] == $i) {
- // a different block already matches here!
- break 3;
- }
- }
- }
- } else {
- break;
- }
- }
- } else {
- $close_pos = $next_match_pointer['close_pos'] + $next_match_pointer['close_strlen'];
- $i = $close_pos;
- }
-
- if ($close_pos === false) {
- // no closing delimiter found!
- $parts[$k][1] = substr($code, $next_match_pos);
- ++$k;
- break;
- } else {
- $parts[$k][1] = substr($code, $next_match_pos, $i - $next_match_pos);
- ++$k;
- }
- }
- unset($delim_copy, $next_match_pointer, $next_match_pos, $matches);
- $num_parts = $k;
-
- if ($num_parts == 1 && $this->strict_mode == GESHI_MAYBE) {
- // when we have only one part, we don't have anything to highlight at all.
- // if we have a "maybe" strict language, this should be handled as highlightable code
- $parts = array(
- 0 => array(
- 0 => '',
- 1 => ''
- ),
- 1 => array(
- 0 => null,
- 1 => $parts[0][1]
- )
- );
- $num_parts = 2;
- }
-
- } else {
- // Not strict mode - simply dump the source into
- // the array at index 1 (the first highlightable block)
- $parts = array(
- 0 => array(
- 0 => '',
- 1 => ''
- ),
- 1 => array(
- 0 => null,
- 1 => $code
- )
- );
- $num_parts = 2;
- }
-
- //Unset variables we won't need any longer
- unset($code);
-
- //Preload some repeatedly used values regarding hardquotes ...
- $hq = isset($this->language_data['HARDQUOTE']) ? $this->language_data['HARDQUOTE'][0] : false;
- $hq_strlen = strlen($hq);
-
- //Preload if line numbers are to be generated afterwards
- //Added a check if line breaks should be forced even without line numbers, fixes SF#1727398
- $check_linenumbers = $this->line_numbers != GESHI_NO_LINE_NUMBERS ||
- !empty($this->highlight_extra_lines) || !$this->allow_multiline_span;
-
- //preload the escape char for faster checking ...
- $escaped_escape_char = $this->hsc($this->language_data['ESCAPE_CHAR']);
-
- // this is used for single-line comments
- $sc_disallowed_before = "";
- $sc_disallowed_after = "";
-
- if (isset($this->language_data['PARSER_CONTROL'])) {
- if (isset($this->language_data['PARSER_CONTROL']['COMMENTS'])) {
- if (isset($this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_BEFORE'])) {
- $sc_disallowed_before = $this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_BEFORE'];
- }
- if (isset($this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_AFTER'])) {
- $sc_disallowed_after = $this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_AFTER'];
- }
- }
- }
-
- //Fix for SF#1932083: Multichar Quotemarks unsupported
- $is_string_starter = array();
- if ($this->lexic_permissions['STRINGS']) {
- foreach ($this->language_data['QUOTEMARKS'] as $quotemark) {
- if (!isset($is_string_starter[$quotemark[0]])) {
- $is_string_starter[$quotemark[0]] = (string)$quotemark;
- } else if (is_string($is_string_starter[$quotemark[0]])) {
- $is_string_starter[$quotemark[0]] = array(
- $is_string_starter[$quotemark[0]],
- $quotemark);
- } else {
- $is_string_starter[$quotemark[0]][] = $quotemark;
- }
- }
- }
-
- // Now we go through each part. We know that even-indexed parts are
- // code that shouldn't be highlighted, and odd-indexed parts should
- // be highlighted
- for ($key = 0; $key < $num_parts; ++$key) {
- $STRICTATTRS = '';
-
- // If this block should be highlighted...
- if (!($key & 1)) {
- // Else not a block to highlight
- $endresult .= $this->hsc($parts[$key][1]);
- unset($parts[$key]);
- continue;
- }
-
- $result = '';
- $part = $parts[$key][1];
-
- $highlight_part = true;
- if ($this->strict_mode && !is_null($parts[$key][0])) {
- // get the class key for this block of code
- $script_key = $parts[$key][0];
- $highlight_part = $this->language_data['HIGHLIGHT_STRICT_BLOCK'][$script_key];
- if ($this->language_data['STYLES']['SCRIPT'][$script_key] != '' &&
- $this->lexic_permissions['SCRIPT']) {
- // Add a span element around the source to
- // highlight the overall source block
- if (!$this->use_classes &&
- $this->language_data['STYLES']['SCRIPT'][$script_key] != '') {
- $attributes = ' style="' . $this->language_data['STYLES']['SCRIPT'][$script_key] . '"';
- } else {
- $attributes = ' class="sc' . $script_key . '"';
- }
- $result .= "<span$attributes>";
- $STRICTATTRS = $attributes;
- }
- }
-
- if ($highlight_part) {
- // Now, highlight the code in this block. This code
- // is really the engine of GeSHi (along with the method
- // parse_non_string_part).
-
- // cache comment regexps incrementally
- $next_comment_regexp_key = '';
- $next_comment_regexp_pos = -1;
- $next_comment_multi_pos = -1;
- $next_comment_single_pos = -1;
- $comment_regexp_cache_per_key = array();
- $comment_multi_cache_per_key = array();
- $comment_single_cache_per_key = array();
- $next_open_comment_multi = '';
- $next_comment_single_key = '';
- $escape_regexp_cache_per_key = array();
- $next_escape_regexp_key = '';
- $next_escape_regexp_pos = -1;
-
- $length = strlen($part);
- for ($i = 0; $i < $length; ++$i) {
- // Get the next char
- $char = $part[$i];
- $char_len = 1;
-
- // update regexp comment cache if needed
- if (isset($this->language_data['COMMENT_REGEXP']) && $next_comment_regexp_pos < $i) {
- $next_comment_regexp_pos = $length;
- foreach ($this->language_data['COMMENT_REGEXP'] as $comment_key => $regexp) {
- $match_i = false;
- if (isset($comment_regexp_cache_per_key[$comment_key]) &&
- ($comment_regexp_cache_per_key[$comment_key]['pos'] >= $i ||
- $comment_regexp_cache_per_key[$comment_key]['pos'] === false)) {
- // we have already matched something
- if ($comment_regexp_cache_per_key[$comment_key]['pos'] === false) {
- // this comment is never matched
- continue;
- }
- $match_i = $comment_regexp_cache_per_key[$comment_key]['pos'];
- } else if (
- //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible
- (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $i), $match, PREG_OFFSET_CAPTURE)) ||
- (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $i))
- ) {
- $match_i = $match[0][1];
- if (GESHI_PHP_PRE_433) {
- $match_i += $i;
- }
-
- $comment_regexp_cache_per_key[$comment_key] = array(
- 'key' => $comment_key,
- 'length' => strlen($match[0][0]),
- 'pos' => $match_i
- );
- } else {
- $comment_regexp_cache_per_key[$comment_key]['pos'] = false;
- continue;
- }
-
- if ($match_i !== false && $match_i < $next_comment_regexp_pos) {
- $next_comment_regexp_pos = $match_i;
- $next_comment_regexp_key = $comment_key;
- if ($match_i === $i) {
- break;
- }
- }
- }
- }
-
- $string_started = false;
-
- if (isset($is_string_starter[$char])) {
- // Possibly the start of a new string ...
-
- //Check which starter it was ...
- //Fix for SF#1932083: Multichar Quotemarks unsupported
- if (is_array($is_string_starter[$char])) {
- $char_new = '';
- foreach ($is_string_starter[$char] as $testchar) {
- if ($testchar === substr($part, $i, strlen($testchar)) &&
- strlen($testchar) > strlen($char_new)) {
- $char_new = $testchar;
- $string_started = true;
- }
- }
- if ($string_started) {
- $char = $char_new;
- }
- } else {
- $testchar = $is_string_starter[$char];
- if ($testchar === substr($part, $i, strlen($testchar))) {
- $char = $testchar;
- $string_started = true;
- }
- }
- $char_len = strlen($char);
- }
-
- if ($string_started && ($i != $next_comment_regexp_pos)) {
- // Hand out the correct style information for this string
- $string_key = array_search($char, $this->language_data['QUOTEMARKS']);
- if (!isset($this->language_data['STYLES']['STRINGS'][$string_key]) ||
- !isset($this->language_data['STYLES']['ESCAPE_CHAR'][$string_key])) {
- $string_key = 0;
- }
-
- // parse the stuff before this
- $result .= $this->parse_non_string_part($stuff_to_parse);
- $stuff_to_parse = '';
-
- if (!$this->use_classes) {
- $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS'][$string_key] . '"';
- } else {
- $string_attributes = ' class="st'.$string_key.'"';
- }
-
- // now handle the string
- $string = "<span$string_attributes>" . GeSHi::hsc($char);
- $start = $i + $char_len;
- $string_open = true;
-
- if(empty($this->language_data['ESCAPE_REGEXP'])) {
- $next_escape_regexp_pos = $length;
- }
-
- do {
- //Get the regular ending pos ...
- $close_pos = strpos($part, $char, $start);
- if(false === $close_pos) {
- $close_pos = $length;
- }
-
- if($this->lexic_permissions['ESCAPE_CHAR']) {
- // update escape regexp cache if needed
- if (isset($this->language_data['ESCAPE_REGEXP']) && $next_escape_regexp_pos < $start) {
- $next_escape_regexp_pos = $length;
- foreach ($this->language_data['ESCAPE_REGEXP'] as $escape_key => $regexp) {
- $match_i = false;
- if (isset($escape_regexp_cache_per_key[$escape_key]) &&
- ($escape_regexp_cache_per_key[$escape_key]['pos'] >= $start ||
- $escape_regexp_cache_per_key[$escape_key]['pos'] === false)) {
- // we have already matched something
- if ($escape_regexp_cache_per_key[$escape_key]['pos'] === false) {
- // this comment is never matched
- continue;
- }
- $match_i = $escape_regexp_cache_per_key[$escape_key]['pos'];
- } else if (
- //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible
- (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $start), $match, PREG_OFFSET_CAPTURE)) ||
- (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $start))
- ) {
- $match_i = $match[0][1];
- if (GESHI_PHP_PRE_433) {
- $match_i += $start;
- }
-
- $escape_regexp_cache_per_key[$escape_key] = array(
- 'key' => $escape_key,
- 'length' => strlen($match[0][0]),
- 'pos' => $match_i
- );
- } else {
- $escape_regexp_cache_per_key[$escape_key]['pos'] = false;
- continue;
- }
-
- if ($match_i !== false && $match_i < $next_escape_regexp_pos) {
- $next_escape_regexp_pos = $match_i;
- $next_escape_regexp_key = $escape_key;
- if ($match_i === $start) {
- break;
- }
- }
- }
- }
-
- //Find the next simple escape position
- if('' != $this->language_data['ESCAPE_CHAR']) {
- $simple_escape = strpos($part, $this->language_data['ESCAPE_CHAR'], $start);
- if(false === $simple_escape) {
- $simple_escape = $length;
- }
- } else {
- $simple_escape = $length;
- }
- } else {
- $next_escape_regexp_pos = $length;
- $simple_escape = $length;
- }
-
- if($simple_escape < $next_escape_regexp_pos &&
- $simple_escape < $length &&
- $simple_escape < $close_pos) {
- //The nexxt escape sequence is a simple one ...
- $es_pos = $simple_escape;
-
- //Add the stuff not in the string yet ...
- $string .= $this->hsc(substr($part, $start, $es_pos - $start));
-
- //Get the style for this escaped char ...
- if (!$this->use_classes) {
- $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][0] . '"';
- } else {
- $escape_char_attributes = ' class="es0"';
- }
-
- //Add the style for the escape char ...
- $string .= "<span$escape_char_attributes>" .
- GeSHi::hsc($this->language_data['ESCAPE_CHAR']);
-
- //Get the byte AFTER the ESCAPE_CHAR we just found
- $es_char = $part[$es_pos + 1];
- if ($es_char == "\n") {
- // don't put a newline around newlines
- $string .= "</span>\n";
- $start = $es_pos + 2;
- } else if (ord($es_char) >= 128) {
- //This is an non-ASCII char (UTF8 or single byte)
- //This code tries to work around SF#2037598 ...
- if(function_exists('mb_substr')) {
- $es_char_m = mb_substr(substr($part, $es_pos+1, 16), 0, 1, $this->encoding);
- $string .= $es_char_m . '</span>';
- } else if (!GESHI_PHP_PRE_433 && 'utf-8' == $this->encoding) {
- if(preg_match("/[\xC2-\xDF][\x80-\xBF]".
- "|\xE0[\xA0-\xBF][\x80-\xBF]".
- "|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}".
- "|\xED[\x80-\x9F][\x80-\xBF]".
- "|\xF0[\x90-\xBF][\x80-\xBF]{2}".
- "|[\xF1-\xF3][\x80-\xBF]{3}".
- "|\xF4[\x80-\x8F][\x80-\xBF]{2}/s",
- $part, $es_char_m, null, $es_pos + 1)) {
- $es_char_m = $es_char_m[0];
- } else {
- $es_char_m = $es_char;
- }
- $string .= $this->hsc($es_char_m) . '</span>';
- } else {
- $es_char_m = $this->hsc($es_char);
- }
- $start = $es_pos + strlen($es_char_m) + 1;
- } else {
- $string .= $this->hsc($es_char) . '</span>';
- $start = $es_pos + 2;
- }
- } else if ($next_escape_regexp_pos < $length &&
- $next_escape_regexp_pos < $close_pos) {
- $es_pos = $next_escape_regexp_pos;
- //Add the stuff not in the string yet ...
- $string .= $this->hsc(substr($part, $start, $es_pos - $start));
-
- //Get the key and length of this match ...
- $escape = $escape_regexp_cache_per_key[$next_escape_regexp_key];
- $escape_str = substr($part, $es_pos, $escape['length']);
- $escape_key = $escape['key'];
-
- //Get the style for this escaped char ...
- if (!$this->use_classes) {
- $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][$escape_key] . '"';
- } else {
- $escape_char_attributes = ' class="es' . $escape_key . '"';
- }
-
- //Add the style for the escape char ...
- $string .= "<span$escape_char_attributes>" .
- $this->hsc($escape_str) . '</span>';
-
- $start = $es_pos + $escape['length'];
- } else {
- //Copy the remainder of the string ...
- $string .= $this->hsc(substr($part, $start, $close_pos - $start + $char_len)) . '</span>';
- $start = $close_pos + $char_len;
- $string_open = false;
- }
- } while($string_open);
-
- if ($check_linenumbers) {
- // Are line numbers used? If, we should end the string before
- // the newline and begin it again (so when <li>s are put in the source
- // remains XHTML compliant)
- // note to self: This opens up possibility of config files specifying
- // that languages can/cannot have multiline strings???
- $string = str_replace("\n", "</span>\n<span$string_attributes>", $string);
- }
-
- $result .= $string;
- $string = '';
- $i = $start - 1;
- continue;
- } else if ($this->lexic_permissions['STRINGS'] && $hq && $hq[0] == $char &&
- substr($part, $i, $hq_strlen) == $hq && ($i != $next_comment_regexp_pos)) {
- // The start of a hard quoted string
- if (!$this->use_classes) {
- $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS']['HARD'] . '"';
- $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR']['HARD'] . '"';
- } else {
- $string_attributes = ' class="st_h"';
- $escape_char_attributes = ' class="es_h"';
- }
- // parse the stuff before this
- $result .= $this->parse_non_string_part($stuff_to_parse);
- $stuff_to_parse = '';
-
- // now handle the string
- $string = '';
-
- // look for closing quote
- $start = $i + $hq_strlen;
- while ($close_pos = strpos($part, $this->language_data['HARDQUOTE'][1], $start)) {
- $start = $close_pos + 1;
- if ($this->lexic_permissions['ESCAPE_CHAR'] && $part[$close_pos - 1] == $this->language_data['HARDCHAR'] &&
- (($i + $hq_strlen) != ($close_pos))) { //Support empty string for HQ escapes if Starter = Escape
- // make sure this quote is not escaped
- foreach ($this->language_data['HARDESCAPE'] as $hardescape) {
- if (substr($part, $close_pos - 1, strlen($hardescape)) == $hardescape) {
- // check wether this quote is escaped or if it is something like '\\'
- $escape_char_pos = $close_pos - 1;
- while ($escape_char_pos > 0
- && $part[$escape_char_pos - 1] == $this->language_data['HARDCHAR']) {
- --$escape_char_pos;
- }
- if (($close_pos - $escape_char_pos) & 1) {
- // uneven number of escape chars => this quote is escaped
- continue 2;
- }
- }
- }
- }
-
- // found closing quote
- break;
- }
-
- //Found the closing delimiter?
- if (!$close_pos) {
- // span till the end of this $part when no closing delimiter is found
- $close_pos = $length;
- }
-
- //Get the actual string
- $string = substr($part, $i, $close_pos - $i + 1);
- $i = $close_pos;
-
- // handle escape chars and encode html chars
- // (special because when we have escape chars within our string they may not be escaped)
- if ($this->lexic_permissions['ESCAPE_CHAR'] && $this->language_data['ESCAPE_CHAR']) {
- $start = 0;
- $new_string = '';
- while ($es_pos = strpos($string, $this->language_data['ESCAPE_CHAR'], $start)) {
- // hmtl escape stuff before
- $new_string .= $this->hsc(substr($string, $start, $es_pos - $start));
- // check if this is a hard escape
- foreach ($this->language_data['HARDESCAPE'] as $hardescape) {
- if (substr($string, $es_pos, strlen($hardescape)) == $hardescape) {
- // indeed, this is a hardescape
- $new_string .= "<span$escape_char_attributes>" .
- $this->hsc($hardescape) . '</span>';
- $start = $es_pos + strlen($hardescape);
- continue 2;
- }
- }
- // not a hard escape, but a normal escape
- // they come in pairs of two
- $c = 0;
- while (isset($string[$es_pos + $c]) && isset($string[$es_pos + $c + 1])
- && $string[$es_pos + $c] == $this->language_data['ESCAPE_CHAR']
- && $string[$es_pos + $c + 1] == $this->language_data['ESCAPE_CHAR']) {
- $c += 2;
- }
- if ($c) {
- $new_string .= "<span$escape_char_attributes>" .
- str_repeat($escaped_escape_char, $c) .
- '</span>';
- $start = $es_pos + $c;
- } else {
- // this is just a single lonely escape char...
- $new_string .= $escaped_escape_char;
- $start = $es_pos + 1;
- }
- }
- $string = $new_string . $this->hsc(substr($string, $start));
- } else {
- $string = $this->hsc($string);
- }
-
- if ($check_linenumbers) {
- // Are line numbers used? If, we should end the string before
- // the newline and begin it again (so when <li>s are put in the source
- // remains XHTML compliant)
- // note to self: This opens up possibility of config files specifying
- // that languages can/cannot have multiline strings???
- $string = str_replace("\n", "</span>\n<span$string_attributes>", $string);
- }
-
- $result .= "<span$string_attributes>" . $string . '</span>';
- $string = '';
- continue;
- } else {
- //Have a look for regexp comments
- if ($i == $next_comment_regexp_pos) {
- $COMMENT_MATCHED = true;
- $comment = $comment_regexp_cache_per_key[$next_comment_regexp_key];
- $test_str = $this->hsc(substr($part, $i, $comment['length']));
-
- //@todo If remove important do remove here
- if ($this->lexic_permissions['COMMENTS']['MULTI']) {
- if (!$this->use_classes) {
- $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment['key']] . '"';
- } else {
- $attributes = ' class="co' . $comment['key'] . '"';
- }
-
- $test_str = "<span$attributes>" . $test_str . "</span>";
-
- // Short-cut through all the multiline code
- if ($check_linenumbers) {
- // strreplace to put close span and open span around multiline newlines
- $test_str = str_replace(
- "\n", "</span>\n<span$attributes>",
- str_replace("\n ", "\n&nbsp;", $test_str)
- );
- }
- }
-
- $i += $comment['length'] - 1;
-
- // parse the rest
- $result .= $this->parse_non_string_part($stuff_to_parse);
- $stuff_to_parse = '';
- }
-
- // If we haven't matched a regexp comment, try multi-line comments
- if (!$COMMENT_MATCHED) {
- // Is this a multiline comment?
- if (!empty($this->language_data['COMMENT_MULTI']) && $next_comment_multi_pos < $i) {
- $next_comment_multi_pos = $length;
- foreach ($this->language_data['COMMENT_MULTI'] as $open => $close) {
- $match_i = false;
- if (isset($comment_multi_cache_per_key[$open]) &&
- ($comment_multi_cache_per_key[$open] >= $i ||
- $comment_multi_cache_per_key[$open] === false)) {
- // we have already matched something
- if ($comment_multi_cache_per_key[$open] === false) {
- // this comment is never matched
- continue;
- }
- $match_i = $comment_multi_cache_per_key[$open];
- } else if (($match_i = stripos($part, $open, $i)) !== false) {
- $comment_multi_cache_per_key[$open] = $match_i;
- } else {
- $comment_multi_cache_per_key[$open] = false;
- continue;
- }
- if ($match_i !== false && $match_i < $next_comment_multi_pos) {
- $next_comment_multi_pos = $match_i;
- $next_open_comment_multi = $open;
- if ($match_i === $i) {
- break;
- }
- }
- }
- }
- if ($i == $next_comment_multi_pos) {
- $open = $next_open_comment_multi;
- $close = $this->language_data['COMMENT_MULTI'][$open];
- $open_strlen = strlen($open);
- $close_strlen = strlen($close);
- $COMMENT_MATCHED = true;
- $test_str_match = $open;
- //@todo If remove important do remove here
- if ($this->lexic_permissions['COMMENTS']['MULTI'] ||
- $open == GESHI_START_IMPORTANT) {
- if ($open != GESHI_START_IMPORTANT) {
- if (!$this->use_classes) {
- $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS']['MULTI'] . '"';
- } else {
- $attributes = ' class="coMULTI"';
- }
- $test_str = "<span$attributes>" . $this->hsc($open);
- } else {
- if (!$this->use_classes) {
- $attributes = ' style="' . $this->important_styles . '"';
- } else {
- $attributes = ' class="imp"';
- }
-
- // We don't include the start of the comment if it's an
- // "important" part
- $test_str = "<span$attributes>";
- }
- } else {
- $test_str = $this->hsc($open);
- }
-
- $close_pos = strpos( $part, $close, $i + $open_strlen );
-
- if ($close_pos === false) {
- $close_pos = $length;
- }
-
- // Short-cut through all the multiline code
- $rest_of_comment = $this->hsc(substr($part, $i + $open_strlen, $close_pos - $i - $open_strlen + $close_strlen));
- if (($this->lexic_permissions['COMMENTS']['MULTI'] ||
- $test_str_match == GESHI_START_IMPORTANT) &&
- $check_linenumbers) {
-
- // strreplace to put close span and open span around multiline newlines
- $test_str .= str_replace(
- "\n", "</span>\n<span$attributes>",
- str_replace("\n ", "\n&nbsp;", $rest_of_comment)
- );
- } else {
- $test_str .= $rest_of_comment;
- }
-
- if ($this->lexic_permissions['COMMENTS']['MULTI'] ||
- $test_str_match == GESHI_START_IMPORTANT) {
- $test_str .= '</span>';
- }
-
- $i = $close_pos + $close_strlen - 1;
-
- // parse the rest
- $result .= $this->parse_non_string_part($stuff_to_parse);
- $stuff_to_parse = '';
- }
- }
-
- // If we haven't matched a multiline comment, try single-line comments
- if (!$COMMENT_MATCHED) {
- // cache potential single line comment occurances
- if (!empty($this->language_data['COMMENT_SINGLE']) && $next_comment_single_pos < $i) {
- $next_comment_single_pos = $length;
- foreach ($this->language_data['COMMENT_SINGLE'] as $comment_key => $comment_mark) {
- $match_i = false;
- if (isset($comment_single_cache_per_key[$comment_key]) &&
- ($comment_single_cache_per_key[$comment_key] >= $i ||
- $comment_single_cache_per_key[$comment_key] === false)) {
- // we have already matched something
- if ($comment_single_cache_per_key[$comment_key] === false) {
- // this comment is never matched
- continue;
- }
- $match_i = $comment_single_cache_per_key[$comment_key];
- } else if (
- // case sensitive comments
- ($this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] &&
- ($match_i = stripos($part, $comment_mark, $i)) !== false) ||
- // non case sensitive
- (!$this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] &&
- (($match_i = strpos($part, $comment_mark, $i)) !== false))) {
- $comment_single_cache_per_key[$comment_key] = $match_i;
- } else {
- $comment_single_cache_per_key[$comment_key] = false;
- continue;
- }
- if ($match_i !== false && $match_i < $next_comment_single_pos) {
- $next_comment_single_pos = $match_i;
- $next_comment_single_key = $comment_key;
- if ($match_i === $i) {
- break;
- }
- }
- }
- }
- if ($next_comment_single_pos == $i) {
- $comment_key = $next_comment_single_key;
- $comment_mark = $this->language_data['COMMENT_SINGLE'][$comment_key];
- $com_len = strlen($comment_mark);
-
- // This check will find special variables like $# in bash
- // or compiler directives of Delphi beginning {$
- if ((empty($sc_disallowed_before) || ($i == 0) ||
- (false === strpos($sc_disallowed_before, $part[$i-1]))) &&
- (empty($sc_disallowed_after) || ($length <= $i + $com_len) ||
- (false === strpos($sc_disallowed_after, $part[$i + $com_len]))))
- {
- // this is a valid comment
- $COMMENT_MATCHED = true;
- if ($this->lexic_permissions['COMMENTS'][$comment_key]) {
- if (!$this->use_classes) {
- $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment_key] . '"';
- } else {
- $attributes = ' class="co' . $comment_key . '"';
- }
- $test_str = "<span$attributes>" . $this->hsc($this->change_case($comment_mark));
- } else {
- $test_str = $this->hsc($comment_mark);
- }
-
- //Check if this comment is the last in the source
- $close_pos = strpos($part, "\n", $i);
- $oops = false;
- if ($close_pos === false) {
- $close_pos = $length;
- $oops = true;
- }
- $test_str .= $this->hsc(substr($part, $i + $com_len, $close_pos - $i - $com_len));
- if ($this->lexic_permissions['COMMENTS'][$comment_key]) {
- $test_str .= "</span>";
- }
-
- // Take into account that the comment might be the last in the source
- if (!$oops) {
- $test_str .= "\n";
- }
-
- $i = $close_pos;
-
- // parse the rest
- $result .= $this->parse_non_string_part($stuff_to_parse);
- $stuff_to_parse = '';
- }
- }
- }
- }
-
- // Where are we adding this char?
- if (!$COMMENT_MATCHED) {
- $stuff_to_parse .= $char;
- } else {
- $result .= $test_str;
- unset($test_str);
- $COMMENT_MATCHED = false;
- }
- }
- // Parse the last bit
- $result .= $this->parse_non_string_part($stuff_to_parse);
- $stuff_to_parse = '';
- } else {
- $result .= $this->hsc($part);
- }
- // Close the <span> that surrounds the block
- if ($STRICTATTRS != '') {
- $result = str_replace("\n", "</span>\n<span$STRICTATTRS>", $result);
- $result .= '</span>';
- }
-
- $endresult .= $result;
- unset($part, $parts[$key], $result);
- }
-
- //This fix is related to SF#1923020, but has to be applied regardless of
- //actually highlighting symbols.
- /** NOTE: memorypeak #3 */
- $endresult = str_replace(array('<SEMI>', '<PIPE>'), array(';', '|'), $endresult);
-
-// // Parse the last stuff (redundant?)
-// $result .= $this->parse_non_string_part($stuff_to_parse);
-
- // Lop off the very first and last spaces
-// $result = substr($result, 1, -1);
-
- // We're finished: stop timing
- $this->set_time($start_time, microtime());
-
- $this->finalise($endresult);
- return $endresult;
- }
-
- /**
- * Swaps out spaces and tabs for HTML indentation. Not needed if
- * the code is in a pre block...
- *
- * @param string The source to indent (reference!)
- * @since 1.0.0
- * @access private
- */
- function indent(&$result) {
- /// Replace tabs with the correct number of spaces
- if (false !== strpos($result, "\t")) {
- $lines = explode("\n", $result);
- $result = null;//Save memory while we process the lines individually
- $tab_width = $this->get_real_tab_width();
- $tab_string = '&nbsp;' . str_repeat(' ', $tab_width);
-
- for ($key = 0, $n = count($lines); $key < $n; $key++) {
- $line = $lines[$key];
- if (false === strpos($line, "\t")) {
- continue;
- }
-
- $pos = 0;
- $length = strlen($line);
- $lines[$key] = ''; // reduce memory
-
- $IN_TAG = false;
- for ($i = 0; $i < $length; ++$i) {
- $char = $line[$i];
- // Simple engine to work out whether we're in a tag.
- // If we are we modify $pos. This is so we ignore HTML
- // in the line and only workout the tab replacement
- // via the actual content of the string
- // This test could be improved to include strings in the
- // html so that < or > would be allowed in user's styles
- // (e.g. quotes: '<' '>'; or similar)
- if ($IN_TAG) {
- if ('>' == $char) {
- $IN_TAG = false;
- }
- $lines[$key] .= $char;
- } else if ('<' == $char) {
- $IN_TAG = true;
- $lines[$key] .= '<';
- } else if ('&' == $char) {
- $substr = substr($line, $i + 3, 5);
- $posi = strpos($substr, ';');
- if (false === $posi) {
- ++$pos;
- } else {
- $pos -= $posi+2;
- }
- $lines[$key] .= $char;
- } else if ("\t" == $char) {
- $str = '';
- // OPTIMISE - move $strs out. Make an array:
- // $tabs = array(
- // 1 => '&nbsp;',
- // 2 => '&nbsp; ',
- // 3 => '&nbsp; &nbsp;' etc etc
- // to use instead of building a string every time
- $tab_end_width = $tab_width - ($pos % $tab_width); //Moved out of the look as it doesn't change within the loop
- if (($pos & 1) || 1 == $tab_end_width) {
- $str .= substr($tab_string, 6, $tab_end_width);
- } else {
- $str .= substr($tab_string, 0, $tab_end_width+5);
- }
- $lines[$key] .= $str;
- $pos += $tab_end_width;
-
- if (false === strpos($line, "\t", $i + 1)) {
- $lines[$key] .= substr($line, $i + 1);
- break;
- }
- } else if (0 == $pos && ' ' == $char) {
- $lines[$key] .= '&nbsp;';
- ++$pos;
- } else {
- $lines[$key] .= $char;
- ++$pos;
- }
- }
- }
- $result = implode("\n", $lines);
- unset($lines);//We don't need the lines separated beyond this --- free them!
- }
- // Other whitespace
- // BenBE: Fix to reduce the number of replacements to be done
- $result = preg_replace('/^ /m', '&nbsp;', $result);
- $result = str_replace(' ', ' &nbsp;', $result);
-
- if ($this->line_numbers == GESHI_NO_LINE_NUMBERS && $this->header_type != GESHI_HEADER_PRE_TABLE) {
- if ($this->line_ending === null) {
- $result = nl2br($result);
- } else {
- $result = str_replace("\n", $this->line_ending, $result);
- }
- }
- }
-
- /**
- * Changes the case of a keyword for those languages where a change is asked for
- *
- * @param string The keyword to change the case of
- * @return string The keyword with its case changed
- * @since 1.0.0
- * @access private
- */
- function change_case($instr) {
- switch ($this->language_data['CASE_KEYWORDS']) {
- case GESHI_CAPS_UPPER:
- return strtoupper($instr);
- case GESHI_CAPS_LOWER:
- return strtolower($instr);
- default:
- return $instr;
- }
- }
-
- /**
- * Handles replacements of keywords to include markup and links if requested
- *
- * @param string The keyword to add the Markup to
- * @return The HTML for the match found
- * @since 1.0.8
- * @access private
- *
- * @todo Get rid of ender in keyword links
- */
- function handle_keyword_replace($match) {
- $k = $this->_kw_replace_group;
- $keyword = $match[0];
-
- $before = '';
- $after = '';
-
- if ($this->keyword_links) {
- // Keyword links have been ebabled
-
- if (isset($this->language_data['URLS'][$k]) &&
- $this->language_data['URLS'][$k] != '') {
- // There is a base group for this keyword
-
- // Old system: strtolower
- //$keyword = ( $this->language_data['CASE_SENSITIVE'][$group] ) ? $keyword : strtolower($keyword);
- // New system: get keyword from language file to get correct case
- if (!$this->language_data['CASE_SENSITIVE'][$k] &&
- strpos($this->language_data['URLS'][$k], '{FNAME}') !== false) {
- foreach ($this->language_data['KEYWORDS'][$k] as $word) {
- if (strcasecmp($word, $keyword) == 0) {
- break;
- }
- }
- } else {
- $word = $keyword;
- }
-
- $before = '<|UR1|"' .
- str_replace(
- array(
- '{FNAME}',
- '{FNAMEL}',
- '{FNAMEU}',
- '.'),
- array(
- str_replace('+', '%20', urlencode($this->hsc($word))),
- str_replace('+', '%20', urlencode($this->hsc(strtolower($word)))),
- str_replace('+', '%20', urlencode($this->hsc(strtoupper($word)))),
- '<DOT>'),
- $this->language_data['URLS'][$k]
- ) . '">';
- $after = '</a>';
- }
- }
-
- return $before . '<|/'. $k .'/>' . $this->change_case($keyword) . '|>' . $after;
- }
-
- /**
- * handles regular expressions highlighting-definitions with callback functions
- *
- * @note this is a callback, don't use it directly
- *
- * @param array the matches array
- * @return The highlighted string
- * @since 1.0.8
- * @access private
- */
- function handle_regexps_callback($matches) {
- // before: "' style=\"' . call_user_func(\"$func\", '\\1') . '\"\\1|>'",
- return ' style="' . call_user_func($this->language_data['STYLES']['REGEXPS'][$this->_rx_key], $matches[1]) . '"'. $matches[1] . '|>';
- }
-
- /**
- * handles newlines in REGEXPS matches. Set the _hmr_* vars before calling this
- *
- * @note this is a callback, don't use it directly
- *
- * @param array the matches array
- * @return string
- * @since 1.0.8
- * @access private
- */
- function handle_multiline_regexps($matches) {
- $before = $this->_hmr_before;
- $after = $this->_hmr_after;
- if ($this->_hmr_replace) {
- $replace = $this->_hmr_replace;
- $search = array();
-
- foreach (array_keys($matches) as $k) {
- $search[] = '\\' . $k;
- }
-
- $before = str_replace($search, $matches, $before);
- $after = str_replace($search, $matches, $after);
- $replace = str_replace($search, $matches, $replace);
- } else {
- $replace = $matches[0];
- }
- return $before
- . '<|!REG3XP' . $this->_hmr_key .'!>'
- . str_replace("\n", "|>\n<|!REG3XP" . $this->_hmr_key . '!>', $replace)
- . '|>'
- . $after;
- }
-
- /**
- * Takes a string that has no strings or comments in it, and highlights
- * stuff like keywords, numbers and methods.
- *
- * @param string The string to parse for keyword, numbers etc.
- * @since 1.0.0
- * @access private
- * @todo BUGGY! Why? Why not build string and return?
- */
- function parse_non_string_part($stuff_to_parse) {
- $stuff_to_parse = ' ' . $this->hsc($stuff_to_parse);
-
- // Highlight keywords
- $disallowed_before = "(?<![a-zA-Z0-9\$_\|\#;>|^&";
- $disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;";
- if ($this->lexic_permissions['STRINGS']) {
- $quotemarks = preg_quote(implode($this->language_data['QUOTEMARKS']), '/');
- $disallowed_before .= $quotemarks;
- $disallowed_after .= $quotemarks;
- }
- $disallowed_before .= "])";
- $disallowed_after .= "])";
-
- $parser_control_pergroup = false;
- if (isset($this->language_data['PARSER_CONTROL'])) {
- if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
- $x = 0; // check wether per-keyword-group parser_control is enabled
- if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
- $disallowed_before = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
- ++$x;
- }
- if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
- $disallowed_after = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
- ++$x;
- }
- $parser_control_pergroup = (count($this->language_data['PARSER_CONTROL']['KEYWORDS']) - $x) > 0;
- }
- }
-
- foreach (array_keys($this->language_data['KEYWORDS']) as $k) {
- if (!isset($this->lexic_permissions['KEYWORDS'][$k]) ||
- $this->lexic_permissions['KEYWORDS'][$k]) {
-
- $case_sensitive = $this->language_data['CASE_SENSITIVE'][$k];
- $modifiers = $case_sensitive ? '' : 'i';
-
- // NEW in 1.0.8 - per-keyword-group parser control
- $disallowed_before_local = $disallowed_before;
- $disallowed_after_local = $disallowed_after;
- if ($parser_control_pergroup && isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k])) {
- if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'])) {
- $disallowed_before_local =
- $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'];
- }
-
- if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'])) {
- $disallowed_after_local =
- $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'];
- }
- }
-
- $this->_kw_replace_group = $k;
-
- //NEW in 1.0.8, the cached regexp list
- // since we don't want PHP / PCRE to crash due to too large patterns we split them into smaller chunks
- for ($set = 0, $set_length = count($this->language_data['CACHED_KEYWORD_LISTS'][$k]); $set < $set_length; ++$set) {
- $keywordset =& $this->language_data['CACHED_KEYWORD_LISTS'][$k][$set];
- // Might make a more unique string for putting the number in soon
- // Basically, we don't put the styles in yet because then the styles themselves will
- // get highlighted if the language has a CSS keyword in it (like CSS, for example ;))
- $stuff_to_parse = preg_replace_callback(
- "/$disallowed_before_local({$keywordset})(?!\<DOT\>(?:htm|php))$disallowed_after_local/$modifiers",
- array($this, 'handle_keyword_replace'),
- $stuff_to_parse
- );
- }
- }
- }
-
- // Regular expressions
- foreach ($this->language_data['REGEXPS'] as $key => $regexp) {
- if ($this->lexic_permissions['REGEXPS'][$key]) {
- if (is_array($regexp)) {
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- // produce valid HTML when we match multiple lines
- $this->_hmr_replace = $regexp[GESHI_REPLACE];
- $this->_hmr_before = $regexp[GESHI_BEFORE];
- $this->_hmr_key = $key;
- $this->_hmr_after = $regexp[GESHI_AFTER];
- $stuff_to_parse = preg_replace_callback(
- "/" . $regexp[GESHI_SEARCH] . "/{$regexp[GESHI_MODIFIERS]}",
- array($this, 'handle_multiline_regexps'),
- $stuff_to_parse);
- $this->_hmr_replace = false;
- $this->_hmr_before = '';
- $this->_hmr_after = '';
- } else {
- $stuff_to_parse = preg_replace(
- '/' . $regexp[GESHI_SEARCH] . '/' . $regexp[GESHI_MODIFIERS],
- $regexp[GESHI_BEFORE] . '<|!REG3XP'. $key .'!>' . $regexp[GESHI_REPLACE] . '|>' . $regexp[GESHI_AFTER],
- $stuff_to_parse);
- }
- } else {
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- // produce valid HTML when we match multiple lines
- $this->_hmr_key = $key;
- $stuff_to_parse = preg_replace_callback( "/(" . $regexp . ")/",
- array($this, 'handle_multiline_regexps'), $stuff_to_parse);
- $this->_hmr_key = '';
- } else {
- $stuff_to_parse = preg_replace( "/(" . $regexp . ")/", "<|!REG3XP$key!>\\1|>", $stuff_to_parse);
- }
- }
- }
- }
-
- // Highlight numbers. As of 1.0.8 we support different types of numbers
- $numbers_found = false;
-
- if ($this->lexic_permissions['NUMBERS'] && preg_match($this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'], $stuff_to_parse )) {
- $numbers_found = true;
-
- //For each of the formats ...
- foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
- //Check if it should be highlighted ...
- $stuff_to_parse = preg_replace($regexp, "<|/NUM!$id/>\\1|>", $stuff_to_parse);
- }
- }
-
- //
- // Now that's all done, replace /[number]/ with the correct styles
- //
- foreach (array_keys($this->language_data['KEYWORDS']) as $k) {
- if (!$this->use_classes) {
- $attributes = ' style="' .
- (isset($this->language_data['STYLES']['KEYWORDS'][$k]) ?
- $this->language_data['STYLES']['KEYWORDS'][$k] : "") . '"';
- } else {
- $attributes = ' class="kw' . $k . '"';
- }
- $stuff_to_parse = str_replace("<|/$k/>", "<|$attributes>", $stuff_to_parse);
- }
-
- if ($numbers_found) {
- // Put number styles in
- foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
- //Commented out for now, as this needs some review ...
- // if ($numbers_permissions & $id) {
- //Get the appropriate style ...
- //Checking for unset styles is done by the style cache builder ...
- if (!$this->use_classes) {
- $attributes = ' style="' . $this->language_data['STYLES']['NUMBERS'][$id] . '"';
- } else {
- $attributes = ' class="nu'.$id.'"';
- }
-
- //Set in the correct styles ...
- $stuff_to_parse = str_replace("/NUM!$id/", $attributes, $stuff_to_parse);
- // }
- }
- }
-
- // Highlight methods and fields in objects
- if ($this->lexic_permissions['METHODS'] && $this->language_data['OOLANG']) {
- $oolang_spaces = "[\s]*";
- $oolang_before = "";
- $oolang_after = "[a-zA-Z][a-zA-Z0-9_]*";
- if (isset($this->language_data['PARSER_CONTROL'])) {
- if (isset($this->language_data['PARSER_CONTROL']['OOLANG'])) {
- if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_BEFORE'])) {
- $oolang_before = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_BEFORE'];
- }
- if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_AFTER'])) {
- $oolang_after = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_AFTER'];
- }
- if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_SPACES'])) {
- $oolang_spaces = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_SPACES'];
- }
- }
- }
-
- foreach ($this->language_data['OBJECT_SPLITTERS'] as $key => $splitter) {
- if (false !== strpos($stuff_to_parse, $splitter)) {
- if (!$this->use_classes) {
- $attributes = ' style="' . $this->language_data['STYLES']['METHODS'][$key] . '"';
- } else {
- $attributes = ' class="me' . $key . '"';
- }
- $stuff_to_parse = preg_replace("/($oolang_before)(" . preg_quote($this->language_data['OBJECT_SPLITTERS'][$key], '/') . ")($oolang_spaces)($oolang_after)/", "\\1\\2\\3<|$attributes>\\4|>", $stuff_to_parse);
- }
- }
- }
-
- //
- // Highlight brackets. Yes, I've tried adding a semi-colon to this list.
- // You try it, and see what happens ;)
- // TODO: Fix lexic permissions not converting entities if shouldn't
- // be highlighting regardless
- //
- if ($this->lexic_permissions['BRACKETS']) {
- $stuff_to_parse = str_replace( $this->language_data['CACHE_BRACKET_MATCH'],
- $this->language_data['CACHE_BRACKET_REPLACE'], $stuff_to_parse );
- }
-
-
- //FIX for symbol highlighting ...
- if ($this->lexic_permissions['SYMBOLS'] && !empty($this->language_data['SYMBOLS'])) {
- //Get all matches and throw away those witin a block that is already highlighted... (i.e. matched by a regexp)
- $n_symbols = preg_match_all("/<\|(?:<DOT>|[^>])+>(?:(?!\|>).*?)\|>|<\/a>|(?:" . $this->language_data['SYMBOL_SEARCH'] . ")+(?![^<]+?>)/", $stuff_to_parse, $pot_symbols, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
- $global_offset = 0;
- for ($s_id = 0; $s_id < $n_symbols; ++$s_id) {
- $symbol_match = $pot_symbols[$s_id][0][0];
- if (strpos($symbol_match, '<') !== false || strpos($symbol_match, '>') !== false) {
- // already highlighted blocks _must_ include either < or >
- // so if this conditional applies, we have to skip this match
- // BenBE: UNLESS the block contains <SEMI> or <PIPE>
- if(strpos($symbol_match, '<SEMI>') === false &&
- strpos($symbol_match, '<PIPE>') === false) {
- continue;
- }
- }
-
- // if we reach this point, we have a valid match which needs to be highlighted
-
- $symbol_length = strlen($symbol_match);
- $symbol_offset = $pot_symbols[$s_id][0][1];
- unset($pot_symbols[$s_id]);
- $symbol_end = $symbol_length + $symbol_offset;
- $symbol_hl = "";
-
- // if we have multiple styles, we have to handle them properly
- if ($this->language_data['MULTIPLE_SYMBOL_GROUPS']) {
- $old_sym = -1;
- // Split the current stuff to replace into its atomic symbols ...
- preg_match_all("/" . $this->language_data['SYMBOL_SEARCH'] . "/", $symbol_match, $sym_match_syms, PREG_PATTERN_ORDER);
- foreach ($sym_match_syms[0] as $sym_ms) {
- //Check if consequtive symbols belong to the same group to save output ...
- if (isset($this->language_data['SYMBOL_DATA'][$sym_ms])
- && ($this->language_data['SYMBOL_DATA'][$sym_ms] != $old_sym)) {
- if (-1 != $old_sym) {
- $symbol_hl .= "|>";
- }
- $old_sym = $this->language_data['SYMBOL_DATA'][$sym_ms];
- if (!$this->use_classes) {
- $symbol_hl .= '<| style="' . $this->language_data['STYLES']['SYMBOLS'][$old_sym] . '">';
- } else {
- $symbol_hl .= '<| class="sy' . $old_sym . '">';
- }
- }
- $symbol_hl .= $sym_ms;
- }
- unset($sym_match_syms);
-
- //Close remaining tags and insert the replacement at the right position ...
- //Take caution if symbol_hl is empty to avoid doubled closing spans.
- if (-1 != $old_sym) {
- $symbol_hl .= "|>";
- }
- } else {
- if (!$this->use_classes) {
- $symbol_hl = '<| style="' . $this->language_data['STYLES']['SYMBOLS'][0] . '">';
- } else {
- $symbol_hl = '<| class="sy0">';
- }
- $symbol_hl .= $symbol_match . '|>';
- }
-
- $stuff_to_parse = substr_replace($stuff_to_parse, $symbol_hl, $symbol_offset + $global_offset, $symbol_length);
-
- // since we replace old text with something of different size,
- // we'll have to keep track of the differences
- $global_offset += strlen($symbol_hl) - $symbol_length;
- }
- }
- //FIX for symbol highlighting ...
-
- // Add class/style for regexps
- foreach (array_keys($this->language_data['REGEXPS']) as $key) {
- if ($this->lexic_permissions['REGEXPS'][$key]) {
- if (is_callable($this->language_data['STYLES']['REGEXPS'][$key])) {
- $this->_rx_key = $key;
- $stuff_to_parse = preg_replace_callback("/!REG3XP$key!(.*)\|>/U",
- array($this, 'handle_regexps_callback'),
- $stuff_to_parse);
- } else {
- if (!$this->use_classes) {
- $attributes = ' style="' . $this->language_data['STYLES']['REGEXPS'][$key] . '"';
- } else {
- if (is_array($this->language_data['REGEXPS'][$key]) &&
- array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$key])) {
- $attributes = ' class="' .
- $this->language_data['REGEXPS'][$key][GESHI_CLASS] . '"';
- } else {
- $attributes = ' class="re' . $key . '"';
- }
- }
- $stuff_to_parse = str_replace("!REG3XP$key!", "$attributes", $stuff_to_parse);
- }
- }
- }
-
- // Replace <DOT> with . for urls
- $stuff_to_parse = str_replace('<DOT>', '.', $stuff_to_parse);
- // Replace <|UR1| with <a href= for urls also
- if (isset($this->link_styles[GESHI_LINK])) {
- if ($this->use_classes) {
- $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' href=', $stuff_to_parse);
- } else {
- $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' style="' . $this->link_styles[GESHI_LINK] . '" href=', $stuff_to_parse);
- }
- } else {
- $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' href=', $stuff_to_parse);
- }
-
- //
- // NOW we add the span thingy ;)
- //
-
- $stuff_to_parse = str_replace('<|', '<span', $stuff_to_parse);
- $stuff_to_parse = str_replace ( '|>', '</span>', $stuff_to_parse );
- return substr($stuff_to_parse, 1);
- }
-
- /**
- * Sets the time taken to parse the code
- *
- * @param microtime The time when parsing started
- * @param microtime The time when parsing ended
- * @since 1.0.2
- * @access private
- */
- function set_time($start_time, $end_time) {
- $start = explode(' ', $start_time);
- $end = explode(' ', $end_time);
- $this->time = $end[0] + $end[1] - $start[0] - $start[1];
- }
-
- /**
- * Gets the time taken to parse the code
- *
- * @return double The time taken to parse the code
- * @since 1.0.2
- */
- function get_time() {
- return $this->time;
- }
-
- /**
- * Merges arrays recursively, overwriting values of the first array with values of later arrays
- *
- * @since 1.0.8
- * @access private
- */
- function merge_arrays() {
- $arrays = func_get_args();
- $narrays = count($arrays);
-
- // check arguments
- // comment out if more performance is necessary (in this case the foreach loop will trigger a warning if the argument is not an array)
- for ($i = 0; $i < $narrays; $i ++) {
- if (!is_array($arrays[$i])) {
- // also array_merge_recursive returns nothing in this case
- trigger_error('Argument #' . ($i+1) . ' is not an array - trying to merge array with scalar! Returning false!', E_USER_WARNING);
- return false;
- }
- }
-
- // the first array is in the output set in every case
- $ret = $arrays[0];
-
- // merege $ret with the remaining arrays
- for ($i = 1; $i < $narrays; $i ++) {
- foreach ($arrays[$i] as $key => $value) {
- if (is_array($value) && isset($ret[$key])) {
- // if $ret[$key] is not an array you try to merge an scalar value with an array - the result is not defined (incompatible arrays)
- // in this case the call will trigger an E_USER_WARNING and the $ret[$key] will be false.
- $ret[$key] = $this->merge_arrays($ret[$key], $value);
- } else {
- $ret[$key] = $value;
- }
- }
- }
-
- return $ret;
- }
-
- /**
- * Gets language information and stores it for later use
- *
- * @param string The filename of the language file you want to load
- * @since 1.0.0
- * @access private
- * @todo Needs to load keys for lexic permissions for keywords, regexps etc
- */
- function load_language($file_name) {
- if ($file_name == $this->loaded_language) {
- // this file is already loaded!
- return;
- }
-
- //Prepare some stuff before actually loading the language file
- $this->loaded_language = $file_name;
- $this->parse_cache_built = false;
- $this->enable_highlighting();
- $language_data = array();
-
- //Load the language file
- require $file_name;
-
- // Perhaps some checking might be added here later to check that
- // $language data is a valid thing but maybe not
- $this->language_data = $language_data;
-
- // Set strict mode if should be set
- $this->strict_mode = $this->language_data['STRICT_MODE_APPLIES'];
-
- // Set permissions for all lexics to true
- // so they'll be highlighted by default
- foreach (array_keys($this->language_data['KEYWORDS']) as $key) {
- if (!empty($this->language_data['KEYWORDS'][$key])) {
- $this->lexic_permissions['KEYWORDS'][$key] = true;
- } else {
- $this->lexic_permissions['KEYWORDS'][$key] = false;
- }
- }
-
- foreach (array_keys($this->language_data['COMMENT_SINGLE']) as $key) {
- $this->lexic_permissions['COMMENTS'][$key] = true;
- }
- foreach (array_keys($this->language_data['REGEXPS']) as $key) {
- $this->lexic_permissions['REGEXPS'][$key] = true;
- }
-
- // for BenBE and future code reviews:
- // we can use empty here since we only check for existance and emptiness of an array
- // if it is not an array at all but rather false or null this will work as intended as well
- // even if $this->language_data['PARSER_CONTROL'] is undefined this won't trigger a notice
- if (!empty($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS'])) {
- foreach ($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS'] as $flag => $value) {
- // it's either true or false and maybe is true as well
- $perm = $value !== GESHI_NEVER;
- if ($flag == 'ALL') {
- $this->enable_highlighting($perm);
- continue;
- }
- if (!isset($this->lexic_permissions[$flag])) {
- // unknown lexic permission
- continue;
- }
- if (is_array($this->lexic_permissions[$flag])) {
- foreach ($this->lexic_permissions[$flag] as $key => $val) {
- $this->lexic_permissions[$flag][$key] = $perm;
- }
- } else {
- $this->lexic_permissions[$flag] = $perm;
- }
- }
- unset($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS']);
- }
-
- //Fix: Problem where hardescapes weren't handled if no ESCAPE_CHAR was given
- //You need to set one for HARDESCAPES only in this case.
- if(!isset($this->language_data['HARDCHAR'])) {
- $this->language_data['HARDCHAR'] = $this->language_data['ESCAPE_CHAR'];
- }
-
- //NEW in 1.0.8: Allow styles to be loaded from a separate file to override defaults
- $style_filename = substr($file_name, 0, -4) . '.style.php';
- if (is_readable($style_filename)) {
- //Clear any style_data that could have been set before ...
- if (isset($style_data)) {
- unset($style_data);
- }
-
- //Read the Style Information from the style file
- include $style_filename;
-
- //Apply the new styles to our current language styles
- if (isset($style_data) && is_array($style_data)) {
- $this->language_data['STYLES'] =
- $this->merge_arrays($this->language_data['STYLES'], $style_data);
- }
- }
- }
-
- /**
- * Takes the parsed code and various options, and creates the HTML
- * surrounding it to make it look nice.
- *
- * @param string The code already parsed (reference!)
- * @since 1.0.0
- * @access private
- */
- function finalise(&$parsed_code) {
- // Remove end parts of important declarations
- // This is BUGGY!! My fault for bad code: fix coming in 1.2
- // @todo Remove this crap
- if ($this->enable_important_blocks &&
- (strpos($parsed_code, $this->hsc(GESHI_START_IMPORTANT)) === false)) {
- $parsed_code = str_replace($this->hsc(GESHI_END_IMPORTANT), '', $parsed_code);
- }
-
- // Add HTML whitespace stuff if we're using the <div> header
- if ($this->header_type != GESHI_HEADER_PRE && $this->header_type != GESHI_HEADER_PRE_VALID) {
- $this->indent($parsed_code);
- }
-
- // purge some unnecessary stuff
- /** NOTE: memorypeak #1 */
- $parsed_code = preg_replace('#<span[^>]+>(\s*)</span>#', '\\1', $parsed_code);
-
- // If we are using IDs for line numbers, there needs to be an overall
- // ID set to prevent collisions.
- if ($this->add_ids && !$this->overall_id) {
- $this->overall_id = 'geshi-' . substr(md5(microtime()), 0, 4);
- }
-
- // Get code into lines
- /** NOTE: memorypeak #2 */
- $code = explode("\n", $parsed_code);
- $parsed_code = $this->header();
-
- // If we're using line numbers, we insert <li>s and appropriate
- // markup to style them (otherwise we don't need to do anything)
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS && $this->header_type != GESHI_HEADER_PRE_TABLE) {
- // If we're using the <pre> header, we shouldn't add newlines because
- // the <pre> will line-break them (and the <li>s already do this for us)
- $ls = ($this->header_type != GESHI_HEADER_PRE && $this->header_type != GESHI_HEADER_PRE_VALID) ? "\n" : '';
-
- // Set vars to defaults for following loop
- $i = 0;
-
- // Foreach line...
- for ($i = 0, $n = count($code); $i < $n;) {
- //Reset the attributes for a new line ...
- $attrs = array();
-
- // Make lines have at least one space in them if they're empty
- // BenBE: Checking emptiness using trim instead of relying on blanks
- if ('' == trim($code[$i])) {
- $code[$i] = '&nbsp;';
- }
-
- // If this is a "special line"...
- if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
- $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
- // Set the attributes to style the line
- if ($this->use_classes) {
- //$attr = ' class="li2"';
- $attrs['class'][] = 'li2';
- $def_attr = ' class="de2"';
- } else {
- //$attr = ' style="' . $this->line_style2 . '"';
- $attrs['style'][] = $this->line_style2;
- // This style "covers up" the special styles set for special lines
- // so that styles applied to special lines don't apply to the actual
- // code on that line
- $def_attr = ' style="' . $this->code_style . '"';
- }
- } else {
- if ($this->use_classes) {
- //$attr = ' class="li1"';
- $attrs['class'][] = 'li1';
- $def_attr = ' class="de1"';
- } else {
- //$attr = ' style="' . $this->line_style1 . '"';
- $attrs['style'][] = $this->line_style1;
- $def_attr = ' style="' . $this->code_style . '"';
- }
- }
-
- //Check which type of tag to insert for this line
- if ($this->header_type == GESHI_HEADER_PRE_VALID) {
- $start = "<pre$def_attr>";
- $end = '</pre>';
- } else {
- // Span or div?
- $start = "<div$def_attr>";
- $end = '</div>';
- }
-
- ++$i;
-
- // Are we supposed to use ids? If so, add them
- if ($this->add_ids) {
- $attrs['id'][] = "$this->overall_id-$i";
- }
-
- //Is this some line with extra styles???
- if (in_array($i, $this->highlight_extra_lines)) {
- if ($this->use_classes) {
- if (isset($this->highlight_extra_lines_styles[$i])) {
- $attrs['class'][] = "lx$i";
- } else {
- $attrs['class'][] = "ln-xtra";
- }
- } else {
- array_push($attrs['style'], $this->get_line_style($i));
- }
- }
-
- // Add in the line surrounded by appropriate list HTML
- $attr_string = '';
- foreach ($attrs as $key => $attr) {
- $attr_string .= ' ' . $key . '="' . implode(' ', $attr) . '"';
- }
-
- $parsed_code .= "<li$attr_string>$start{$code[$i-1]}$end</li>$ls";
- unset($code[$i - 1]);
- }
- } else {
- $n = count($code);
- if ($this->use_classes) {
- $attributes = ' class="de1"';
- } else {
- $attributes = ' style="'. $this->code_style .'"';
- }
- if ($this->header_type == GESHI_HEADER_PRE_VALID) {
- $parsed_code .= '<pre'. $attributes .'>';
- } elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) {
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- if ($this->use_classes) {
- $attrs = ' class="ln"';
- } else {
- $attrs = ' style="'. $this->table_linenumber_style .'"';
- }
- $parsed_code .= '<td'.$attrs.'><pre'.$attributes.'>';
- // get linenumbers
- // we don't merge it with the for below, since it should be better for
- // memory consumption this way
- // @todo: but... actually it would still be somewhat nice to merge the two loops
- // the mem peaks are at different positions
- for ($i = 0; $i < $n; ++$i) {
- $close = 0;
- // fancy lines
- if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
- $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
- // Set the attributes to style the line
- if ($this->use_classes) {
- $parsed_code .= '<span class="xtra li2"><span class="de2">';
- } else {
- // This style "covers up" the special styles set for special lines
- // so that styles applied to special lines don't apply to the actual
- // code on that line
- $parsed_code .= '<span style="display:block;' . $this->line_style2 . '">'
- .'<span style="' . $this->code_style .'">';
- }
- $close += 2;
- }
- //Is this some line with extra styles???
- if (in_array($i + 1, $this->highlight_extra_lines)) {
- if ($this->use_classes) {
- if (isset($this->highlight_extra_lines_styles[$i])) {
- $parsed_code .= "<span class=\"xtra lx$i\">";
- } else {
- $parsed_code .= "<span class=\"xtra ln-xtra\">";
- }
- } else {
- $parsed_code .= "<span style=\"display:block;" . $this->get_line_style($i) . "\">";
- }
- ++$close;
- }
- $parsed_code .= $this->line_numbers_start + $i;
- if ($close) {
- $parsed_code .= str_repeat('</span>', $close);
- } else if ($i != $n) {
- $parsed_code .= "\n";
- }
- }
- $parsed_code .= '</pre></td><td'.$attributes.'>';
- }
- $parsed_code .= '<pre'. $attributes .'>';
- }
- // No line numbers, but still need to handle highlighting lines extra.
- // Have to use divs so the full width of the code is highlighted
- $close = 0;
- for ($i = 0; $i < $n; ++$i) {
- // Make lines have at least one space in them if they're empty
- // BenBE: Checking emptiness using trim instead of relying on blanks
- if ('' == trim($code[$i])) {
- $code[$i] = '&nbsp;';
- }
- // fancy lines
- if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
- $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
- // Set the attributes to style the line
- if ($this->use_classes) {
- $parsed_code .= '<span class="xtra li2"><span class="de2">';
- } else {
- // This style "covers up" the special styles set for special lines
- // so that styles applied to special lines don't apply to the actual
- // code on that line
- $parsed_code .= '<span style="display:block;' . $this->line_style2 . '">'
- .'<span style="' . $this->code_style .'">';
- }
- $close += 2;
- }
- //Is this some line with extra styles???
- if (in_array($i + 1, $this->highlight_extra_lines)) {
- if ($this->use_classes) {
- if (isset($this->highlight_extra_lines_styles[$i])) {
- $parsed_code .= "<span class=\"xtra lx$i\">";
- } else {
- $parsed_code .= "<span class=\"xtra ln-xtra\">";
- }
- } else {
- $parsed_code .= "<span style=\"display:block;" . $this->get_line_style($i) . "\">";
- }
- ++$close;
- }
-
- $parsed_code .= $code[$i];
-
- if ($close) {
- $parsed_code .= str_repeat('</span>', $close);
- $close = 0;
- }
- elseif ($i + 1 < $n) {
- $parsed_code .= "\n";
- }
- unset($code[$i]);
- }
-
- if ($this->header_type == GESHI_HEADER_PRE_VALID || $this->header_type == GESHI_HEADER_PRE_TABLE) {
- $parsed_code .= '</pre>';
- }
- if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- $parsed_code .= '</td>';
- }
- }
-
- $parsed_code .= $this->footer();
- }
-
- /**
- * Creates the header for the code block (with correct attributes)
- *
- * @return string The header for the code block
- * @since 1.0.0
- * @access private
- */
- function header() {
- // Get attributes needed
- /**
- * @todo Document behaviour change - class is outputted regardless of whether
- * we're using classes or not. Same with style
- */
- $attributes = ' class="' . $this->_genCSSName($this->language);
- if ($this->overall_class != '') {
- $attributes .= " ".$this->_genCSSName($this->overall_class);
- }
- $attributes .= '"';
-
- if ($this->overall_id != '') {
- $attributes .= " id=\"{$this->overall_id}\"";
- }
- if ($this->overall_style != '' && !$this->use_classes) {
- $attributes .= ' style="' . $this->overall_style . '"';
- }
-
- $ol_attributes = '';
-
- if ($this->line_numbers_start != 1) {
- $ol_attributes .= ' start="' . $this->line_numbers_start . '"';
- }
-
- // Get the header HTML
- $header = $this->header_content;
- if ($header) {
- if ($this->header_type == GESHI_HEADER_PRE || $this->header_type == GESHI_HEADER_PRE_VALID) {
- $header = str_replace("\n", '', $header);
- }
- $header = $this->replace_keywords($header);
-
- if ($this->use_classes) {
- $attr = ' class="head"';
- } else {
- $attr = " style=\"{$this->header_content_style}\"";
- }
- if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- $header = "<thead><tr><td colspan=\"2\" $attr>$header</td></tr></thead>";
- } else {
- $header = "<div$attr>$header</div>";
- }
- }
-
- if (GESHI_HEADER_NONE == $this->header_type) {
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- return "$header<ol$attributes$ol_attributes>";
- }
- return $header . ($this->force_code_block ? '<div>' : '');
- }
-
- // Work out what to return and do it
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- if ($this->header_type == GESHI_HEADER_PRE) {
- return "<pre$attributes>$header<ol$ol_attributes>";
- } else if ($this->header_type == GESHI_HEADER_DIV ||
- $this->header_type == GESHI_HEADER_PRE_VALID) {
- return "<div$attributes>$header<ol$ol_attributes>";
- } else if ($this->header_type == GESHI_HEADER_PRE_TABLE) {
- return "<table$attributes>$header<tbody><tr class=\"li1\">";
- }
- } else {
- if ($this->header_type == GESHI_HEADER_PRE) {
- return "<pre$attributes>$header" .
- ($this->force_code_block ? '<div>' : '');
- } else {
- return "<div$attributes>$header" .
- ($this->force_code_block ? '<div>' : '');
- }
- }
- }
-
- /**
- * Returns the footer for the code block.
- *
- * @return string The footer for the code block
- * @since 1.0.0
- * @access private
- */
- function footer() {
- $footer = $this->footer_content;
- if ($footer) {
- if ($this->header_type == GESHI_HEADER_PRE) {
- $footer = str_replace("\n", '', $footer);;
- }
- $footer = $this->replace_keywords($footer);
-
- if ($this->use_classes) {
- $attr = ' class="foot"';
- } else {
- $attr = " style=\"{$this->footer_content_style}\"";
- }
- if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- $footer = "<tfoot><tr><td colspan=\"2\">$footer</td></tr></tfoot>";
- } else {
- $footer = "<div$attr>$footer</div>";
- }
- }
-
- if (GESHI_HEADER_NONE == $this->header_type) {
- return ($this->line_numbers != GESHI_NO_LINE_NUMBERS) ? '</ol>' . $footer : $footer;
- }
-
- if ($this->header_type == GESHI_HEADER_DIV || $this->header_type == GESHI_HEADER_PRE_VALID) {
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- return "</ol>$footer</div>";
- }
- return ($this->force_code_block ? '</div>' : '') .
- "$footer</div>";
- }
- elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) {
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- return "</tr></tbody>$footer</table>";
- }
- return ($this->force_code_block ? '</div>' : '') .
- "$footer</div>";
- }
- else {
- if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- return "</ol>$footer</pre>";
- }
- return ($this->force_code_block ? '</div>' : '') .
- "$footer</pre>";
- }
- }
-
- /**
- * Replaces certain keywords in the header and footer with
- * certain configuration values
- *
- * @param string The header or footer content to do replacement on
- * @return string The header or footer with replaced keywords
- * @since 1.0.2
- * @access private
- */
- function replace_keywords($instr) {
- $keywords = $replacements = array();
-
- $keywords[] = '<TIME>';
- $keywords[] = '{TIME}';
- $replacements[] = $replacements[] = number_format($time = $this->get_time(), 3);
-
- $keywords[] = '<LANGUAGE>';
- $keywords[] = '{LANGUAGE}';
- $replacements[] = $replacements[] = $this->language_data['LANG_NAME'];
-
- $keywords[] = '<VERSION>';
- $keywords[] = '{VERSION}';
- $replacements[] = $replacements[] = GESHI_VERSION;
-
- $keywords[] = '<SPEED>';
- $keywords[] = '{SPEED}';
- if ($time <= 0) {
- $speed = 'N/A';
- } else {
- $speed = strlen($this->source) / $time;
- if ($speed >= 1024) {
- $speed = sprintf("%.2f KB/s", $speed / 1024.0);
- } else {
- $speed = sprintf("%.0f B/s", $speed);
- }
- }
- $replacements[] = $replacements[] = $speed;
-
- return str_replace($keywords, $replacements, $instr);
- }
-
- /**
- * Secure replacement for PHP built-in function htmlspecialchars().
- *
- * See ticket #427 (http://wush.net/trac/wikka/ticket/427) for the rationale
- * for this replacement function.
- *
- * The INTERFACE for this function is almost the same as that for
- * htmlspecialchars(), with the same default for quote style; however, there
- * is no 'charset' parameter. The reason for this is as follows:
- *
- * The PHP docs say:
- * "The third argument charset defines character set used in conversion."
- *
- * I suspect PHP's htmlspecialchars() is working at the byte-value level and
- * thus _needs_ to know (or asssume) a character set because the special
- * characters to be replaced could exist at different code points in
- * different character sets. (If indeed htmlspecialchars() works at
- * byte-value level that goes some way towards explaining why the
- * vulnerability would exist in this function, too, and not only in
- * htmlentities() which certainly is working at byte-value level.)
- *
- * This replacement function however works at character level and should
- * therefore be "immune" to character set differences - so no charset
- * parameter is needed or provided. If a third parameter is passed, it will
- * be silently ignored.
- *
- * In the OUTPUT there is a minor difference in that we use '&#39;' instead
- * of PHP's '&#039;' for a single quote: this provides compatibility with
- * get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES)
- * (see comment by mikiwoz at yahoo dot co dot uk on
- * http://php.net/htmlspecialchars); it also matches the entity definition
- * for XML 1.0
- * (http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters).
- * Like PHP we use a numeric character reference instead of '&apos;' for the
- * single quote. For the other special characters we use the named entity
- * references, as PHP is doing.
- *
- * @author {@link http://wikkawiki.org/JavaWoman Marjolein Katsma}
- *
- * @license http://www.gnu.org/copyleft/lgpl.html
- * GNU Lesser General Public License
- * @copyright Copyright 2007, {@link http://wikkawiki.org/CreditsPage
- * Wikka Development Team}
- *
- * @access private
- * @param string $string string to be converted
- * @param integer $quote_style
- * - ENT_COMPAT: escapes &, <, > and double quote (default)
- * - ENT_NOQUOTES: escapes only &, < and >
- * - ENT_QUOTES: escapes &, <, >, double and single quotes
- * @return string converted string
- * @since 1.0.7.18
- */
- function hsc($string, $quote_style = ENT_COMPAT) {
- // init
- static $aTransSpecchar = array(
- '&' => '&amp;',
- '"' => '&quot;',
- '<' => '&lt;',
- '>' => '&gt;',
-
- //This fix is related to SF#1923020, but has to be applied
- //regardless of actually highlighting symbols.
-
- //Circumvent a bug with symbol highlighting
- //This is required as ; would produce undesirable side-effects if it
- //was not to be processed as an entity.
- ';' => '<SEMI>', // Force ; to be processed as entity
- '|' => '<PIPE>' // Force | to be processed as entity
- ); // ENT_COMPAT set
-
- switch ($quote_style) {
- case ENT_NOQUOTES: // don't convert double quotes
- unset($aTransSpecchar['"']);
- break;
- case ENT_QUOTES: // convert single quotes as well
- $aTransSpecchar["'"] = '&#39;'; // (apos) htmlspecialchars() uses '&#039;'
- break;
- }
-
- // return translated string
- return strtr($string, $aTransSpecchar);
- }
-
- function _genCSSName($name){
- return (is_numeric($name[0]) ? '_' : '') . $name;
- }
-
- /**
- * Returns a stylesheet for the highlighted code. If $economy mode
- * is true, we only return the stylesheet declarations that matter for
- * this code block instead of the whole thing
- *
- * @param boolean Whether to use economy mode or not
- * @return string A stylesheet built on the data for the current language
- * @since 1.0.0
- */
- function get_stylesheet($economy_mode = true) {
- // If there's an error, chances are that the language file
- // won't have populated the language data file, so we can't
- // risk getting a stylesheet...
- if ($this->error) {
- return '';
- }
-
- //Check if the style rearrangements have been processed ...
- //This also does some preprocessing to check which style groups are useable ...
- if(!isset($this->language_data['NUMBERS_CACHE'])) {
- $this->build_style_cache();
- }
-
- // First, work out what the selector should be. If there's an ID,
- // that should be used, the same for a class. Otherwise, a selector
- // of '' means that these styles will be applied anywhere
- if ($this->overall_id) {
- $selector = '#' . $this->_genCSSName($this->overall_id);
- } else {
- $selector = '.' . $this->_genCSSName($this->language);
- if ($this->overall_class) {
- $selector .= '.' . $this->_genCSSName($this->overall_class);
- }
- }
- $selector .= ' ';
-
- // Header of the stylesheet
- if (!$economy_mode) {
- $stylesheet = "/**\n".
- " * GeSHi Dynamically Generated Stylesheet\n".
- " * --------------------------------------\n".
- " * Dynamically generated stylesheet for {$this->language}\n".
- " * CSS class: {$this->overall_class}, CSS id: {$this->overall_id}\n".
- " * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" .
- " * (http://qbnz.com/highlighter/ and http://geshi.org/)\n".
- " * --------------------------------------\n".
- " */\n";
- } else {
- $stylesheet = "/**\n".
- " * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" .
- " * (http://qbnz.com/highlighter/ and http://geshi.org/)\n".
- " */\n";
- }
-
- // Set the <ol> to have no effect at all if there are line numbers
- // (<ol>s have margins that should be destroyed so all layout is
- // controlled by the set_overall_style method, which works on the
- // <pre> or <div> container). Additionally, set default styles for lines
- if (!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
- //$stylesheet .= "$selector, {$selector}ol, {$selector}ol li {margin: 0;}\n";
- $stylesheet .= "$selector.de1, $selector.de2 {{$this->code_style}}\n";
- }
-
- // Add overall styles
- // note: neglect economy_mode, empty styles are meaningless
- if ($this->overall_style != '') {
- $stylesheet .= "$selector {{$this->overall_style}}\n";
- }
-
- // Add styles for links
- // note: economy mode does not make _any_ sense here
- // either the style is empty and thus no selector is needed
- // or the appropriate key is given.
- foreach ($this->link_styles as $key => $style) {
- if ($style != '') {
- switch ($key) {
- case GESHI_LINK:
- $stylesheet .= "{$selector}a:link {{$style}}\n";
- break;
- case GESHI_HOVER:
- $stylesheet .= "{$selector}a:hover {{$style}}\n";
- break;
- case GESHI_ACTIVE:
- $stylesheet .= "{$selector}a:active {{$style}}\n";
- break;
- case GESHI_VISITED:
- $stylesheet .= "{$selector}a:visited {{$style}}\n";
- break;
- }
- }
- }
-
- // Header and footer
- // note: neglect economy_mode, empty styles are meaningless
- if ($this->header_content_style != '') {
- $stylesheet .= "$selector.head {{$this->header_content_style}}\n";
- }
- if ($this->footer_content_style != '') {
- $stylesheet .= "$selector.foot {{$this->footer_content_style}}\n";
- }
-
- // Styles for important stuff
- // note: neglect economy_mode, empty styles are meaningless
- if ($this->important_styles != '') {
- $stylesheet .= "$selector.imp {{$this->important_styles}}\n";
- }
-
- // Simple line number styles
- if ((!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) && $this->line_style1 != '') {
- $stylesheet .= "{$selector}li, {$selector}.li1 {{$this->line_style1}}\n";
- }
- if ((!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) && $this->table_linenumber_style != '') {
- $stylesheet .= "{$selector}.ln {{$this->table_linenumber_style}}\n";
- }
- // If there is a style set for fancy line numbers, echo it out
- if ((!$economy_mode || $this->line_numbers == GESHI_FANCY_LINE_NUMBERS) && $this->line_style2 != '') {
- $stylesheet .= "{$selector}.li2 {{$this->line_style2}}\n";
- }
-
- // note: empty styles are meaningless
- foreach ($this->language_data['STYLES']['KEYWORDS'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode ||
- (isset($this->lexic_permissions['KEYWORDS'][$group]) &&
- $this->lexic_permissions['KEYWORDS'][$group]))) {
- $stylesheet .= "$selector.kw$group {{$styles}}\n";
- }
- }
- foreach ($this->language_data['STYLES']['COMMENTS'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode ||
- (isset($this->lexic_permissions['COMMENTS'][$group]) &&
- $this->lexic_permissions['COMMENTS'][$group]) ||
- (!empty($this->language_data['COMMENT_REGEXP']) &&
- !empty($this->language_data['COMMENT_REGEXP'][$group])))) {
- $stylesheet .= "$selector.co$group {{$styles}}\n";
- }
- }
- foreach ($this->language_data['STYLES']['ESCAPE_CHAR'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode || $this->lexic_permissions['ESCAPE_CHAR'])) {
- // NEW: since 1.0.8 we have to handle hardescapes
- if ($group === 'HARD') {
- $group = '_h';
- }
- $stylesheet .= "$selector.es$group {{$styles}}\n";
- }
- }
- foreach ($this->language_data['STYLES']['BRACKETS'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode || $this->lexic_permissions['BRACKETS'])) {
- $stylesheet .= "$selector.br$group {{$styles}}\n";
- }
- }
- foreach ($this->language_data['STYLES']['SYMBOLS'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode || $this->lexic_permissions['SYMBOLS'])) {
- $stylesheet .= "$selector.sy$group {{$styles}}\n";
- }
- }
- foreach ($this->language_data['STYLES']['STRINGS'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode || $this->lexic_permissions['STRINGS'])) {
- // NEW: since 1.0.8 we have to handle hardquotes
- if ($group === 'HARD') {
- $group = '_h';
- }
- $stylesheet .= "$selector.st$group {{$styles}}\n";
- }
- }
- foreach ($this->language_data['STYLES']['NUMBERS'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode || $this->lexic_permissions['NUMBERS'])) {
- $stylesheet .= "$selector.nu$group {{$styles}}\n";
- }
- }
- foreach ($this->language_data['STYLES']['METHODS'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode || $this->lexic_permissions['METHODS'])) {
- $stylesheet .= "$selector.me$group {{$styles}}\n";
- }
- }
- // note: neglect economy_mode, empty styles are meaningless
- foreach ($this->language_data['STYLES']['SCRIPT'] as $group => $styles) {
- if ($styles != '') {
- $stylesheet .= "$selector.sc$group {{$styles}}\n";
- }
- }
- foreach ($this->language_data['STYLES']['REGEXPS'] as $group => $styles) {
- if ($styles != '' && (!$economy_mode ||
- (isset($this->lexic_permissions['REGEXPS'][$group]) &&
- $this->lexic_permissions['REGEXPS'][$group]))) {
- if (is_array($this->language_data['REGEXPS'][$group]) &&
- array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$group])) {
- $stylesheet .= "$selector.";
- $stylesheet .= $this->language_data['REGEXPS'][$group][GESHI_CLASS];
- $stylesheet .= " {{$styles}}\n";
- } else {
- $stylesheet .= "$selector.re$group {{$styles}}\n";
- }
- }
- }
- // Styles for lines being highlighted extra
- if (!$economy_mode || (count($this->highlight_extra_lines)!=count($this->highlight_extra_lines_styles))) {
- $stylesheet .= "{$selector}.ln-xtra, {$selector}li.ln-xtra, {$selector}div.ln-xtra {{$this->highlight_extra_lines_style}}\n";
- }
- $stylesheet .= "{$selector}span.xtra { display:block; }\n";
- foreach ($this->highlight_extra_lines_styles as $lineid => $linestyle) {
- $stylesheet .= "{$selector}.lx$lineid, {$selector}li.lx$lineid, {$selector}div.lx$lineid {{$linestyle}}\n";
- }
-
- return $stylesheet;
- }
-
- /**
- * Get's the style that is used for the specified line
- *
- * @param int The line number information is requested for
- * @access private
- * @since 1.0.7.21
- */
- function get_line_style($line) {
- //$style = null;
- $style = null;
- if (isset($this->highlight_extra_lines_styles[$line])) {
- $style = $this->highlight_extra_lines_styles[$line];
- } else { // if no "extra" style assigned
- $style = $this->highlight_extra_lines_style;
- }
-
- return $style;
- }
-
- /**
- * this functions creates an optimized regular expression list
- * of an array of strings.
- *
- * Example:
- * <code>$list = array('faa', 'foo', 'foobar');
- * => string 'f(aa|oo(bar)?)'</code>
- *
- * @param $list array of (unquoted) strings
- * @param $regexp_delimiter your regular expression delimiter, @see preg_quote()
- * @return string for regular expression
- * @author Milian Wolff <mail@milianw.de>
- * @since 1.0.8
- * @access private
- */
- function optimize_regexp_list($list, $regexp_delimiter = '/') {
- $regex_chars = array('.', '\\', '+', '*', '?', '[', '^', ']', '$',
- '(', ')', '{', '}', '=', '!', '<', '>', '|', ':', $regexp_delimiter);
- sort($list);
- $regexp_list = array('');
- $num_subpatterns = 0;
- $list_key = 0;
-
- // the tokens which we will use to generate the regexp list
- $tokens = array();
- $prev_keys = array();
- // go through all entries of the list and generate the token list
- $cur_len = 0;
- for ($i = 0, $i_max = count($list); $i < $i_max; ++$i) {
- if ($cur_len > GESHI_MAX_PCRE_LENGTH) {
- // seems like the length of this pcre is growing exorbitantly
- $regexp_list[++$list_key] = $this->_optimize_regexp_list_tokens_to_string($tokens);
- $num_subpatterns = substr_count($regexp_list[$list_key], '(?:');
- $tokens = array();
- $cur_len = 0;
- }
- $level = 0;
- $entry = preg_quote((string) $list[$i], $regexp_delimiter);
- $pointer = &$tokens;
- // properly assign the new entry to the correct position in the token array
- // possibly generate smaller common denominator keys
- while (true) {
- // get the common denominator
- if (isset($prev_keys[$level])) {
- if ($prev_keys[$level] == $entry) {
- // this is a duplicate entry, skip it
- continue 2;
- }
- $char = 0;
- while (isset($entry[$char]) && isset($prev_keys[$level][$char])
- && $entry[$char] == $prev_keys[$level][$char]) {
- ++$char;
- }
- if ($char > 0) {
- // this entry has at least some chars in common with the current key
- if ($char == strlen($prev_keys[$level])) {
- // current key is totally matched, i.e. this entry has just some bits appended
- $pointer = &$pointer[$prev_keys[$level]];
- } else {
- // only part of the keys match
- $new_key_part1 = substr($prev_keys[$level], 0, $char);
- $new_key_part2 = substr($prev_keys[$level], $char);
-
- if (in_array($new_key_part1[0], $regex_chars)
- || in_array($new_key_part2[0], $regex_chars)) {
- // this is bad, a regex char as first character
- $pointer[$entry] = array('' => true);
- array_splice($prev_keys, $level, count($prev_keys), $entry);
- $cur_len += strlen($entry);
- continue;
- } else {
- // relocate previous tokens
- $pointer[$new_key_part1] = array($new_key_part2 => $pointer[$prev_keys[$level]]);
- unset($pointer[$prev_keys[$level]]);
- $pointer = &$pointer[$new_key_part1];
- // recreate key index
- array_splice($prev_keys, $level, count($prev_keys), array($new_key_part1, $new_key_part2));
- $cur_len += strlen($new_key_part2);
- }
- }
- ++$level;
- $entry = substr($entry, $char);
- continue;
- }
- // else: fall trough, i.e. no common denominator was found
- }
- if ($level == 0 && !empty($tokens)) {
- // we can dump current tokens into the string and throw them away afterwards
- $new_entry = $this->_optimize_regexp_list_tokens_to_string($tokens);
- $new_subpatterns = substr_count($new_entry, '(?:');
- if (GESHI_MAX_PCRE_SUBPATTERNS && $num_subpatterns + $new_subpatterns > GESHI_MAX_PCRE_SUBPATTERNS) {
- $regexp_list[++$list_key] = $new_entry;
- $num_subpatterns = $new_subpatterns;
- } else {
- if (!empty($regexp_list[$list_key])) {
- $new_entry = '|' . $new_entry;
- }
- $regexp_list[$list_key] .= $new_entry;
- $num_subpatterns += $new_subpatterns;
- }
- $tokens = array();
- $cur_len = 0;
- }
- // no further common denominator found
- $pointer[$entry] = array('' => true);
- array_splice($prev_keys, $level, count($prev_keys), $entry);
-
- $cur_len += strlen($entry);
- break;
- }
- unset($list[$i]);
- }
- // make sure the last tokens get converted as well
- $new_entry = $this->_optimize_regexp_list_tokens_to_string($tokens);
- if (GESHI_MAX_PCRE_SUBPATTERNS && $num_subpatterns + substr_count($new_entry, '(?:') > GESHI_MAX_PCRE_SUBPATTERNS) {
- if ( !empty($regexp_list[$list_key]) ) {
- ++$list_key;
- }
- $regexp_list[$list_key] = $new_entry;
- } else {
- if (!empty($regexp_list[$list_key])) {
- $new_entry = '|' . $new_entry;
- }
- $regexp_list[$list_key] .= $new_entry;
- }
- return $regexp_list;
- }
- /**
- * this function creates the appropriate regexp string of an token array
- * you should not call this function directly, @see $this->optimize_regexp_list().
- *
- * @param &$tokens array of tokens
- * @param $recursed bool to know wether we recursed or not
- * @return string
- * @author Milian Wolff <mail@milianw.de>
- * @since 1.0.8
- * @access private
- */
- function _optimize_regexp_list_tokens_to_string(&$tokens, $recursed = false) {
- $list = '';
- foreach ($tokens as $token => $sub_tokens) {
- $list .= $token;
- $close_entry = isset($sub_tokens['']);
- unset($sub_tokens['']);
- if (!empty($sub_tokens)) {
- $list .= '(?:' . $this->_optimize_regexp_list_tokens_to_string($sub_tokens, true) . ')';
- if ($close_entry) {
- // make sub_tokens optional
- $list .= '?';
- }
- }
- $list .= '|';
- }
- if (!$recursed) {
- // do some optimizations
- // common trailing strings
- // BUGGY!
- //$list = preg_replace_callback('#(?<=^|\:|\|)\w+?(\w+)(?:\|.+\1)+(?=\|)#', create_function(
- // '$matches', 'return "(?:" . preg_replace("#" . preg_quote($matches[1], "#") . "(?=\||$)#", "", $matches[0]) . ")" . $matches[1];'), $list);
- // (?:p)? => p?
- $list = preg_replace('#\(\?\:(.)\)\?#', '\1?', $list);
- // (?:a|b|c|d|...)? => [abcd...]?
- // TODO: a|bb|c => [ac]|bb
- static $callback_2;
- if (!isset($callback_2)) {
- $callback_2 = create_function('$matches', 'return "[" . str_replace("|", "", $matches[1]) . "]";');
- }
- $list = preg_replace_callback('#\(\?\:((?:.\|)+.)\)#', $callback_2, $list);
- }
- // return $list without trailing pipe
- return substr($list, 0, -1);
- }
-} // End Class GeSHi
-
-
-if (!function_exists('geshi_highlight')) {
- /**
- * Easy way to highlight stuff. Behaves just like highlight_string
- *
- * @param string The code to highlight
- * @param string The language to highlight the code in
- * @param string The path to the language files. You can leave this blank if you need
- * as from version 1.0.7 the path should be automatically detected
- * @param boolean Whether to return the result or to echo
- * @return string The code highlighted (if $return is true)
- * @since 1.0.2
- */
- function geshi_highlight($string, $language, $path = null, $return = false) {
- $geshi = new GeSHi($string, $language, $path);
- $geshi->set_header_type(GESHI_HEADER_NONE);
-
- if ($return) {
- return '<code>' . $geshi->parse_code() . '</code>';
- }
-
- echo '<code>' . $geshi->parse_code() . '</code>';
-
- if ($geshi->error()) {
- return false;
- }
- return true;
- }
-}
-
+<?php
+/**
+ * GeSHi - Generic Syntax Highlighter
+ *
+ * The GeSHi class for Generic Syntax Highlighting. Please refer to the
+ * documentation at http://qbnz.com/highlighter/documentation.php for more
+ * information about how to use this class.
+ *
+ * For changes, release notes, TODOs etc, see the relevant files in the docs/
+ * directory.
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * @package geshi
+ * @subpackage core
+ * @author Nigel McNie <nigel@geshi.org>, Benny Baumann <BenBE@omorphia.de>
+ * @copyright (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann
+ * @license http://gnu.org/copyleft/gpl.html GNU GPL
+ *
+ */
+
+//
+// GeSHi Constants
+// You should use these constant names in your programs instead of
+// their values - you never know when a value may change in a future
+// version
+//
+
+/** The version of this GeSHi file */
+define('GESHI_VERSION', '1.0.8.11');
+
+// Define the root directory for the GeSHi code tree
+if (!defined('GESHI_ROOT')) {
+ /** The root directory for GeSHi */
+ define('GESHI_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+}
+/** The language file directory for GeSHi
+ @access private */
+define('GESHI_LANG_ROOT', GESHI_ROOT . 'geshi' . DIRECTORY_SEPARATOR);
+
+// Define if GeSHi should be paranoid about security
+if (!defined('GESHI_SECURITY_PARANOID')) {
+ /** Tells GeSHi to be paranoid about security settings */
+ define('GESHI_SECURITY_PARANOID', false);
+}
+
+// Line numbers - use with enable_line_numbers()
+/** Use no line numbers when building the result */
+define('GESHI_NO_LINE_NUMBERS', 0);
+/** Use normal line numbers when building the result */
+define('GESHI_NORMAL_LINE_NUMBERS', 1);
+/** Use fancy line numbers when building the result */
+define('GESHI_FANCY_LINE_NUMBERS', 2);
+
+// Container HTML type
+/** Use nothing to surround the source */
+define('GESHI_HEADER_NONE', 0);
+/** Use a "div" to surround the source */
+define('GESHI_HEADER_DIV', 1);
+/** Use a "pre" to surround the source */
+define('GESHI_HEADER_PRE', 2);
+/** Use a pre to wrap lines when line numbers are enabled or to wrap the whole code. */
+define('GESHI_HEADER_PRE_VALID', 3);
+/**
+ * Use a "table" to surround the source:
+ *
+ * <table>
+ * <thead><tr><td colspan="2">$header</td></tr></thead>
+ * <tbody><tr><td><pre>$linenumbers</pre></td><td><pre>$code></pre></td></tr></tbody>
+ * <tfooter><tr><td colspan="2">$footer</td></tr></tfoot>
+ * </table>
+ *
+ * this is essentially only a workaround for Firefox, see sf#1651996 or take a look at
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=365805
+ * @note when linenumbers are disabled this is essentially the same as GESHI_HEADER_PRE
+ */
+define('GESHI_HEADER_PRE_TABLE', 4);
+
+// Capatalisation constants
+/** Lowercase keywords found */
+define('GESHI_CAPS_NO_CHANGE', 0);
+/** Uppercase keywords found */
+define('GESHI_CAPS_UPPER', 1);
+/** Leave keywords found as the case that they are */
+define('GESHI_CAPS_LOWER', 2);
+
+// Link style constants
+/** Links in the source in the :link state */
+define('GESHI_LINK', 0);
+/** Links in the source in the :hover state */
+define('GESHI_HOVER', 1);
+/** Links in the source in the :active state */
+define('GESHI_ACTIVE', 2);
+/** Links in the source in the :visited state */
+define('GESHI_VISITED', 3);
+
+// Important string starter/finisher
+// Note that if you change these, they should be as-is: i.e., don't
+// write them as if they had been run through htmlentities()
+/** The starter for important parts of the source */
+define('GESHI_START_IMPORTANT', '<BEGIN GeSHi>');
+/** The ender for important parts of the source */
+define('GESHI_END_IMPORTANT', '<END GeSHi>');
+
+/**#@+
+ * @access private
+ */
+// When strict mode applies for a language
+/** Strict mode never applies (this is the most common) */
+define('GESHI_NEVER', 0);
+/** Strict mode *might* apply, and can be enabled or
+ disabled by {@link GeSHi->enable_strict_mode()} */
+define('GESHI_MAYBE', 1);
+/** Strict mode always applies */
+define('GESHI_ALWAYS', 2);
+
+// Advanced regexp handling constants, used in language files
+/** The key of the regex array defining what to search for */
+define('GESHI_SEARCH', 0);
+/** The key of the regex array defining what bracket group in a
+ matched search to use as a replacement */
+define('GESHI_REPLACE', 1);
+/** The key of the regex array defining any modifiers to the regular expression */
+define('GESHI_MODIFIERS', 2);
+/** The key of the regex array defining what bracket group in a
+ matched search to put before the replacement */
+define('GESHI_BEFORE', 3);
+/** The key of the regex array defining what bracket group in a
+ matched search to put after the replacement */
+define('GESHI_AFTER', 4);
+/** The key of the regex array defining a custom keyword to use
+ for this regexp's html tag class */
+define('GESHI_CLASS', 5);
+
+/** Used in language files to mark comments */
+define('GESHI_COMMENTS', 0);
+
+/** Used to work around missing PHP features **/
+define('GESHI_PHP_PRE_433', !(version_compare(PHP_VERSION, '4.3.3') === 1));
+
+/** make sure we can call stripos **/
+if (!function_exists('stripos')) {
+ // the offset param of preg_match is not supported below PHP 4.3.3
+ if (GESHI_PHP_PRE_433) {
+ /**
+ * @ignore
+ */
+ function stripos($haystack, $needle, $offset = null) {
+ if (!is_null($offset)) {
+ $haystack = substr($haystack, $offset);
+ }
+ if (preg_match('/'. preg_quote($needle, '/') . '/', $haystack, $match, PREG_OFFSET_CAPTURE)) {
+ return $match[0][1];
+ }
+ return false;
+ }
+ }
+ else {
+ /**
+ * @ignore
+ */
+ function stripos($haystack, $needle, $offset = null) {
+ if (preg_match('/'. preg_quote($needle, '/') . '/', $haystack, $match, PREG_OFFSET_CAPTURE, $offset)) {
+ return $match[0][1];
+ }
+ return false;
+ }
+ }
+}
+
+/** some old PHP / PCRE subpatterns only support up to xxx subpatterns in
+ regular expressions. Set this to false if your PCRE lib is up to date
+ @see GeSHi->optimize_regexp_list()
+ **/
+define('GESHI_MAX_PCRE_SUBPATTERNS', 500);
+/** it's also important not to generate too long regular expressions
+ be generous here... but keep in mind, that when reaching this limit we
+ still have to close open patterns. 12k should do just fine on a 16k limit.
+ @see GeSHi->optimize_regexp_list()
+ **/
+define('GESHI_MAX_PCRE_LENGTH', 12288);
+
+//Number format specification
+/** Basic number format for integers */
+define('GESHI_NUMBER_INT_BASIC', 1); //Default integers \d+
+/** Enhanced number format for integers like seen in C */
+define('GESHI_NUMBER_INT_CSTYLE', 2); //Default C-Style \d+[lL]?
+/** Number format to highlight binary numbers with a suffix "b" */
+define('GESHI_NUMBER_BIN_SUFFIX', 16); //[01]+[bB]
+/** Number format to highlight binary numbers with a prefix % */
+define('GESHI_NUMBER_BIN_PREFIX_PERCENT', 32); //%[01]+
+/** Number format to highlight binary numbers with a prefix 0b (C) */
+define('GESHI_NUMBER_BIN_PREFIX_0B', 64); //0b[01]+
+/** Number format to highlight octal numbers with a leading zero */
+define('GESHI_NUMBER_OCT_PREFIX', 256); //0[0-7]+
+/** Number format to highlight octal numbers with a prefix 0o (logtalk) */
+define('GESHI_NUMBER_OCT_PREFIX_0O', 512); //0[0-7]+
+/** Number format to highlight octal numbers with a leading @ (Used in HiSofts Devpac series). */
+define('GESHI_NUMBER_OCT_PREFIX_AT', 1024); //@[0-7]+
+/** Number format to highlight octal numbers with a suffix of o */
+define('GESHI_NUMBER_OCT_SUFFIX', 2048); //[0-7]+[oO]
+/** Number format to highlight hex numbers with a prefix 0x */
+define('GESHI_NUMBER_HEX_PREFIX', 4096); //0x[0-9a-fA-F]+
+/** Number format to highlight hex numbers with a prefix $ */
+define('GESHI_NUMBER_HEX_PREFIX_DOLLAR', 8192); //$[0-9a-fA-F]+
+/** Number format to highlight hex numbers with a suffix of h */
+define('GESHI_NUMBER_HEX_SUFFIX', 16384); //[0-9][0-9a-fA-F]*h
+/** Number format to highlight floating-point numbers without support for scientific notation */
+define('GESHI_NUMBER_FLT_NONSCI', 65536); //\d+\.\d+
+/** Number format to highlight floating-point numbers without support for scientific notation */
+define('GESHI_NUMBER_FLT_NONSCI_F', 131072); //\d+(\.\d+)?f
+/** Number format to highlight floating-point numbers with support for scientific notation (E) and optional leading zero */
+define('GESHI_NUMBER_FLT_SCI_SHORT', 262144); //\.\d+e\d+
+/** Number format to highlight floating-point numbers with support for scientific notation (E) and required leading digit */
+define('GESHI_NUMBER_FLT_SCI_ZERO', 524288); //\d+(\.\d+)?e\d+
+//Custom formats are passed by RX array
+
+// Error detection - use these to analyse faults
+/** No sourcecode to highlight was specified
+ * @deprecated
+ */
+define('GESHI_ERROR_NO_INPUT', 1);
+/** The language specified does not exist */
+define('GESHI_ERROR_NO_SUCH_LANG', 2);
+/** GeSHi could not open a file for reading (generally a language file) */
+define('GESHI_ERROR_FILE_NOT_READABLE', 3);
+/** The header type passed to {@link GeSHi->set_header_type()} was invalid */
+define('GESHI_ERROR_INVALID_HEADER_TYPE', 4);
+/** The line number type passed to {@link GeSHi->enable_line_numbers()} was invalid */
+define('GESHI_ERROR_INVALID_LINE_NUMBER_TYPE', 5);
+/**#@-*/
+
+
+/**
+ * The GeSHi Class.
+ *
+ * Please refer to the documentation for GeSHi 1.0.X that is available
+ * at http://qbnz.com/highlighter/documentation.php for more information
+ * about how to use this class.
+ *
+ * @package geshi
+ * @author Nigel McNie <nigel@geshi.org>, Benny Baumann <BenBE@omorphia.de>
+ * @copyright (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann
+ */
+class GeSHi {
+ /**#@+
+ * @access private
+ */
+ /**
+ * The source code to highlight
+ * @var string
+ */
+ var $source = '';
+
+ /**
+ * The language to use when highlighting
+ * @var string
+ */
+ var $language = '';
+
+ /**
+ * The data for the language used
+ * @var array
+ */
+ var $language_data = array();
+
+ /**
+ * The path to the language files
+ * @var string
+ */
+ var $language_path = GESHI_LANG_ROOT;
+
+ /**
+ * The error message associated with an error
+ * @var string
+ * @todo check err reporting works
+ */
+ var $error = false;
+
+ /**
+ * Possible error messages
+ * @var array
+ */
+ var $error_messages = array(
+ GESHI_ERROR_NO_SUCH_LANG => 'GeSHi could not find the language {LANGUAGE} (using path {PATH})',
+ GESHI_ERROR_FILE_NOT_READABLE => 'The file specified for load_from_file was not readable',
+ GESHI_ERROR_INVALID_HEADER_TYPE => 'The header type specified is invalid',
+ GESHI_ERROR_INVALID_LINE_NUMBER_TYPE => 'The line number type specified is invalid'
+ );
+
+ /**
+ * Whether highlighting is strict or not
+ * @var boolean
+ */
+ var $strict_mode = false;
+
+ /**
+ * Whether to use CSS classes in output
+ * @var boolean
+ */
+ var $use_classes = false;
+
+ /**
+ * The type of header to use. Can be one of the following
+ * values:
+ *
+ * - GESHI_HEADER_PRE: Source is outputted in a "pre" HTML element.
+ * - GESHI_HEADER_DIV: Source is outputted in a "div" HTML element.
+ * - GESHI_HEADER_NONE: No header is outputted.
+ *
+ * @var int
+ */
+ var $header_type = GESHI_HEADER_PRE;
+
+ /**
+ * Array of permissions for which lexics should be highlighted
+ * @var array
+ */
+ var $lexic_permissions = array(
+ 'KEYWORDS' => array(),
+ 'COMMENTS' => array('MULTI' => true),
+ 'REGEXPS' => array(),
+ 'ESCAPE_CHAR' => true,
+ 'BRACKETS' => true,
+ 'SYMBOLS' => false,
+ 'STRINGS' => true,
+ 'NUMBERS' => true,
+ 'METHODS' => true,
+ 'SCRIPT' => true
+ );
+
+ /**
+ * The time it took to parse the code
+ * @var double
+ */
+ var $time = 0;
+
+ /**
+ * The content of the header block
+ * @var string
+ */
+ var $header_content = '';
+
+ /**
+ * The content of the footer block
+ * @var string
+ */
+ var $footer_content = '';
+
+ /**
+ * The style of the header block
+ * @var string
+ */
+ var $header_content_style = '';
+
+ /**
+ * The style of the footer block
+ * @var string
+ */
+ var $footer_content_style = '';
+
+ /**
+ * Tells if a block around the highlighted source should be forced
+ * if not using line numbering
+ * @var boolean
+ */
+ var $force_code_block = false;
+
+ /**
+ * The styles for hyperlinks in the code
+ * @var array
+ */
+ var $link_styles = array();
+
+ /**
+ * Whether important blocks should be recognised or not
+ * @var boolean
+ * @deprecated
+ * @todo REMOVE THIS FUNCTIONALITY!
+ */
+ var $enable_important_blocks = false;
+
+ /**
+ * Styles for important parts of the code
+ * @var string
+ * @deprecated
+ * @todo As above - rethink the whole idea of important blocks as it is buggy and
+ * will be hard to implement in 1.2
+ */
+ var $important_styles = 'font-weight: bold; color: red;'; // Styles for important parts of the code
+
+ /**
+ * Whether CSS IDs should be added to the code
+ * @var boolean
+ */
+ var $add_ids = false;
+
+ /**
+ * Lines that should be highlighted extra
+ * @var array
+ */
+ var $highlight_extra_lines = array();
+
+ /**
+ * Styles of lines that should be highlighted extra
+ * @var array
+ */
+ var $highlight_extra_lines_styles = array();
+
+ /**
+ * Styles of extra-highlighted lines
+ * @var string
+ */
+ var $highlight_extra_lines_style = 'background-color: #ffc;';
+
+ /**
+ * The line ending
+ * If null, nl2br() will be used on the result string.
+ * Otherwise, all instances of \n will be replaced with $line_ending
+ * @var string
+ */
+ var $line_ending = null;
+
+ /**
+ * Number at which line numbers should start at
+ * @var int
+ */
+ var $line_numbers_start = 1;
+
+ /**
+ * The overall style for this code block
+ * @var string
+ */
+ var $overall_style = 'font-family:monospace;';
+
+ /**
+ * The style for the actual code
+ * @var string
+ */
+ var $code_style = 'font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;';
+
+ /**
+ * The overall class for this code block
+ * @var string
+ */
+ var $overall_class = '';
+
+ /**
+ * The overall ID for this code block
+ * @var string
+ */
+ var $overall_id = '';
+
+ /**
+ * Line number styles
+ * @var string
+ */
+ var $line_style1 = 'font-weight: normal; vertical-align:top;';
+
+ /**
+ * Line number styles for fancy lines
+ * @var string
+ */
+ var $line_style2 = 'font-weight: bold; vertical-align:top;';
+
+ /**
+ * Style for line numbers when GESHI_HEADER_PRE_TABLE is chosen
+ * @var string
+ */
+ var $table_linenumber_style = 'width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;';
+
+ /**
+ * Flag for how line numbers are displayed
+ * @var boolean
+ */
+ var $line_numbers = GESHI_NO_LINE_NUMBERS;
+
+ /**
+ * Flag to decide if multi line spans are allowed. Set it to false to make sure
+ * each tag is closed before and reopened after each linefeed.
+ * @var boolean
+ */
+ var $allow_multiline_span = true;
+
+ /**
+ * The "nth" value for fancy line highlighting
+ * @var int
+ */
+ var $line_nth_row = 0;
+
+ /**
+ * The size of tab stops
+ * @var int
+ */
+ var $tab_width = 8;
+
+ /**
+ * Should we use language-defined tab stop widths?
+ * @var int
+ */
+ var $use_language_tab_width = false;
+
+ /**
+ * Default target for keyword links
+ * @var string
+ */
+ var $link_target = '';
+
+ /**
+ * The encoding to use for entity encoding
+ * NOTE: Used with Escape Char Sequences to fix UTF-8 handling (cf. SF#2037598)
+ * @var string
+ */
+ var $encoding = 'utf-8';
+
+ /**
+ * Should keywords be linked?
+ * @var boolean
+ */
+ var $keyword_links = true;
+
+ /**
+ * Currently loaded language file
+ * @var string
+ * @since 1.0.7.22
+ */
+ var $loaded_language = '';
+
+ /**
+ * Wether the caches needed for parsing are built or not
+ *
+ * @var bool
+ * @since 1.0.8
+ */
+ var $parse_cache_built = false;
+
+ /**
+ * Work around for Suhosin Patch with disabled /e modifier
+ *
+ * Note from suhosins author in config file:
+ * <blockquote>
+ * The /e modifier inside <code>preg_replace()</code> allows code execution.
+ * Often it is the cause for remote code execution exploits. It is wise to
+ * deactivate this feature and test where in the application it is used.
+ * The developer using the /e modifier should be made aware that he should
+ * use <code>preg_replace_callback()</code> instead
+ * </blockquote>
+ *
+ * @var array
+ * @since 1.0.8
+ */
+ var $_kw_replace_group = 0;
+ var $_rx_key = 0;
+
+ /**
+ * some "callback parameters" for handle_multiline_regexps
+ *
+ * @since 1.0.8
+ * @access private
+ * @var string
+ */
+ var $_hmr_before = '';
+ var $_hmr_replace = '';
+ var $_hmr_after = '';
+ var $_hmr_key = 0;
+
+ /**#@-*/
+
+ /**
+ * Creates a new GeSHi object, with source and language
+ *
+ * @param string The source code to highlight
+ * @param string The language to highlight the source with
+ * @param string The path to the language file directory. <b>This
+ * is deprecated!</b> I've backported the auto path
+ * detection from the 1.1.X dev branch, so now it
+ * should be automatically set correctly. If you have
+ * renamed the language directory however, you will
+ * still need to set the path using this parameter or
+ * {@link GeSHi->set_language_path()}
+ * @since 1.0.0
+ */
+ function GeSHi($source = '', $language = '', $path = '') {
+ if (!empty($source)) {
+ $this->set_source($source);
+ }
+ if (!empty($language)) {
+ $this->set_language($language);
+ }
+ $this->set_language_path($path);
+ }
+
+ /**
+ * Returns the version of GeSHi
+ *
+ * @return string
+ * @since 1 0.8.11
+ */
+ function get_version()
+ {
+ return GESHI_VERSION;
+ }
+
+ /**
+ * Returns an error message associated with the last GeSHi operation,
+ * or false if no error has occured
+ *
+ * @return string|false An error message if there has been an error, else false
+ * @since 1.0.0
+ */
+ function error() {
+ if ($this->error) {
+ //Put some template variables for debugging here ...
+ $debug_tpl_vars = array(
+ '{LANGUAGE}' => $this->language,
+ '{PATH}' => $this->language_path
+ );
+ $msg = str_replace(
+ array_keys($debug_tpl_vars),
+ array_values($debug_tpl_vars),
+ $this->error_messages[$this->error]);
+
+ return "<br /><strong>GeSHi Error:</strong> $msg (code {$this->error})<br />";
+ }
+ return false;
+ }
+
+ /**
+ * Gets a human-readable language name (thanks to Simon Patterson
+ * for the idea :))
+ *
+ * @return string The name for the current language
+ * @since 1.0.2
+ */
+ function get_language_name() {
+ if (GESHI_ERROR_NO_SUCH_LANG == $this->error) {
+ return $this->language_data['LANG_NAME'] . ' (Unknown Language)';
+ }
+ return $this->language_data['LANG_NAME'];
+ }
+
+ /**
+ * Sets the source code for this object
+ *
+ * @param string The source code to highlight
+ * @since 1.0.0
+ */
+ function set_source($source) {
+ $this->source = $source;
+ $this->highlight_extra_lines = array();
+ }
+
+ /**
+ * Sets the language for this object
+ *
+ * @note since 1.0.8 this function won't reset language-settings by default anymore!
+ * if you need this set $force_reset = true
+ *
+ * @param string The name of the language to use
+ * @since 1.0.0
+ */
+ function set_language($language, $force_reset = false) {
+ if ($force_reset) {
+ $this->loaded_language = false;
+ }
+
+ //Clean up the language name to prevent malicious code injection
+ $language = preg_replace('#[^a-zA-Z0-9\-_]#', '', $language);
+
+ $language = strtolower($language);
+
+ //Retreive the full filename
+ $file_name = $this->language_path . $language . '.php';
+ if ($file_name == $this->loaded_language) {
+ // this language is already loaded!
+ return;
+ }
+
+ $this->language = $language;
+
+ $this->error = false;
+ $this->strict_mode = GESHI_NEVER;
+
+ //Check if we can read the desired file
+ if (!is_readable($file_name)) {
+ $this->error = GESHI_ERROR_NO_SUCH_LANG;
+ return;
+ }
+
+ // Load the language for parsing
+ $this->load_language($file_name);
+ }
+
+ /**
+ * Sets the path to the directory containing the language files. Note
+ * that this path is relative to the directory of the script that included
+ * geshi.php, NOT geshi.php itself.
+ *
+ * @param string The path to the language directory
+ * @since 1.0.0
+ * @deprecated The path to the language files should now be automatically
+ * detected, so this method should no longer be needed. The
+ * 1.1.X branch handles manual setting of the path differently
+ * so this method will disappear in 1.2.0.
+ */
+ function set_language_path($path) {
+ if(strpos($path,':')) {
+ //Security Fix to prevent external directories using fopen wrappers.
+ if(DIRECTORY_SEPARATOR == "\\") {
+ if(!preg_match('#^[a-zA-Z]:#', $path) || false !== strpos($path, ':', 2)) {
+ return;
+ }
+ } else {
+ return;
+ }
+ }
+ if(preg_match('#[^/a-zA-Z0-9_\.\-\\\s:]#', $path)) {
+ //Security Fix to prevent external directories using fopen wrappers.
+ return;
+ }
+ if(GESHI_SECURITY_PARANOID && false !== strpos($path, '/.')) {
+ //Security Fix to prevent external directories using fopen wrappers.
+ return;
+ }
+ if(GESHI_SECURITY_PARANOID && false !== strpos($path, '..')) {
+ //Security Fix to prevent external directories using fopen wrappers.
+ return;
+ }
+ if ($path) {
+ $this->language_path = ('/' == $path[strlen($path) - 1]) ? $path : $path . '/';
+ $this->set_language($this->language); // otherwise set_language_path has no effect
+ }
+ }
+
+ /**
+ * Get supported langs or an associative array lang=>full_name.
+ * @param boolean $longnames
+ * @return array
+ */
+ function get_supported_languages($full_names=false)
+ {
+ // return array
+ $back = array();
+
+ // we walk the lang root
+ $dir = dir($this->language_path);
+
+ // foreach entry
+ while (false !== ($entry = $dir->read()))
+ {
+ $full_path = $this->language_path.$entry;
+
+ // Skip all dirs
+ if (is_dir($full_path)) {
+ continue;
+ }
+
+ // we only want lang.php files
+ if (!preg_match('/^([^.]+)\.php$/', $entry, $matches)) {
+ continue;
+ }
+
+ // Raw lang name is here
+ $langname = $matches[1];
+
+ // We want the fullname too?
+ if ($full_names === true)
+ {
+ if (false !== ($fullname = $this->get_language_fullname($langname)))
+ {
+ $back[$langname] = $fullname; // we go associative
+ }
+ }
+ else
+ {
+ // just store raw langname
+ $back[] = $langname;
+ }
+ }
+
+ $dir->close();
+
+ return $back;
+ }
+
+ /**
+ * Get full_name for a lang or false.
+ * @param string $language short langname (html4strict for example)
+ * @return mixed
+ */
+ function get_language_fullname($language)
+ {
+ //Clean up the language name to prevent malicious code injection
+ $language = preg_replace('#[^a-zA-Z0-9\-_]#', '', $language);
+
+ $language = strtolower($language);
+
+ // get fullpath-filename for a langname
+ $fullpath = $this->language_path.$language.'.php';
+
+ // we need to get contents :S
+ if (false === ($data = file_get_contents($fullpath))) {
+ $this->error = sprintf('Geshi::get_lang_fullname() Unknown Language: %s', $language);
+ return false;
+ }
+
+ // match the langname
+ if (!preg_match('/\'LANG_NAME\'\s*=>\s*\'((?:[^\']|\\\')+?)\'/', $data, $matches)) {
+ $this->error = sprintf('Geshi::get_lang_fullname(%s): Regex can not detect language', $language);
+ return false;
+ }
+
+ // return fullname for langname
+ return stripcslashes($matches[1]);
+ }
+
+ /**
+ * Sets the type of header to be used.
+ *
+ * If GESHI_HEADER_DIV is used, the code is surrounded in a "div".This
+ * means more source code but more control over tab width and line-wrapping.
+ * GESHI_HEADER_PRE means that a "pre" is used - less source, but less
+ * control. Default is GESHI_HEADER_PRE.
+ *
+ * From 1.0.7.2, you can use GESHI_HEADER_NONE to specify that no header code
+ * should be outputted.
+ *
+ * @param int The type of header to be used
+ * @since 1.0.0
+ */
+ function set_header_type($type) {
+ //Check if we got a valid header type
+ if (!in_array($type, array(GESHI_HEADER_NONE, GESHI_HEADER_DIV,
+ GESHI_HEADER_PRE, GESHI_HEADER_PRE_VALID, GESHI_HEADER_PRE_TABLE))) {
+ $this->error = GESHI_ERROR_INVALID_HEADER_TYPE;
+ return;
+ }
+
+ //Set that new header type
+ $this->header_type = $type;
+ }
+
+ /**
+ * Sets the styles for the code that will be outputted
+ * when this object is parsed. The style should be a
+ * string of valid stylesheet declarations
+ *
+ * @param string The overall style for the outputted code block
+ * @param boolean Whether to merge the styles with the current styles or not
+ * @since 1.0.0
+ */
+ function set_overall_style($style, $preserve_defaults = false) {
+ if (!$preserve_defaults) {
+ $this->overall_style = $style;
+ } else {
+ $this->overall_style .= $style;
+ }
+ }
+
+ /**
+ * Sets the overall classname for this block of code. This
+ * class can then be used in a stylesheet to style this object's
+ * output
+ *
+ * @param string The class name to use for this block of code
+ * @since 1.0.0
+ */
+ function set_overall_class($class) {
+ $this->overall_class = $class;
+ }
+
+ /**
+ * Sets the overall id for this block of code. This id can then
+ * be used in a stylesheet to style this object's output
+ *
+ * @param string The ID to use for this block of code
+ * @since 1.0.0
+ */
+ function set_overall_id($id) {
+ $this->overall_id = $id;
+ }
+
+ /**
+ * Sets whether CSS classes should be used to highlight the source. Default
+ * is off, calling this method with no arguments will turn it on
+ *
+ * @param boolean Whether to turn classes on or not
+ * @since 1.0.0
+ */
+ function enable_classes($flag = true) {
+ $this->use_classes = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets the style for the actual code. This should be a string
+ * containing valid stylesheet declarations. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * Note: Use this method to override any style changes you made to
+ * the line numbers if you are using line numbers, else the line of
+ * code will have the same style as the line number! Consult the
+ * GeSHi documentation for more information about this.
+ *
+ * @param string The style to use for actual code
+ * @param boolean Whether to merge the current styles with the new styles
+ * @since 1.0.2
+ */
+ function set_code_style($style, $preserve_defaults = false) {
+ if (!$preserve_defaults) {
+ $this->code_style = $style;
+ } else {
+ $this->code_style .= $style;
+ }
+ }
+
+ /**
+ * Sets the styles for the line numbers.
+ *
+ * @param string The style for the line numbers that are "normal"
+ * @param string|boolean If a string, this is the style of the line
+ * numbers that are "fancy", otherwise if boolean then this
+ * defines whether the normal styles should be merged with the
+ * new normal styles or not
+ * @param boolean If set, is the flag for whether to merge the "fancy"
+ * styles with the current styles or not
+ * @since 1.0.2
+ */
+ function set_line_style($style1, $style2 = '', $preserve_defaults = false) {
+ //Check if we got 2 or three parameters
+ if (is_bool($style2)) {
+ $preserve_defaults = $style2;
+ $style2 = '';
+ }
+
+ //Actually set the new styles
+ if (!$preserve_defaults) {
+ $this->line_style1 = $style1;
+ $this->line_style2 = $style2;
+ } else {
+ $this->line_style1 .= $style1;
+ $this->line_style2 .= $style2;
+ }
+ }
+
+ /**
+ * Sets whether line numbers should be displayed.
+ *
+ * Valid values for the first parameter are:
+ *
+ * - GESHI_NO_LINE_NUMBERS: Line numbers will not be displayed
+ * - GESHI_NORMAL_LINE_NUMBERS: Line numbers will be displayed
+ * - GESHI_FANCY_LINE_NUMBERS: Fancy line numbers will be displayed
+ *
+ * For fancy line numbers, the second parameter is used to signal which lines
+ * are to be fancy. For example, if the value of this parameter is 5 then every
+ * 5th line will be fancy.
+ *
+ * @param int How line numbers should be displayed
+ * @param int Defines which lines are fancy
+ * @since 1.0.0
+ */
+ function enable_line_numbers($flag, $nth_row = 5) {
+ if (GESHI_NO_LINE_NUMBERS != $flag && GESHI_NORMAL_LINE_NUMBERS != $flag
+ && GESHI_FANCY_LINE_NUMBERS != $flag) {
+ $this->error = GESHI_ERROR_INVALID_LINE_NUMBER_TYPE;
+ }
+ $this->line_numbers = $flag;
+ $this->line_nth_row = $nth_row;
+ }
+
+ /**
+ * Sets wether spans and other HTML markup generated by GeSHi can
+ * span over multiple lines or not. Defaults to true to reduce overhead.
+ * Set it to false if you want to manipulate the output or manually display
+ * the code in an ordered list.
+ *
+ * @param boolean Wether multiline spans are allowed or not
+ * @since 1.0.7.22
+ */
+ function enable_multiline_span($flag) {
+ $this->allow_multiline_span = (bool) $flag;
+ }
+
+ /**
+ * Get current setting for multiline spans, see GeSHi->enable_multiline_span().
+ *
+ * @see enable_multiline_span
+ * @return bool
+ */
+ function get_multiline_span() {
+ return $this->allow_multiline_span;
+ }
+
+ /**
+ * Sets the style for a keyword group. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param int The key of the keyword group to change the styles of
+ * @param string The style to make the keywords
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @since 1.0.0
+ */
+ function set_keyword_group_style($key, $style, $preserve_defaults = false) {
+ //Set the style for this keyword group
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['KEYWORDS'][$key] = $style;
+ } else {
+ $this->language_data['STYLES']['KEYWORDS'][$key] .= $style;
+ }
+
+ //Update the lexic permissions
+ if (!isset($this->lexic_permissions['KEYWORDS'][$key])) {
+ $this->lexic_permissions['KEYWORDS'][$key] = true;
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for a keyword group
+ *
+ * @param int The key of the keyword group to turn on or off
+ * @param boolean Whether to turn highlighting for that group on or off
+ * @since 1.0.0
+ */
+ function set_keyword_group_highlighting($key, $flag = true) {
+ $this->lexic_permissions['KEYWORDS'][$key] = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets the styles for comment groups. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param int The key of the comment group to change the styles of
+ * @param string The style to make the comments
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @since 1.0.0
+ */
+ function set_comments_style($key, $style, $preserve_defaults = false) {
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['COMMENTS'][$key] = $style;
+ } else {
+ $this->language_data['STYLES']['COMMENTS'][$key] .= $style;
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for comment groups
+ *
+ * @param int The key of the comment group to turn on or off
+ * @param boolean Whether to turn highlighting for that group on or off
+ * @since 1.0.0
+ */
+ function set_comments_highlighting($key, $flag = true) {
+ $this->lexic_permissions['COMMENTS'][$key] = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets the styles for escaped characters. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param string The style to make the escape characters
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @since 1.0.0
+ */
+ function set_escape_characters_style($style, $preserve_defaults = false, $group = 0) {
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['ESCAPE_CHAR'][$group] = $style;
+ } else {
+ $this->language_data['STYLES']['ESCAPE_CHAR'][$group] .= $style;
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for escaped characters
+ *
+ * @param boolean Whether to turn highlighting for escape characters on or off
+ * @since 1.0.0
+ */
+ function set_escape_characters_highlighting($flag = true) {
+ $this->lexic_permissions['ESCAPE_CHAR'] = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets the styles for brackets. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * This method is DEPRECATED: use set_symbols_style instead.
+ * This method will be removed in 1.2.X
+ *
+ * @param string The style to make the brackets
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @since 1.0.0
+ * @deprecated In favour of set_symbols_style
+ */
+ function set_brackets_style($style, $preserve_defaults = false) {
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['BRACKETS'][0] = $style;
+ } else {
+ $this->language_data['STYLES']['BRACKETS'][0] .= $style;
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for brackets
+ *
+ * This method is DEPRECATED: use set_symbols_highlighting instead.
+ * This method will be remove in 1.2.X
+ *
+ * @param boolean Whether to turn highlighting for brackets on or off
+ * @since 1.0.0
+ * @deprecated In favour of set_symbols_highlighting
+ */
+ function set_brackets_highlighting($flag) {
+ $this->lexic_permissions['BRACKETS'] = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets the styles for symbols. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param string The style to make the symbols
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @param int Tells the group of symbols for which style should be set.
+ * @since 1.0.1
+ */
+ function set_symbols_style($style, $preserve_defaults = false, $group = 0) {
+ // Update the style of symbols
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['SYMBOLS'][$group] = $style;
+ } else {
+ $this->language_data['STYLES']['SYMBOLS'][$group] .= $style;
+ }
+
+ // For backward compatibility
+ if (0 == $group) {
+ $this->set_brackets_style ($style, $preserve_defaults);
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for symbols
+ *
+ * @param boolean Whether to turn highlighting for symbols on or off
+ * @since 1.0.0
+ */
+ function set_symbols_highlighting($flag) {
+ // Update lexic permissions for this symbol group
+ $this->lexic_permissions['SYMBOLS'] = ($flag) ? true : false;
+
+ // For backward compatibility
+ $this->set_brackets_highlighting ($flag);
+ }
+
+ /**
+ * Sets the styles for strings. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param string The style to make the escape characters
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @param int Tells the group of strings for which style should be set.
+ * @since 1.0.0
+ */
+ function set_strings_style($style, $preserve_defaults = false, $group = 0) {
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['STRINGS'][$group] = $style;
+ } else {
+ $this->language_data['STYLES']['STRINGS'][$group] .= $style;
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for strings
+ *
+ * @param boolean Whether to turn highlighting for strings on or off
+ * @since 1.0.0
+ */
+ function set_strings_highlighting($flag) {
+ $this->lexic_permissions['STRINGS'] = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets the styles for strict code blocks. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param string The style to make the script blocks
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @param int Tells the group of script blocks for which style should be set.
+ * @since 1.0.8.4
+ */
+ function set_script_style($style, $preserve_defaults = false, $group = 0) {
+ // Update the style of symbols
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['SCRIPT'][$group] = $style;
+ } else {
+ $this->language_data['STYLES']['SCRIPT'][$group] .= $style;
+ }
+ }
+
+ /**
+ * Sets the styles for numbers. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param string The style to make the numbers
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @param int Tells the group of numbers for which style should be set.
+ * @since 1.0.0
+ */
+ function set_numbers_style($style, $preserve_defaults = false, $group = 0) {
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['NUMBERS'][$group] = $style;
+ } else {
+ $this->language_data['STYLES']['NUMBERS'][$group] .= $style;
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for numbers
+ *
+ * @param boolean Whether to turn highlighting for numbers on or off
+ * @since 1.0.0
+ */
+ function set_numbers_highlighting($flag) {
+ $this->lexic_permissions['NUMBERS'] = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets the styles for methods. $key is a number that references the
+ * appropriate "object splitter" - see the language file for the language
+ * you are highlighting to get this number. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param int The key of the object splitter to change the styles of
+ * @param string The style to make the methods
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @since 1.0.0
+ */
+ function set_methods_style($key, $style, $preserve_defaults = false) {
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['METHODS'][$key] = $style;
+ } else {
+ $this->language_data['STYLES']['METHODS'][$key] .= $style;
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for methods
+ *
+ * @param boolean Whether to turn highlighting for methods on or off
+ * @since 1.0.0
+ */
+ function set_methods_highlighting($flag) {
+ $this->lexic_permissions['METHODS'] = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets the styles for regexps. If $preserve_defaults is
+ * true, then styles are merged with the default styles, with the
+ * user defined styles having priority
+ *
+ * @param string The style to make the regular expression matches
+ * @param boolean Whether to merge the new styles with the old or just
+ * to overwrite them
+ * @since 1.0.0
+ */
+ function set_regexps_style($key, $style, $preserve_defaults = false) {
+ if (!$preserve_defaults) {
+ $this->language_data['STYLES']['REGEXPS'][$key] = $style;
+ } else {
+ $this->language_data['STYLES']['REGEXPS'][$key] .= $style;
+ }
+ }
+
+ /**
+ * Turns highlighting on/off for regexps
+ *
+ * @param int The key of the regular expression group to turn on or off
+ * @param boolean Whether to turn highlighting for the regular expression group on or off
+ * @since 1.0.0
+ */
+ function set_regexps_highlighting($key, $flag) {
+ $this->lexic_permissions['REGEXPS'][$key] = ($flag) ? true : false;
+ }
+
+ /**
+ * Sets whether a set of keywords are checked for in a case sensitive manner
+ *
+ * @param int The key of the keyword group to change the case sensitivity of
+ * @param boolean Whether to check in a case sensitive manner or not
+ * @since 1.0.0
+ */
+ function set_case_sensitivity($key, $case) {
+ $this->language_data['CASE_SENSITIVE'][$key] = ($case) ? true : false;
+ }
+
+ /**
+ * Sets the case that keywords should use when found. Use the constants:
+ *
+ * - GESHI_CAPS_NO_CHANGE: leave keywords as-is
+ * - GESHI_CAPS_UPPER: convert all keywords to uppercase where found
+ * - GESHI_CAPS_LOWER: convert all keywords to lowercase where found
+ *
+ * @param int A constant specifying what to do with matched keywords
+ * @since 1.0.1
+ */
+ function set_case_keywords($case) {
+ if (in_array($case, array(
+ GESHI_CAPS_NO_CHANGE, GESHI_CAPS_UPPER, GESHI_CAPS_LOWER))) {
+ $this->language_data['CASE_KEYWORDS'] = $case;
+ }
+ }
+
+ /**
+ * Sets how many spaces a tab is substituted for
+ *
+ * Widths below zero are ignored
+ *
+ * @param int The tab width
+ * @since 1.0.0
+ */
+ function set_tab_width($width) {
+ $this->tab_width = intval($width);
+
+ //Check if it fit's the constraints:
+ if ($this->tab_width < 1) {
+ //Return it to the default
+ $this->tab_width = 8;
+ }
+ }
+
+ /**
+ * Sets whether or not to use tab-stop width specifed by language
+ *
+ * @param boolean Whether to use language-specific tab-stop widths
+ * @since 1.0.7.20
+ */
+ function set_use_language_tab_width($use) {
+ $this->use_language_tab_width = (bool) $use;
+ }
+
+ /**
+ * Returns the tab width to use, based on the current language and user
+ * preference
+ *
+ * @return int Tab width
+ * @since 1.0.7.20
+ */
+ function get_real_tab_width() {
+ if (!$this->use_language_tab_width ||
+ !isset($this->language_data['TAB_WIDTH'])) {
+ return $this->tab_width;
+ } else {
+ return $this->language_data['TAB_WIDTH'];
+ }
+ }
+
+ /**
+ * Enables/disables strict highlighting. Default is off, calling this
+ * method without parameters will turn it on. See documentation
+ * for more details on strict mode and where to use it.
+ *
+ * @param boolean Whether to enable strict mode or not
+ * @since 1.0.0
+ */
+ function enable_strict_mode($mode = true) {
+ if (GESHI_MAYBE == $this->language_data['STRICT_MODE_APPLIES']) {
+ $this->strict_mode = ($mode) ? GESHI_ALWAYS : GESHI_NEVER;
+ }
+ }
+
+ /**
+ * Disables all highlighting
+ *
+ * @since 1.0.0
+ * @todo Rewrite with array traversal
+ * @deprecated In favour of enable_highlighting
+ */
+ function disable_highlighting() {
+ $this->enable_highlighting(false);
+ }
+
+ /**
+ * Enables all highlighting
+ *
+ * The optional flag parameter was added in version 1.0.7.21 and can be used
+ * to enable (true) or disable (false) all highlighting.
+ *
+ * @since 1.0.0
+ * @param boolean A flag specifying whether to enable or disable all highlighting
+ * @todo Rewrite with array traversal
+ */
+ function enable_highlighting($flag = true) {
+ $flag = $flag ? true : false;
+ foreach ($this->lexic_permissions as $key => $value) {
+ if (is_array($value)) {
+ foreach ($value as $k => $v) {
+ $this->lexic_permissions[$key][$k] = $flag;
+ }
+ } else {
+ $this->lexic_permissions[$key] = $flag;
+ }
+ }
+
+ // Context blocks
+ $this->enable_important_blocks = $flag;
+ }
+
+ /**
+ * Given a file extension, this method returns either a valid geshi language
+ * name, or the empty string if it couldn't be found
+ *
+ * @param string The extension to get a language name for
+ * @param array A lookup array to use instead of the default one
+ * @since 1.0.5
+ * @todo Re-think about how this method works (maybe make it private and/or make it
+ * a extension->lang lookup?)
+ * @todo static?
+ */
+ function get_language_name_from_extension( $extension, $lookup = array() ) {
+ $extension = strtolower($extension);
+
+ if ( !is_array($lookup) || empty($lookup)) {
+ $lookup = array(
+ '6502acme' => array( 'a', 's', 'asm', 'inc' ),
+ '6502tasm' => array( 'a', 's', 'asm', 'inc' ),
+ '6502kickass' => array( 'a', 's', 'asm', 'inc' ),
+ '68000devpac' => array( 'a', 's', 'asm', 'inc' ),
+ 'abap' => array('abap'),
+ 'actionscript' => array('as'),
+ 'ada' => array('a', 'ada', 'adb', 'ads'),
+ 'apache' => array('conf'),
+ 'asm' => array('ash', 'asm', 'inc'),
+ 'asp' => array('asp'),
+ 'bash' => array('sh'),
+ 'bf' => array('bf'),
+ 'c' => array('c', 'h'),
+ 'c_mac' => array('c', 'h'),
+ 'caddcl' => array(),
+ 'cadlisp' => array(),
+ 'cdfg' => array('cdfg'),
+ 'cobol' => array('cbl'),
+ 'cpp' => array('cpp', 'hpp', 'C', 'H', 'CPP', 'HPP'),
+ 'csharp' => array('cs'),
+ 'css' => array('css'),
+ 'd' => array('d'),
+ 'delphi' => array('dpk', 'dpr', 'pp', 'pas'),
+ 'diff' => array('diff', 'patch'),
+ 'dos' => array('bat', 'cmd'),
+ 'gdb' => array('kcrash', 'crash', 'bt'),
+ 'gettext' => array('po', 'pot'),
+ 'gml' => array('gml'),
+ 'gnuplot' => array('plt'),
+ 'groovy' => array('groovy'),
+ 'haskell' => array('hs'),
+ 'haxe' => array('hx'),
+ 'html4strict' => array('html', 'htm'),
+ 'ini' => array('ini', 'desktop'),
+ 'java' => array('java'),
+ 'javascript' => array('js'),
+ 'klonec' => array('kl1'),
+ 'klonecpp' => array('klx'),
+ 'latex' => array('tex'),
+ 'lisp' => array('lisp'),
+ 'lua' => array('lua'),
+ 'matlab' => array('m'),
+ 'mpasm' => array(),
+ 'mysql' => array('sql'),
+ 'nsis' => array(),
+ 'objc' => array(),
+ 'oobas' => array(),
+ 'oracle8' => array(),
+ 'oracle10' => array(),
+ 'pascal' => array('pas'),
+ 'perl' => array('pl', 'pm'),
+ 'php' => array('php', 'php5', 'phtml', 'phps'),
+ 'povray' => array('pov'),
+ 'providex' => array('pvc', 'pvx'),
+ 'prolog' => array('pl'),
+ 'python' => array('py'),
+ 'qbasic' => array('bi'),
+ 'reg' => array('reg'),
+ 'ruby' => array('rb'),
+ 'sas' => array('sas'),
+ 'scala' => array('scala'),
+ 'scheme' => array('scm'),
+ 'scilab' => array('sci'),
+ 'smalltalk' => array('st'),
+ 'smarty' => array(),
+ 'tcl' => array('tcl'),
+ 'text' => array('txt'),
+ 'vb' => array('bas'),
+ 'vbnet' => array(),
+ 'visualfoxpro' => array(),
+ 'whitespace' => array('ws'),
+ 'xml' => array('xml', 'svg', 'xrc'),
+ 'z80' => array('z80', 'asm', 'inc')
+ );
+ }
+
+ foreach ($lookup as $lang => $extensions) {
+ if (in_array($extension, $extensions)) {
+ return $lang;
+ }
+ }
+
+ return 'text';
+ }
+
+ /**
+ * Given a file name, this method loads its contents in, and attempts
+ * to set the language automatically. An optional lookup table can be
+ * passed for looking up the language name. If not specified a default
+ * table is used
+ *
+ * The language table is in the form
+ * <pre>array(
+ * 'lang_name' => array('extension', 'extension', ...),
+ * 'lang_name' ...
+ * );</pre>
+ *
+ * @param string The filename to load the source from
+ * @param array A lookup array to use instead of the default one
+ * @todo Complete rethink of this and above method
+ * @since 1.0.5
+ */
+ function load_from_file($file_name, $lookup = array()) {
+ if (is_readable($file_name)) {
+ $this->set_source(file_get_contents($file_name));
+ $this->set_language($this->get_language_name_from_extension(substr(strrchr($file_name, '.'), 1), $lookup));
+ } else {
+ $this->error = GESHI_ERROR_FILE_NOT_READABLE;
+ }
+ }
+
+ /**
+ * Adds a keyword to a keyword group for highlighting
+ *
+ * @param int The key of the keyword group to add the keyword to
+ * @param string The word to add to the keyword group
+ * @since 1.0.0
+ */
+ function add_keyword($key, $word) {
+ if (!is_array($this->language_data['KEYWORDS'][$key])) {
+ $this->language_data['KEYWORDS'][$key] = array();
+ }
+ if (!in_array($word, $this->language_data['KEYWORDS'][$key])) {
+ $this->language_data['KEYWORDS'][$key][] = $word;
+
+ //NEW in 1.0.8 don't recompile the whole optimized regexp, simply append it
+ if ($this->parse_cache_built) {
+ $subkey = count($this->language_data['CACHED_KEYWORD_LISTS'][$key]) - 1;
+ $this->language_data['CACHED_KEYWORD_LISTS'][$key][$subkey] .= '|' . preg_quote($word, '/');
+ }
+ }
+ }
+
+ /**
+ * Removes a keyword from a keyword group
+ *
+ * @param int The key of the keyword group to remove the keyword from
+ * @param string The word to remove from the keyword group
+ * @param bool Wether to automatically recompile the optimized regexp list or not.
+ * Note: if you set this to false and @see GeSHi->parse_code() was already called once,
+ * for the current language, you have to manually call @see GeSHi->optimize_keyword_group()
+ * or the removed keyword will stay in cache and still be highlighted! On the other hand
+ * it might be too expensive to recompile the regexp list for every removal if you want to
+ * remove a lot of keywords.
+ * @since 1.0.0
+ */
+ function remove_keyword($key, $word, $recompile = true) {
+ $key_to_remove = array_search($word, $this->language_data['KEYWORDS'][$key]);
+ if ($key_to_remove !== false) {
+ unset($this->language_data['KEYWORDS'][$key][$key_to_remove]);
+
+ //NEW in 1.0.8, optionally recompile keyword group
+ if ($recompile && $this->parse_cache_built) {
+ $this->optimize_keyword_group($key);
+ }
+ }
+ }
+
+ /**
+ * Creates a new keyword group
+ *
+ * @param int The key of the keyword group to create
+ * @param string The styles for the keyword group
+ * @param boolean Whether the keyword group is case sensitive ornot
+ * @param array The words to use for the keyword group
+ * @since 1.0.0
+ */
+ function add_keyword_group($key, $styles, $case_sensitive = true, $words = array()) {
+ $words = (array) $words;
+ if (empty($words)) {
+ // empty word lists mess up highlighting
+ return false;
+ }
+
+ //Add the new keyword group internally
+ $this->language_data['KEYWORDS'][$key] = $words;
+ $this->lexic_permissions['KEYWORDS'][$key] = true;
+ $this->language_data['CASE_SENSITIVE'][$key] = $case_sensitive;
+ $this->language_data['STYLES']['KEYWORDS'][$key] = $styles;
+
+ //NEW in 1.0.8, cache keyword regexp
+ if ($this->parse_cache_built) {
+ $this->optimize_keyword_group($key);
+ }
+ }
+
+ /**
+ * Removes a keyword group
+ *
+ * @param int The key of the keyword group to remove
+ * @since 1.0.0
+ */
+ function remove_keyword_group ($key) {
+ //Remove the keyword group internally
+ unset($this->language_data['KEYWORDS'][$key]);
+ unset($this->lexic_permissions['KEYWORDS'][$key]);
+ unset($this->language_data['CASE_SENSITIVE'][$key]);
+ unset($this->language_data['STYLES']['KEYWORDS'][$key]);
+
+ //NEW in 1.0.8
+ unset($this->language_data['CACHED_KEYWORD_LISTS'][$key]);
+ }
+
+ /**
+ * compile optimized regexp list for keyword group
+ *
+ * @param int The key of the keyword group to compile & optimize
+ * @since 1.0.8
+ */
+ function optimize_keyword_group($key) {
+ $this->language_data['CACHED_KEYWORD_LISTS'][$key] =
+ $this->optimize_regexp_list($this->language_data['KEYWORDS'][$key]);
+ $space_as_whitespace = false;
+ if(isset($this->language_data['PARSER_CONTROL'])) {
+ if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
+ if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'])) {
+ $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'];
+ }
+ if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) {
+ if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) {
+ $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'];
+ }
+ }
+ }
+ }
+ if($space_as_whitespace) {
+ foreach($this->language_data['CACHED_KEYWORD_LISTS'][$key] as $rxk => $rxv) {
+ $this->language_data['CACHED_KEYWORD_LISTS'][$key][$rxk] =
+ str_replace(" ", "\\s+", $rxv);
+ }
+ }
+ }
+
+ /**
+ * Sets the content of the header block
+ *
+ * @param string The content of the header block
+ * @since 1.0.2
+ */
+ function set_header_content($content) {
+ $this->header_content = $content;
+ }
+
+ /**
+ * Sets the content of the footer block
+ *
+ * @param string The content of the footer block
+ * @since 1.0.2
+ */
+ function set_footer_content($content) {
+ $this->footer_content = $content;
+ }
+
+ /**
+ * Sets the style for the header content
+ *
+ * @param string The style for the header content
+ * @since 1.0.2
+ */
+ function set_header_content_style($style) {
+ $this->header_content_style = $style;
+ }
+
+ /**
+ * Sets the style for the footer content
+ *
+ * @param string The style for the footer content
+ * @since 1.0.2
+ */
+ function set_footer_content_style($style) {
+ $this->footer_content_style = $style;
+ }
+
+ /**
+ * Sets whether to force a surrounding block around
+ * the highlighted code or not
+ *
+ * @param boolean Tells whether to enable or disable this feature
+ * @since 1.0.7.20
+ */
+ function enable_inner_code_block($flag) {
+ $this->force_code_block = (bool)$flag;
+ }
+
+ /**
+ * Sets the base URL to be used for keywords
+ *
+ * @param int The key of the keyword group to set the URL for
+ * @param string The URL to set for the group. If {FNAME} is in
+ * the url somewhere, it is replaced by the keyword
+ * that the URL is being made for
+ * @since 1.0.2
+ */
+ function set_url_for_keyword_group($group, $url) {
+ $this->language_data['URLS'][$group] = $url;
+ }
+
+ /**
+ * Sets styles for links in code
+ *
+ * @param int A constant that specifies what state the style is being
+ * set for - e.g. :hover or :visited
+ * @param string The styles to use for that state
+ * @since 1.0.2
+ */
+ function set_link_styles($type, $styles) {
+ $this->link_styles[$type] = $styles;
+ }
+
+ /**
+ * Sets the target for links in code
+ *
+ * @param string The target for links in the code, e.g. _blank
+ * @since 1.0.3
+ */
+ function set_link_target($target) {
+ if (!$target) {
+ $this->link_target = '';
+ } else {
+ $this->link_target = ' target="' . $target . '"';
+ }
+ }
+
+ /**
+ * Sets styles for important parts of the code
+ *
+ * @param string The styles to use on important parts of the code
+ * @since 1.0.2
+ */
+ function set_important_styles($styles) {
+ $this->important_styles = $styles;
+ }
+
+ /**
+ * Sets whether context-important blocks are highlighted
+ *
+ * @param boolean Tells whether to enable or disable highlighting of important blocks
+ * @todo REMOVE THIS SHIZ FROM GESHI!
+ * @deprecated
+ * @since 1.0.2
+ */
+ function enable_important_blocks($flag) {
+ $this->enable_important_blocks = ( $flag ) ? true : false;
+ }
+
+ /**
+ * Whether CSS IDs should be added to each line
+ *
+ * @param boolean If true, IDs will be added to each line.
+ * @since 1.0.2
+ */
+ function enable_ids($flag = true) {
+ $this->add_ids = ($flag) ? true : false;
+ }
+
+ /**
+ * Specifies which lines to highlight extra
+ *
+ * The extra style parameter was added in 1.0.7.21.
+ *
+ * @param mixed An array of line numbers to highlight, or just a line
+ * number on its own.
+ * @param string A string specifying the style to use for this line.
+ * If null is specified, the default style is used.
+ * If false is specified, the line will be removed from
+ * special highlighting
+ * @since 1.0.2
+ * @todo Some data replication here that could be cut down on
+ */
+ function highlight_lines_extra($lines, $style = null) {
+ if (is_array($lines)) {
+ //Split up the job using single lines at a time
+ foreach ($lines as $line) {
+ $this->highlight_lines_extra($line, $style);
+ }
+ } else {
+ //Mark the line as being highlighted specially
+ $lines = intval($lines);
+ $this->highlight_extra_lines[$lines] = $lines;
+
+ //Decide on which style to use
+ if ($style === null) { //Check if we should use default style
+ unset($this->highlight_extra_lines_styles[$lines]);
+ } elseif ($style === false) { //Check if to remove this line
+ unset($this->highlight_extra_lines[$lines]);
+ unset($this->highlight_extra_lines_styles[$lines]);
+ } else {
+ $this->highlight_extra_lines_styles[$lines] = $style;
+ }
+ }
+ }
+
+ /**
+ * Sets the style for extra-highlighted lines
+ *
+ * @param string The style for extra-highlighted lines
+ * @since 1.0.2
+ */
+ function set_highlight_lines_extra_style($styles) {
+ $this->highlight_extra_lines_style = $styles;
+ }
+
+ /**
+ * Sets the line-ending
+ *
+ * @param string The new line-ending
+ * @since 1.0.2
+ */
+ function set_line_ending($line_ending) {
+ $this->line_ending = (string)$line_ending;
+ }
+
+ /**
+ * Sets what number line numbers should start at. Should
+ * be a positive integer, and will be converted to one.
+ *
+ * <b>Warning:</b> Using this method will add the "start"
+ * attribute to the &lt;ol&gt; that is used for line numbering.
+ * This is <b>not</b> valid XHTML strict, so if that's what you
+ * care about then don't use this method. Firefox is getting
+ * support for the CSS method of doing this in 1.1 and Opera
+ * has support for the CSS method, but (of course) IE doesn't
+ * so it's not worth doing it the CSS way yet.
+ *
+ * @param int The number to start line numbers at
+ * @since 1.0.2
+ */
+ function start_line_numbers_at($number) {
+ $this->line_numbers_start = abs(intval($number));
+ }
+
+ /**
+ * Sets the encoding used for htmlspecialchars(), for international
+ * support.
+ *
+ * NOTE: This is not needed for now because htmlspecialchars() is not
+ * being used (it has a security hole in PHP4 that has not been patched).
+ * Maybe in a future version it may make a return for speed reasons, but
+ * I doubt it.
+ *
+ * @param string The encoding to use for the source
+ * @since 1.0.3
+ */
+ function set_encoding($encoding) {
+ if ($encoding) {
+ $this->encoding = strtolower($encoding);
+ }
+ }
+
+ /**
+ * Turns linking of keywords on or off.
+ *
+ * @param boolean If true, links will be added to keywords
+ * @since 1.0.2
+ */
+ function enable_keyword_links($enable = true) {
+ $this->keyword_links = (bool) $enable;
+ }
+
+ /**
+ * Setup caches needed for styling. This is automatically called in
+ * parse_code() and get_stylesheet() when appropriate. This function helps
+ * stylesheet generators as they rely on some style information being
+ * preprocessed
+ *
+ * @since 1.0.8
+ * @access private
+ */
+ function build_style_cache() {
+ //Build the style cache needed to highlight numbers appropriate
+ if($this->lexic_permissions['NUMBERS']) {
+ //First check what way highlighting information for numbers are given
+ if(!isset($this->language_data['NUMBERS'])) {
+ $this->language_data['NUMBERS'] = 0;
+ }
+
+ if(is_array($this->language_data['NUMBERS'])) {
+ $this->language_data['NUMBERS_CACHE'] = $this->language_data['NUMBERS'];
+ } else {
+ $this->language_data['NUMBERS_CACHE'] = array();
+ if(!$this->language_data['NUMBERS']) {
+ $this->language_data['NUMBERS'] =
+ GESHI_NUMBER_INT_BASIC |
+ GESHI_NUMBER_FLT_NONSCI;
+ }
+
+ for($i = 0, $j = $this->language_data['NUMBERS']; $j > 0; ++$i, $j>>=1) {
+ //Rearrange style indices if required ...
+ if(isset($this->language_data['STYLES']['NUMBERS'][1<<$i])) {
+ $this->language_data['STYLES']['NUMBERS'][$i] =
+ $this->language_data['STYLES']['NUMBERS'][1<<$i];
+ unset($this->language_data['STYLES']['NUMBERS'][1<<$i]);
+ }
+
+ //Check if this bit is set for highlighting
+ if($j&1) {
+ //So this bit is set ...
+ //Check if it belongs to group 0 or the actual stylegroup
+ if(isset($this->language_data['STYLES']['NUMBERS'][$i])) {
+ $this->language_data['NUMBERS_CACHE'][$i] = 1 << $i;
+ } else {
+ if(!isset($this->language_data['NUMBERS_CACHE'][0])) {
+ $this->language_data['NUMBERS_CACHE'][0] = 0;
+ }
+ $this->language_data['NUMBERS_CACHE'][0] |= 1 << $i;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Setup caches needed for parsing. This is automatically called in parse_code() when appropriate.
+ * This function makes stylesheet generators much faster as they do not need these caches.
+ *
+ * @since 1.0.8
+ * @access private
+ */
+ function build_parse_cache() {
+ // cache symbol regexp
+ //As this is a costy operation, we avoid doing it for multiple groups ...
+ //Instead we perform it for all symbols at once.
+ //
+ //For this to work, we need to reorganize the data arrays.
+ if ($this->lexic_permissions['SYMBOLS'] && !empty($this->language_data['SYMBOLS'])) {
+ $this->language_data['MULTIPLE_SYMBOL_GROUPS'] = count($this->language_data['STYLES']['SYMBOLS']) > 1;
+
+ $this->language_data['SYMBOL_DATA'] = array();
+ $symbol_preg_multi = array(); // multi char symbols
+ $symbol_preg_single = array(); // single char symbols
+ foreach ($this->language_data['SYMBOLS'] as $key => $symbols) {
+ if (is_array($symbols)) {
+ foreach ($symbols as $sym) {
+ $sym = $this->hsc($sym);
+ if (!isset($this->language_data['SYMBOL_DATA'][$sym])) {
+ $this->language_data['SYMBOL_DATA'][$sym] = $key;
+ if (isset($sym[1])) { // multiple chars
+ $symbol_preg_multi[] = preg_quote($sym, '/');
+ } else { // single char
+ if ($sym == '-') {
+ // don't trigger range out of order error
+ $symbol_preg_single[] = '\-';
+ } else {
+ $symbol_preg_single[] = preg_quote($sym, '/');
+ }
+ }
+ }
+ }
+ } else {
+ $symbols = $this->hsc($symbols);
+ if (!isset($this->language_data['SYMBOL_DATA'][$symbols])) {
+ $this->language_data['SYMBOL_DATA'][$symbols] = 0;
+ if (isset($symbols[1])) { // multiple chars
+ $symbol_preg_multi[] = preg_quote($symbols, '/');
+ } elseif ($symbols == '-') {
+ // don't trigger range out of order error
+ $symbol_preg_single[] = '\-';
+ } else { // single char
+ $symbol_preg_single[] = preg_quote($symbols, '/');
+ }
+ }
+ }
+ }
+
+ //Now we have an array with each possible symbol as the key and the style as the actual data.
+ //This way we can set the correct style just the moment we highlight ...
+ //
+ //Now we need to rewrite our array to get a search string that
+ $symbol_preg = array();
+ if (!empty($symbol_preg_multi)) {
+ rsort($symbol_preg_multi);
+ $symbol_preg[] = implode('|', $symbol_preg_multi);
+ }
+ if (!empty($symbol_preg_single)) {
+ rsort($symbol_preg_single);
+ $symbol_preg[] = '[' . implode('', $symbol_preg_single) . ']';
+ }
+ $this->language_data['SYMBOL_SEARCH'] = implode("|", $symbol_preg);
+ }
+
+ // cache optimized regexp for keyword matching
+ // remove old cache
+ $this->language_data['CACHED_KEYWORD_LISTS'] = array();
+ foreach (array_keys($this->language_data['KEYWORDS']) as $key) {
+ if (!isset($this->lexic_permissions['KEYWORDS'][$key]) ||
+ $this->lexic_permissions['KEYWORDS'][$key]) {
+ $this->optimize_keyword_group($key);
+ }
+ }
+
+ // brackets
+ if ($this->lexic_permissions['BRACKETS']) {
+ $this->language_data['CACHE_BRACKET_MATCH'] = array('[', ']', '(', ')', '{', '}');
+ if (!$this->use_classes && isset($this->language_data['STYLES']['BRACKETS'][0])) {
+ $this->language_data['CACHE_BRACKET_REPLACE'] = array(
+ '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#91;|>',
+ '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#93;|>',
+ '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#40;|>',
+ '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#41;|>',
+ '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#123;|>',
+ '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">&#125;|>',
+ );
+ }
+ else {
+ $this->language_data['CACHE_BRACKET_REPLACE'] = array(
+ '<| class="br0">&#91;|>',
+ '<| class="br0">&#93;|>',
+ '<| class="br0">&#40;|>',
+ '<| class="br0">&#41;|>',
+ '<| class="br0">&#123;|>',
+ '<| class="br0">&#125;|>',
+ );
+ }
+ }
+
+ //Build the parse cache needed to highlight numbers appropriate
+ if($this->lexic_permissions['NUMBERS']) {
+ //Check if the style rearrangements have been processed ...
+ //This also does some preprocessing to check which style groups are useable ...
+ if(!isset($this->language_data['NUMBERS_CACHE'])) {
+ $this->build_style_cache();
+ }
+
+ //Number format specification
+ //All this formats are matched case-insensitively!
+ static $numbers_format = array(
+ GESHI_NUMBER_INT_BASIC =>
+ '(?:(?<![0-9a-z_\.%$@])|(?<=\.\.))(?<![\d\.]e[+\-])([1-9]\d*?|0)(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_INT_CSTYLE =>
+ '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])([1-9]\d*?|0)l(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_BIN_SUFFIX =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])[01]+?[bB](?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_BIN_PREFIX_PERCENT =>
+ '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])%[01]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_BIN_PREFIX_0B =>
+ '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])0b[01]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_OCT_PREFIX =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])0[0-7]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_OCT_PREFIX_0O =>
+ '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])0o[0-7]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_OCT_PREFIX_AT =>
+ '(?<![0-9a-z_\.%])(?<![\d\.]e[+\-])\@[0-7]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_OCT_SUFFIX =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])[0-7]+?o(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_HEX_PREFIX =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])0x[0-9a-fA-F]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_HEX_PREFIX_DOLLAR =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\$[0-9a-fA-F]+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_HEX_SUFFIX =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\d[0-9a-fA-F]*?[hH](?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_FLT_NONSCI =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\d+?\.\d+?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_FLT_NONSCI_F =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])(?:\d+?(?:\.\d*?)?|\.\d+?)f(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_FLT_SCI_SHORT =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])\.\d+?(?:e[+\-]?\d+?)?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)',
+ GESHI_NUMBER_FLT_SCI_ZERO =>
+ '(?<![0-9a-z_\.])(?<![\d\.]e[+\-])(?:\d+?(?:\.\d*?)?|\.\d+?)(?:e[+\-]?\d+?)?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)'
+ );
+
+ //At this step we have an associative array with flag groups for a
+ //specific style or an string denoting a regexp given its index.
+ $this->language_data['NUMBERS_RXCACHE'] = array();
+ foreach($this->language_data['NUMBERS_CACHE'] as $key => $rxdata) {
+ if(is_string($rxdata)) {
+ $regexp = $rxdata;
+ } else {
+ //This is a bitfield of number flags to highlight:
+ //Build an array, implode them together and make this the actual RX
+ $rxuse = array();
+ for($i = 1; $i <= $rxdata; $i<<=1) {
+ if($rxdata & $i) {
+ $rxuse[] = $numbers_format[$i];
+ }
+ }
+ $regexp = implode("|", $rxuse);
+ }
+
+ $this->language_data['NUMBERS_RXCACHE'][$key] =
+ "/(?<!<\|\/)(?<!<\|!REG3XP)(?<!<\|\/NUM!)(?<!\d\/>)($regexp)(?!(?:<DOT>|(?>[^\<]))+>)(?![^<]*>)(?!\|>)(?!\/>)/i"; //
+ }
+
+ if(!isset($this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'])) {
+ $this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'] = '#\d#';
+ }
+ }
+
+ $this->parse_cache_built = true;
+ }
+
+ /**
+ * Returns the code in $this->source, highlighted and surrounded by the
+ * nessecary HTML.
+ *
+ * This should only be called ONCE, cos it's SLOW! If you want to highlight
+ * the same source multiple times, you're better off doing a whole lot of
+ * str_replaces to replace the &lt;span&gt;s
+ *
+ * @since 1.0.0
+ */
+ function parse_code () {
+ // Start the timer
+ $start_time = microtime();
+
+ // Replace all newlines to a common form.
+ $code = str_replace("\r\n", "\n", $this->source);
+ $code = str_replace("\r", "\n", $code);
+
+ // Firstly, if there is an error, we won't highlight
+ if ($this->error) {
+ //Escape the source for output
+ $result = $this->hsc($this->source);
+
+ //This fix is related to SF#1923020, but has to be applied regardless of
+ //actually highlighting symbols.
+ $result = str_replace(array('<SEMI>', '<PIPE>'), array(';', '|'), $result);
+
+ // Timing is irrelevant
+ $this->set_time($start_time, $start_time);
+ $this->finalise($result);
+ return $result;
+ }
+
+ // make sure the parse cache is up2date
+ if (!$this->parse_cache_built) {
+ $this->build_parse_cache();
+ }
+
+ // Initialise various stuff
+ $length = strlen($code);
+ $COMMENT_MATCHED = false;
+ $stuff_to_parse = '';
+ $endresult = '';
+
+ // "Important" selections are handled like multiline comments
+ // @todo GET RID OF THIS SHIZ
+ if ($this->enable_important_blocks) {
+ $this->language_data['COMMENT_MULTI'][GESHI_START_IMPORTANT] = GESHI_END_IMPORTANT;
+ }
+
+ if ($this->strict_mode) {
+ // Break the source into bits. Each bit will be a portion of the code
+ // within script delimiters - for example, HTML between < and >
+ $k = 0;
+ $parts = array();
+ $matches = array();
+ $next_match_pointer = null;
+ // we use a copy to unset delimiters on demand (when they are not found)
+ $delim_copy = $this->language_data['SCRIPT_DELIMITERS'];
+ $i = 0;
+ while ($i < $length) {
+ $next_match_pos = $length + 1; // never true
+ foreach ($delim_copy as $dk => $delimiters) {
+ if(is_array($delimiters)) {
+ foreach ($delimiters as $open => $close) {
+ // make sure the cache is setup properly
+ if (!isset($matches[$dk][$open])) {
+ $matches[$dk][$open] = array(
+ 'next_match' => -1,
+ 'dk' => $dk,
+
+ 'open' => $open, // needed for grouping of adjacent code blocks (see below)
+ 'open_strlen' => strlen($open),
+
+ 'close' => $close,
+ 'close_strlen' => strlen($close),
+ );
+ }
+ // Get the next little bit for this opening string
+ if ($matches[$dk][$open]['next_match'] < $i) {
+ // only find the next pos if it was not already cached
+ $open_pos = strpos($code, $open, $i);
+ if ($open_pos === false) {
+ // no match for this delimiter ever
+ unset($delim_copy[$dk][$open]);
+ continue;
+ }
+ $matches[$dk][$open]['next_match'] = $open_pos;
+ }
+ if ($matches[$dk][$open]['next_match'] < $next_match_pos) {
+ //So we got a new match, update the close_pos
+ $matches[$dk][$open]['close_pos'] =
+ strpos($code, $close, $matches[$dk][$open]['next_match']+1);
+
+ $next_match_pointer =& $matches[$dk][$open];
+ $next_match_pos = $matches[$dk][$open]['next_match'];
+ }
+ }
+ } else {
+ //So we should match an RegExp as Strict Block ...
+ /**
+ * The value in $delimiters is expected to be an RegExp
+ * containing exactly 2 matching groups:
+ * - Group 1 is the opener
+ * - Group 2 is the closer
+ */
+ if(!GESHI_PHP_PRE_433 && //Needs proper rewrite to work with PHP >=4.3.0; 4.3.3 is guaranteed to work.
+ preg_match($delimiters, $code, $matches_rx, PREG_OFFSET_CAPTURE, $i)) {
+ //We got a match ...
+ if(isset($matches_rx['start']) && isset($matches_rx['end']))
+ {
+ $matches[$dk] = array(
+ 'next_match' => $matches_rx['start'][1],
+ 'dk' => $dk,
+
+ 'close_strlen' => strlen($matches_rx['end'][0]),
+ 'close_pos' => $matches_rx['end'][1],
+ );
+ } else {
+ $matches[$dk] = array(
+ 'next_match' => $matches_rx[1][1],
+ 'dk' => $dk,
+
+ 'close_strlen' => strlen($matches_rx[2][0]),
+ 'close_pos' => $matches_rx[2][1],
+ );
+ }
+ } else {
+ // no match for this delimiter ever
+ unset($delim_copy[$dk]);
+ continue;
+ }
+
+ if ($matches[$dk]['next_match'] <= $next_match_pos) {
+ $next_match_pointer =& $matches[$dk];
+ $next_match_pos = $matches[$dk]['next_match'];
+ }
+ }
+ }
+
+ // non-highlightable text
+ $parts[$k] = array(
+ 1 => substr($code, $i, $next_match_pos - $i)
+ );
+ ++$k;
+
+ if ($next_match_pos > $length) {
+ // out of bounds means no next match was found
+ break;
+ }
+
+ // highlightable code
+ $parts[$k][0] = $next_match_pointer['dk'];
+
+ //Only combine for non-rx script blocks
+ if(is_array($delim_copy[$next_match_pointer['dk']])) {
+ // group adjacent script blocks, e.g. <foobar><asdf> should be one block, not three!
+ $i = $next_match_pos + $next_match_pointer['open_strlen'];
+ while (true) {
+ $close_pos = strpos($code, $next_match_pointer['close'], $i);
+ if ($close_pos == false) {
+ break;
+ }
+ $i = $close_pos + $next_match_pointer['close_strlen'];
+ if ($i == $length) {
+ break;
+ }
+ if ($code[$i] == $next_match_pointer['open'][0] && ($next_match_pointer['open_strlen'] == 1 ||
+ substr($code, $i, $next_match_pointer['open_strlen']) == $next_match_pointer['open'])) {
+ // merge adjacent but make sure we don't merge things like <tag><!-- comment -->
+ foreach ($matches as $submatches) {
+ foreach ($submatches as $match) {
+ if ($match['next_match'] == $i) {
+ // a different block already matches here!
+ break 3;
+ }
+ }
+ }
+ } else {
+ break;
+ }
+ }
+ } else {
+ $close_pos = $next_match_pointer['close_pos'] + $next_match_pointer['close_strlen'];
+ $i = $close_pos;
+ }
+
+ if ($close_pos === false) {
+ // no closing delimiter found!
+ $parts[$k][1] = substr($code, $next_match_pos);
+ ++$k;
+ break;
+ } else {
+ $parts[$k][1] = substr($code, $next_match_pos, $i - $next_match_pos);
+ ++$k;
+ }
+ }
+ unset($delim_copy, $next_match_pointer, $next_match_pos, $matches);
+ $num_parts = $k;
+
+ if ($num_parts == 1 && $this->strict_mode == GESHI_MAYBE) {
+ // when we have only one part, we don't have anything to highlight at all.
+ // if we have a "maybe" strict language, this should be handled as highlightable code
+ $parts = array(
+ 0 => array(
+ 0 => '',
+ 1 => ''
+ ),
+ 1 => array(
+ 0 => null,
+ 1 => $parts[0][1]
+ )
+ );
+ $num_parts = 2;
+ }
+
+ } else {
+ // Not strict mode - simply dump the source into
+ // the array at index 1 (the first highlightable block)
+ $parts = array(
+ 0 => array(
+ 0 => '',
+ 1 => ''
+ ),
+ 1 => array(
+ 0 => null,
+ 1 => $code
+ )
+ );
+ $num_parts = 2;
+ }
+
+ //Unset variables we won't need any longer
+ unset($code);
+
+ //Preload some repeatedly used values regarding hardquotes ...
+ $hq = isset($this->language_data['HARDQUOTE']) ? $this->language_data['HARDQUOTE'][0] : false;
+ $hq_strlen = strlen($hq);
+
+ //Preload if line numbers are to be generated afterwards
+ //Added a check if line breaks should be forced even without line numbers, fixes SF#1727398
+ $check_linenumbers = $this->line_numbers != GESHI_NO_LINE_NUMBERS ||
+ !empty($this->highlight_extra_lines) || !$this->allow_multiline_span;
+
+ //preload the escape char for faster checking ...
+ $escaped_escape_char = $this->hsc($this->language_data['ESCAPE_CHAR']);
+
+ // this is used for single-line comments
+ $sc_disallowed_before = "";
+ $sc_disallowed_after = "";
+
+ if (isset($this->language_data['PARSER_CONTROL'])) {
+ if (isset($this->language_data['PARSER_CONTROL']['COMMENTS'])) {
+ if (isset($this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_BEFORE'])) {
+ $sc_disallowed_before = $this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_BEFORE'];
+ }
+ if (isset($this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_AFTER'])) {
+ $sc_disallowed_after = $this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_AFTER'];
+ }
+ }
+ }
+
+ //Fix for SF#1932083: Multichar Quotemarks unsupported
+ $is_string_starter = array();
+ if ($this->lexic_permissions['STRINGS']) {
+ foreach ($this->language_data['QUOTEMARKS'] as $quotemark) {
+ if (!isset($is_string_starter[$quotemark[0]])) {
+ $is_string_starter[$quotemark[0]] = (string)$quotemark;
+ } elseif (is_string($is_string_starter[$quotemark[0]])) {
+ $is_string_starter[$quotemark[0]] = array(
+ $is_string_starter[$quotemark[0]],
+ $quotemark);
+ } else {
+ $is_string_starter[$quotemark[0]][] = $quotemark;
+ }
+ }
+ }
+
+ // Now we go through each part. We know that even-indexed parts are
+ // code that shouldn't be highlighted, and odd-indexed parts should
+ // be highlighted
+ for ($key = 0; $key < $num_parts; ++$key) {
+ $STRICTATTRS = '';
+
+ // If this block should be highlighted...
+ if (!($key & 1)) {
+ // Else not a block to highlight
+ $endresult .= $this->hsc($parts[$key][1]);
+ unset($parts[$key]);
+ continue;
+ }
+
+ $result = '';
+ $part = $parts[$key][1];
+
+ $highlight_part = true;
+ if ($this->strict_mode && !is_null($parts[$key][0])) {
+ // get the class key for this block of code
+ $script_key = $parts[$key][0];
+ $highlight_part = $this->language_data['HIGHLIGHT_STRICT_BLOCK'][$script_key];
+ if ($this->language_data['STYLES']['SCRIPT'][$script_key] != '' &&
+ $this->lexic_permissions['SCRIPT']) {
+ // Add a span element around the source to
+ // highlight the overall source block
+ if (!$this->use_classes &&
+ $this->language_data['STYLES']['SCRIPT'][$script_key] != '') {
+ $attributes = ' style="' . $this->language_data['STYLES']['SCRIPT'][$script_key] . '"';
+ } else {
+ $attributes = ' class="sc' . $script_key . '"';
+ }
+ $result .= "<span$attributes>";
+ $STRICTATTRS = $attributes;
+ }
+ }
+
+ if ($highlight_part) {
+ // Now, highlight the code in this block. This code
+ // is really the engine of GeSHi (along with the method
+ // parse_non_string_part).
+
+ // cache comment regexps incrementally
+ $next_comment_regexp_key = '';
+ $next_comment_regexp_pos = -1;
+ $next_comment_multi_pos = -1;
+ $next_comment_single_pos = -1;
+ $comment_regexp_cache_per_key = array();
+ $comment_multi_cache_per_key = array();
+ $comment_single_cache_per_key = array();
+ $next_open_comment_multi = '';
+ $next_comment_single_key = '';
+ $escape_regexp_cache_per_key = array();
+ $next_escape_regexp_key = '';
+ $next_escape_regexp_pos = -1;
+
+ $length = strlen($part);
+ for ($i = 0; $i < $length; ++$i) {
+ // Get the next char
+ $char = $part[$i];
+ $char_len = 1;
+
+ // update regexp comment cache if needed
+ if (isset($this->language_data['COMMENT_REGEXP']) && $next_comment_regexp_pos < $i) {
+ $next_comment_regexp_pos = $length;
+ foreach ($this->language_data['COMMENT_REGEXP'] as $comment_key => $regexp) {
+ $match_i = false;
+ if (isset($comment_regexp_cache_per_key[$comment_key]) &&
+ ($comment_regexp_cache_per_key[$comment_key]['pos'] >= $i ||
+ $comment_regexp_cache_per_key[$comment_key]['pos'] === false)) {
+ // we have already matched something
+ if ($comment_regexp_cache_per_key[$comment_key]['pos'] === false) {
+ // this comment is never matched
+ continue;
+ }
+ $match_i = $comment_regexp_cache_per_key[$comment_key]['pos'];
+ } elseif (
+ //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible
+ (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $i), $match, PREG_OFFSET_CAPTURE)) ||
+ (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $i))
+ ) {
+ $match_i = $match[0][1];
+ if (GESHI_PHP_PRE_433) {
+ $match_i += $i;
+ }
+
+ $comment_regexp_cache_per_key[$comment_key] = array(
+ 'key' => $comment_key,
+ 'length' => strlen($match[0][0]),
+ 'pos' => $match_i
+ );
+ } else {
+ $comment_regexp_cache_per_key[$comment_key]['pos'] = false;
+ continue;
+ }
+
+ if ($match_i !== false && $match_i < $next_comment_regexp_pos) {
+ $next_comment_regexp_pos = $match_i;
+ $next_comment_regexp_key = $comment_key;
+ if ($match_i === $i) {
+ break;
+ }
+ }
+ }
+ }
+
+ $string_started = false;
+
+ if (isset($is_string_starter[$char])) {
+ // Possibly the start of a new string ...
+
+ //Check which starter it was ...
+ //Fix for SF#1932083: Multichar Quotemarks unsupported
+ if (is_array($is_string_starter[$char])) {
+ $char_new = '';
+ foreach ($is_string_starter[$char] as $testchar) {
+ if ($testchar === substr($part, $i, strlen($testchar)) &&
+ strlen($testchar) > strlen($char_new)) {
+ $char_new = $testchar;
+ $string_started = true;
+ }
+ }
+ if ($string_started) {
+ $char = $char_new;
+ }
+ } else {
+ $testchar = $is_string_starter[$char];
+ if ($testchar === substr($part, $i, strlen($testchar))) {
+ $char = $testchar;
+ $string_started = true;
+ }
+ }
+ $char_len = strlen($char);
+ }
+
+ if ($string_started && ($i != $next_comment_regexp_pos)) {
+ // Hand out the correct style information for this string
+ $string_key = array_search($char, $this->language_data['QUOTEMARKS']);
+ if (!isset($this->language_data['STYLES']['STRINGS'][$string_key]) ||
+ !isset($this->language_data['STYLES']['ESCAPE_CHAR'][$string_key])) {
+ $string_key = 0;
+ }
+
+ // parse the stuff before this
+ $result .= $this->parse_non_string_part($stuff_to_parse);
+ $stuff_to_parse = '';
+
+ if (!$this->use_classes) {
+ $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS'][$string_key] . '"';
+ } else {
+ $string_attributes = ' class="st'.$string_key.'"';
+ }
+
+ // now handle the string
+ $string = "<span$string_attributes>" . GeSHi::hsc($char);
+ $start = $i + $char_len;
+ $string_open = true;
+
+ if(empty($this->language_data['ESCAPE_REGEXP'])) {
+ $next_escape_regexp_pos = $length;
+ }
+
+ do {
+ //Get the regular ending pos ...
+ $close_pos = strpos($part, $char, $start);
+ if(false === $close_pos) {
+ $close_pos = $length;
+ }
+
+ if($this->lexic_permissions['ESCAPE_CHAR']) {
+ // update escape regexp cache if needed
+ if (isset($this->language_data['ESCAPE_REGEXP']) && $next_escape_regexp_pos < $start) {
+ $next_escape_regexp_pos = $length;
+ foreach ($this->language_data['ESCAPE_REGEXP'] as $escape_key => $regexp) {
+ $match_i = false;
+ if (isset($escape_regexp_cache_per_key[$escape_key]) &&
+ ($escape_regexp_cache_per_key[$escape_key]['pos'] >= $start ||
+ $escape_regexp_cache_per_key[$escape_key]['pos'] === false)) {
+ // we have already matched something
+ if ($escape_regexp_cache_per_key[$escape_key]['pos'] === false) {
+ // this comment is never matched
+ continue;
+ }
+ $match_i = $escape_regexp_cache_per_key[$escape_key]['pos'];
+ } elseif (
+ //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible
+ (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $start), $match, PREG_OFFSET_CAPTURE)) ||
+ (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $start))
+ ) {
+ $match_i = $match[0][1];
+ if (GESHI_PHP_PRE_433) {
+ $match_i += $start;
+ }
+
+ $escape_regexp_cache_per_key[$escape_key] = array(
+ 'key' => $escape_key,
+ 'length' => strlen($match[0][0]),
+ 'pos' => $match_i
+ );
+ } else {
+ $escape_regexp_cache_per_key[$escape_key]['pos'] = false;
+ continue;
+ }
+
+ if ($match_i !== false && $match_i < $next_escape_regexp_pos) {
+ $next_escape_regexp_pos = $match_i;
+ $next_escape_regexp_key = $escape_key;
+ if ($match_i === $start) {
+ break;
+ }
+ }
+ }
+ }
+
+ //Find the next simple escape position
+ if('' != $this->language_data['ESCAPE_CHAR']) {
+ $simple_escape = strpos($part, $this->language_data['ESCAPE_CHAR'], $start);
+ if(false === $simple_escape) {
+ $simple_escape = $length;
+ }
+ } else {
+ $simple_escape = $length;
+ }
+ } else {
+ $next_escape_regexp_pos = $length;
+ $simple_escape = $length;
+ }
+
+ if($simple_escape < $next_escape_regexp_pos &&
+ $simple_escape < $length &&
+ $simple_escape < $close_pos) {
+ //The nexxt escape sequence is a simple one ...
+ $es_pos = $simple_escape;
+
+ //Add the stuff not in the string yet ...
+ $string .= $this->hsc(substr($part, $start, $es_pos - $start));
+
+ //Get the style for this escaped char ...
+ if (!$this->use_classes) {
+ $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][0] . '"';
+ } else {
+ $escape_char_attributes = ' class="es0"';
+ }
+
+ //Add the style for the escape char ...
+ $string .= "<span$escape_char_attributes>" .
+ GeSHi::hsc($this->language_data['ESCAPE_CHAR']);
+
+ //Get the byte AFTER the ESCAPE_CHAR we just found
+ $es_char = $part[$es_pos + 1];
+ if ($es_char == "\n") {
+ // don't put a newline around newlines
+ $string .= "</span>\n";
+ $start = $es_pos + 2;
+ } elseif (ord($es_char) >= 128) {
+ //This is an non-ASCII char (UTF8 or single byte)
+ //This code tries to work around SF#2037598 ...
+ if(function_exists('mb_substr')) {
+ $es_char_m = mb_substr(substr($part, $es_pos+1, 16), 0, 1, $this->encoding);
+ $string .= $es_char_m . '</span>';
+ } elseif (!GESHI_PHP_PRE_433 && 'utf-8' == $this->encoding) {
+ if(preg_match("/[\xC2-\xDF][\x80-\xBF]".
+ "|\xE0[\xA0-\xBF][\x80-\xBF]".
+ "|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}".
+ "|\xED[\x80-\x9F][\x80-\xBF]".
+ "|\xF0[\x90-\xBF][\x80-\xBF]{2}".
+ "|[\xF1-\xF3][\x80-\xBF]{3}".
+ "|\xF4[\x80-\x8F][\x80-\xBF]{2}/s",
+ $part, $es_char_m, null, $es_pos + 1)) {
+ $es_char_m = $es_char_m[0];
+ } else {
+ $es_char_m = $es_char;
+ }
+ $string .= $this->hsc($es_char_m) . '</span>';
+ } else {
+ $es_char_m = $this->hsc($es_char);
+ }
+ $start = $es_pos + strlen($es_char_m) + 1;
+ } else {
+ $string .= $this->hsc($es_char) . '</span>';
+ $start = $es_pos + 2;
+ }
+ } elseif ($next_escape_regexp_pos < $length &&
+ $next_escape_regexp_pos < $close_pos) {
+ $es_pos = $next_escape_regexp_pos;
+ //Add the stuff not in the string yet ...
+ $string .= $this->hsc(substr($part, $start, $es_pos - $start));
+
+ //Get the key and length of this match ...
+ $escape = $escape_regexp_cache_per_key[$next_escape_regexp_key];
+ $escape_str = substr($part, $es_pos, $escape['length']);
+ $escape_key = $escape['key'];
+
+ //Get the style for this escaped char ...
+ if (!$this->use_classes) {
+ $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][$escape_key] . '"';
+ } else {
+ $escape_char_attributes = ' class="es' . $escape_key . '"';
+ }
+
+ //Add the style for the escape char ...
+ $string .= "<span$escape_char_attributes>" .
+ $this->hsc($escape_str) . '</span>';
+
+ $start = $es_pos + $escape['length'];
+ } else {
+ //Copy the remainder of the string ...
+ $string .= $this->hsc(substr($part, $start, $close_pos - $start + $char_len)) . '</span>';
+ $start = $close_pos + $char_len;
+ $string_open = false;
+ }
+ } while($string_open);
+
+ if ($check_linenumbers) {
+ // Are line numbers used? If, we should end the string before
+ // the newline and begin it again (so when <li>s are put in the source
+ // remains XHTML compliant)
+ // note to self: This opens up possibility of config files specifying
+ // that languages can/cannot have multiline strings???
+ $string = str_replace("\n", "</span>\n<span$string_attributes>", $string);
+ }
+
+ $result .= $string;
+ $string = '';
+ $i = $start - 1;
+ continue;
+ } elseif ($this->lexic_permissions['STRINGS'] && $hq && $hq[0] == $char &&
+ substr($part, $i, $hq_strlen) == $hq && ($i != $next_comment_regexp_pos)) {
+ // The start of a hard quoted string
+ if (!$this->use_classes) {
+ $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS']['HARD'] . '"';
+ $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR']['HARD'] . '"';
+ } else {
+ $string_attributes = ' class="st_h"';
+ $escape_char_attributes = ' class="es_h"';
+ }
+ // parse the stuff before this
+ $result .= $this->parse_non_string_part($stuff_to_parse);
+ $stuff_to_parse = '';
+
+ // now handle the string
+ $string = '';
+
+ // look for closing quote
+ $start = $i + $hq_strlen;
+ while ($close_pos = strpos($part, $this->language_data['HARDQUOTE'][1], $start)) {
+ $start = $close_pos + 1;
+ if ($this->lexic_permissions['ESCAPE_CHAR'] && $part[$close_pos - 1] == $this->language_data['HARDCHAR'] &&
+ (($i + $hq_strlen) != ($close_pos))) { //Support empty string for HQ escapes if Starter = Escape
+ // make sure this quote is not escaped
+ foreach ($this->language_data['HARDESCAPE'] as $hardescape) {
+ if (substr($part, $close_pos - 1, strlen($hardescape)) == $hardescape) {
+ // check wether this quote is escaped or if it is something like '\\'
+ $escape_char_pos = $close_pos - 1;
+ while ($escape_char_pos > 0
+ && $part[$escape_char_pos - 1] == $this->language_data['HARDCHAR']) {
+ --$escape_char_pos;
+ }
+ if (($close_pos - $escape_char_pos) & 1) {
+ // uneven number of escape chars => this quote is escaped
+ continue 2;
+ }
+ }
+ }
+ }
+
+ // found closing quote
+ break;
+ }
+
+ //Found the closing delimiter?
+ if (!$close_pos) {
+ // span till the end of this $part when no closing delimiter is found
+ $close_pos = $length;
+ }
+
+ //Get the actual string
+ $string = substr($part, $i, $close_pos - $i + 1);
+ $i = $close_pos;
+
+ // handle escape chars and encode html chars
+ // (special because when we have escape chars within our string they may not be escaped)
+ if ($this->lexic_permissions['ESCAPE_CHAR'] && $this->language_data['ESCAPE_CHAR']) {
+ $start = 0;
+ $new_string = '';
+ while ($es_pos = strpos($string, $this->language_data['ESCAPE_CHAR'], $start)) {
+ // hmtl escape stuff before
+ $new_string .= $this->hsc(substr($string, $start, $es_pos - $start));
+ // check if this is a hard escape
+ foreach ($this->language_data['HARDESCAPE'] as $hardescape) {
+ if (substr($string, $es_pos, strlen($hardescape)) == $hardescape) {
+ // indeed, this is a hardescape
+ $new_string .= "<span$escape_char_attributes>" .
+ $this->hsc($hardescape) . '</span>';
+ $start = $es_pos + strlen($hardescape);
+ continue 2;
+ }
+ }
+ // not a hard escape, but a normal escape
+ // they come in pairs of two
+ $c = 0;
+ while (isset($string[$es_pos + $c]) && isset($string[$es_pos + $c + 1])
+ && $string[$es_pos + $c] == $this->language_data['ESCAPE_CHAR']
+ && $string[$es_pos + $c + 1] == $this->language_data['ESCAPE_CHAR']) {
+ $c += 2;
+ }
+ if ($c) {
+ $new_string .= "<span$escape_char_attributes>" .
+ str_repeat($escaped_escape_char, $c) .
+ '</span>';
+ $start = $es_pos + $c;
+ } else {
+ // this is just a single lonely escape char...
+ $new_string .= $escaped_escape_char;
+ $start = $es_pos + 1;
+ }
+ }
+ $string = $new_string . $this->hsc(substr($string, $start));
+ } else {
+ $string = $this->hsc($string);
+ }
+
+ if ($check_linenumbers) {
+ // Are line numbers used? If, we should end the string before
+ // the newline and begin it again (so when <li>s are put in the source
+ // remains XHTML compliant)
+ // note to self: This opens up possibility of config files specifying
+ // that languages can/cannot have multiline strings???
+ $string = str_replace("\n", "</span>\n<span$string_attributes>", $string);
+ }
+
+ $result .= "<span$string_attributes>" . $string . '</span>';
+ $string = '';
+ continue;
+ } else {
+ //Have a look for regexp comments
+ if ($i == $next_comment_regexp_pos) {
+ $COMMENT_MATCHED = true;
+ $comment = $comment_regexp_cache_per_key[$next_comment_regexp_key];
+ $test_str = $this->hsc(substr($part, $i, $comment['length']));
+
+ //@todo If remove important do remove here
+ if ($this->lexic_permissions['COMMENTS']['MULTI']) {
+ if (!$this->use_classes) {
+ $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment['key']] . '"';
+ } else {
+ $attributes = ' class="co' . $comment['key'] . '"';
+ }
+
+ $test_str = "<span$attributes>" . $test_str . "</span>";
+
+ // Short-cut through all the multiline code
+ if ($check_linenumbers) {
+ // strreplace to put close span and open span around multiline newlines
+ $test_str = str_replace(
+ "\n", "</span>\n<span$attributes>",
+ str_replace("\n ", "\n&nbsp;", $test_str)
+ );
+ }
+ }
+
+ $i += $comment['length'] - 1;
+
+ // parse the rest
+ $result .= $this->parse_non_string_part($stuff_to_parse);
+ $stuff_to_parse = '';
+ }
+
+ // If we haven't matched a regexp comment, try multi-line comments
+ if (!$COMMENT_MATCHED) {
+ // Is this a multiline comment?
+ if (!empty($this->language_data['COMMENT_MULTI']) && $next_comment_multi_pos < $i) {
+ $next_comment_multi_pos = $length;
+ foreach ($this->language_data['COMMENT_MULTI'] as $open => $close) {
+ $match_i = false;
+ if (isset($comment_multi_cache_per_key[$open]) &&
+ ($comment_multi_cache_per_key[$open] >= $i ||
+ $comment_multi_cache_per_key[$open] === false)) {
+ // we have already matched something
+ if ($comment_multi_cache_per_key[$open] === false) {
+ // this comment is never matched
+ continue;
+ }
+ $match_i = $comment_multi_cache_per_key[$open];
+ } elseif (($match_i = stripos($part, $open, $i)) !== false) {
+ $comment_multi_cache_per_key[$open] = $match_i;
+ } else {
+ $comment_multi_cache_per_key[$open] = false;
+ continue;
+ }
+ if ($match_i !== false && $match_i < $next_comment_multi_pos) {
+ $next_comment_multi_pos = $match_i;
+ $next_open_comment_multi = $open;
+ if ($match_i === $i) {
+ break;
+ }
+ }
+ }
+ }
+ if ($i == $next_comment_multi_pos) {
+ $open = $next_open_comment_multi;
+ $close = $this->language_data['COMMENT_MULTI'][$open];
+ $open_strlen = strlen($open);
+ $close_strlen = strlen($close);
+ $COMMENT_MATCHED = true;
+ $test_str_match = $open;
+ //@todo If remove important do remove here
+ if ($this->lexic_permissions['COMMENTS']['MULTI'] ||
+ $open == GESHI_START_IMPORTANT) {
+ if ($open != GESHI_START_IMPORTANT) {
+ if (!$this->use_classes) {
+ $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS']['MULTI'] . '"';
+ } else {
+ $attributes = ' class="coMULTI"';
+ }
+ $test_str = "<span$attributes>" . $this->hsc($open);
+ } else {
+ if (!$this->use_classes) {
+ $attributes = ' style="' . $this->important_styles . '"';
+ } else {
+ $attributes = ' class="imp"';
+ }
+
+ // We don't include the start of the comment if it's an
+ // "important" part
+ $test_str = "<span$attributes>";
+ }
+ } else {
+ $test_str = $this->hsc($open);
+ }
+
+ $close_pos = strpos( $part, $close, $i + $open_strlen );
+
+ if ($close_pos === false) {
+ $close_pos = $length;
+ }
+
+ // Short-cut through all the multiline code
+ $rest_of_comment = $this->hsc(substr($part, $i + $open_strlen, $close_pos - $i - $open_strlen + $close_strlen));
+ if (($this->lexic_permissions['COMMENTS']['MULTI'] ||
+ $test_str_match == GESHI_START_IMPORTANT) &&
+ $check_linenumbers) {
+
+ // strreplace to put close span and open span around multiline newlines
+ $test_str .= str_replace(
+ "\n", "</span>\n<span$attributes>",
+ str_replace("\n ", "\n&nbsp;", $rest_of_comment)
+ );
+ } else {
+ $test_str .= $rest_of_comment;
+ }
+
+ if ($this->lexic_permissions['COMMENTS']['MULTI'] ||
+ $test_str_match == GESHI_START_IMPORTANT) {
+ $test_str .= '</span>';
+ }
+
+ $i = $close_pos + $close_strlen - 1;
+
+ // parse the rest
+ $result .= $this->parse_non_string_part($stuff_to_parse);
+ $stuff_to_parse = '';
+ }
+ }
+
+ // If we haven't matched a multiline comment, try single-line comments
+ if (!$COMMENT_MATCHED) {
+ // cache potential single line comment occurances
+ if (!empty($this->language_data['COMMENT_SINGLE']) && $next_comment_single_pos < $i) {
+ $next_comment_single_pos = $length;
+ foreach ($this->language_data['COMMENT_SINGLE'] as $comment_key => $comment_mark) {
+ $match_i = false;
+ if (isset($comment_single_cache_per_key[$comment_key]) &&
+ ($comment_single_cache_per_key[$comment_key] >= $i ||
+ $comment_single_cache_per_key[$comment_key] === false)) {
+ // we have already matched something
+ if ($comment_single_cache_per_key[$comment_key] === false) {
+ // this comment is never matched
+ continue;
+ }
+ $match_i = $comment_single_cache_per_key[$comment_key];
+ } elseif (
+ // case sensitive comments
+ ($this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] &&
+ ($match_i = stripos($part, $comment_mark, $i)) !== false) ||
+ // non case sensitive
+ (!$this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] &&
+ (($match_i = strpos($part, $comment_mark, $i)) !== false))) {
+ $comment_single_cache_per_key[$comment_key] = $match_i;
+ } else {
+ $comment_single_cache_per_key[$comment_key] = false;
+ continue;
+ }
+ if ($match_i !== false && $match_i < $next_comment_single_pos) {
+ $next_comment_single_pos = $match_i;
+ $next_comment_single_key = $comment_key;
+ if ($match_i === $i) {
+ break;
+ }
+ }
+ }
+ }
+ if ($next_comment_single_pos == $i) {
+ $comment_key = $next_comment_single_key;
+ $comment_mark = $this->language_data['COMMENT_SINGLE'][$comment_key];
+ $com_len = strlen($comment_mark);
+
+ // This check will find special variables like $# in bash
+ // or compiler directives of Delphi beginning {$
+ if ((empty($sc_disallowed_before) || ($i == 0) ||
+ (false === strpos($sc_disallowed_before, $part[$i-1]))) &&
+ (empty($sc_disallowed_after) || ($length <= $i + $com_len) ||
+ (false === strpos($sc_disallowed_after, $part[$i + $com_len]))))
+ {
+ // this is a valid comment
+ $COMMENT_MATCHED = true;
+ if ($this->lexic_permissions['COMMENTS'][$comment_key]) {
+ if (!$this->use_classes) {
+ $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment_key] . '"';
+ } else {
+ $attributes = ' class="co' . $comment_key . '"';
+ }
+ $test_str = "<span$attributes>" . $this->hsc($this->change_case($comment_mark));
+ } else {
+ $test_str = $this->hsc($comment_mark);
+ }
+
+ //Check if this comment is the last in the source
+ $close_pos = strpos($part, "\n", $i);
+ $oops = false;
+ if ($close_pos === false) {
+ $close_pos = $length;
+ $oops = true;
+ }
+ $test_str .= $this->hsc(substr($part, $i + $com_len, $close_pos - $i - $com_len));
+ if ($this->lexic_permissions['COMMENTS'][$comment_key]) {
+ $test_str .= "</span>";
+ }
+
+ // Take into account that the comment might be the last in the source
+ if (!$oops) {
+ $test_str .= "\n";
+ }
+
+ $i = $close_pos;
+
+ // parse the rest
+ $result .= $this->parse_non_string_part($stuff_to_parse);
+ $stuff_to_parse = '';
+ }
+ }
+ }
+ }
+
+ // Where are we adding this char?
+ if (!$COMMENT_MATCHED) {
+ $stuff_to_parse .= $char;
+ } else {
+ $result .= $test_str;
+ unset($test_str);
+ $COMMENT_MATCHED = false;
+ }
+ }
+ // Parse the last bit
+ $result .= $this->parse_non_string_part($stuff_to_parse);
+ $stuff_to_parse = '';
+ } else {
+ $result .= $this->hsc($part);
+ }
+ // Close the <span> that surrounds the block
+ if ($STRICTATTRS != '') {
+ $result = str_replace("\n", "</span>\n<span$STRICTATTRS>", $result);
+ $result .= '</span>';
+ }
+
+ $endresult .= $result;
+ unset($part, $parts[$key], $result);
+ }
+
+ //This fix is related to SF#1923020, but has to be applied regardless of
+ //actually highlighting symbols.
+ /** NOTE: memorypeak #3 */
+ $endresult = str_replace(array('<SEMI>', '<PIPE>'), array(';', '|'), $endresult);
+
+// // Parse the last stuff (redundant?)
+// $result .= $this->parse_non_string_part($stuff_to_parse);
+
+ // Lop off the very first and last spaces
+// $result = substr($result, 1, -1);
+
+ // We're finished: stop timing
+ $this->set_time($start_time, microtime());
+
+ $this->finalise($endresult);
+ return $endresult;
+ }
+
+ /**
+ * Swaps out spaces and tabs for HTML indentation. Not needed if
+ * the code is in a pre block...
+ *
+ * @param string The source to indent (reference!)
+ * @since 1.0.0
+ * @access private
+ */
+ function indent(&$result) {
+ /// Replace tabs with the correct number of spaces
+ if (false !== strpos($result, "\t")) {
+ $lines = explode("\n", $result);
+ $result = null;//Save memory while we process the lines individually
+ $tab_width = $this->get_real_tab_width();
+ $tab_string = '&nbsp;' . str_repeat(' ', $tab_width);
+
+ for ($key = 0, $n = count($lines); $key < $n; $key++) {
+ $line = $lines[$key];
+ if (false === strpos($line, "\t")) {
+ continue;
+ }
+
+ $pos = 0;
+ $length = strlen($line);
+ $lines[$key] = ''; // reduce memory
+
+ $IN_TAG = false;
+ for ($i = 0; $i < $length; ++$i) {
+ $char = $line[$i];
+ // Simple engine to work out whether we're in a tag.
+ // If we are we modify $pos. This is so we ignore HTML
+ // in the line and only workout the tab replacement
+ // via the actual content of the string
+ // This test could be improved to include strings in the
+ // html so that < or > would be allowed in user's styles
+ // (e.g. quotes: '<' '>'; or similar)
+ if ($IN_TAG) {
+ if ('>' == $char) {
+ $IN_TAG = false;
+ }
+ $lines[$key] .= $char;
+ } elseif ('<' == $char) {
+ $IN_TAG = true;
+ $lines[$key] .= '<';
+ } elseif ('&' == $char) {
+ $substr = substr($line, $i + 3, 5);
+ $posi = strpos($substr, ';');
+ if (false === $posi) {
+ ++$pos;
+ } else {
+ $pos -= $posi+2;
+ }
+ $lines[$key] .= $char;
+ } elseif ("\t" == $char) {
+ $str = '';
+ // OPTIMISE - move $strs out. Make an array:
+ // $tabs = array(
+ // 1 => '&nbsp;',
+ // 2 => '&nbsp; ',
+ // 3 => '&nbsp; &nbsp;' etc etc
+ // to use instead of building a string every time
+ $tab_end_width = $tab_width - ($pos % $tab_width); //Moved out of the look as it doesn't change within the loop
+ if (($pos & 1) || 1 == $tab_end_width) {
+ $str .= substr($tab_string, 6, $tab_end_width);
+ } else {
+ $str .= substr($tab_string, 0, $tab_end_width+5);
+ }
+ $lines[$key] .= $str;
+ $pos += $tab_end_width;
+
+ if (false === strpos($line, "\t", $i + 1)) {
+ $lines[$key] .= substr($line, $i + 1);
+ break;
+ }
+ } elseif (0 == $pos && ' ' == $char) {
+ $lines[$key] .= '&nbsp;';
+ ++$pos;
+ } else {
+ $lines[$key] .= $char;
+ ++$pos;
+ }
+ }
+ }
+ $result = implode("\n", $lines);
+ unset($lines);//We don't need the lines separated beyond this --- free them!
+ }
+ // Other whitespace
+ // BenBE: Fix to reduce the number of replacements to be done
+ $result = preg_replace('/^ /m', '&nbsp;', $result);
+ $result = str_replace(' ', ' &nbsp;', $result);
+
+ if ($this->line_numbers == GESHI_NO_LINE_NUMBERS && $this->header_type != GESHI_HEADER_PRE_TABLE) {
+ if ($this->line_ending === null) {
+ $result = nl2br($result);
+ } else {
+ $result = str_replace("\n", $this->line_ending, $result);
+ }
+ }
+ }
+
+ /**
+ * Changes the case of a keyword for those languages where a change is asked for
+ *
+ * @param string The keyword to change the case of
+ * @return string The keyword with its case changed
+ * @since 1.0.0
+ * @access private
+ */
+ function change_case($instr) {
+ switch ($this->language_data['CASE_KEYWORDS']) {
+ case GESHI_CAPS_UPPER:
+ return strtoupper($instr);
+ case GESHI_CAPS_LOWER:
+ return strtolower($instr);
+ default:
+ return $instr;
+ }
+ }
+
+ /**
+ * Handles replacements of keywords to include markup and links if requested
+ *
+ * @param string The keyword to add the Markup to
+ * @return The HTML for the match found
+ * @since 1.0.8
+ * @access private
+ *
+ * @todo Get rid of ender in keyword links
+ */
+ function handle_keyword_replace($match) {
+ $k = $this->_kw_replace_group;
+ $keyword = $match[0];
+ $keyword_match = $match[1];
+
+ $before = '';
+ $after = '';
+
+ if ($this->keyword_links) {
+ // Keyword links have been ebabled
+
+ if (isset($this->language_data['URLS'][$k]) &&
+ $this->language_data['URLS'][$k] != '') {
+ // There is a base group for this keyword
+
+ // Old system: strtolower
+ //$keyword = ( $this->language_data['CASE_SENSITIVE'][$group] ) ? $keyword : strtolower($keyword);
+ // New system: get keyword from language file to get correct case
+ if (!$this->language_data['CASE_SENSITIVE'][$k] &&
+ strpos($this->language_data['URLS'][$k], '{FNAME}') !== false) {
+ foreach ($this->language_data['KEYWORDS'][$k] as $word) {
+ if (strcasecmp($word, $keyword_match) == 0) {
+ break;
+ }
+ }
+ } else {
+ $word = $keyword_match;
+ }
+
+ $before = '<|UR1|"' .
+ str_replace(
+ array(
+ '{FNAME}',
+ '{FNAMEL}',
+ '{FNAMEU}',
+ '.'),
+ array(
+ str_replace('+', '%20', urlencode($this->hsc($word))),
+ str_replace('+', '%20', urlencode($this->hsc(strtolower($word)))),
+ str_replace('+', '%20', urlencode($this->hsc(strtoupper($word)))),
+ '<DOT>'),
+ $this->language_data['URLS'][$k]
+ ) . '">';
+ $after = '</a>';
+ }
+ }
+
+ return $before . '<|/'. $k .'/>' . $this->change_case($keyword) . '|>' . $after;
+ }
+
+ /**
+ * handles regular expressions highlighting-definitions with callback functions
+ *
+ * @note this is a callback, don't use it directly
+ *
+ * @param array the matches array
+ * @return The highlighted string
+ * @since 1.0.8
+ * @access private
+ */
+ function handle_regexps_callback($matches) {
+ // before: "' style=\"' . call_user_func(\"$func\", '\\1') . '\"\\1|>'",
+ return ' style="' . call_user_func($this->language_data['STYLES']['REGEXPS'][$this->_rx_key], $matches[1]) . '"'. $matches[1] . '|>';
+ }
+
+ /**
+ * handles newlines in REGEXPS matches. Set the _hmr_* vars before calling this
+ *
+ * @note this is a callback, don't use it directly
+ *
+ * @param array the matches array
+ * @return string
+ * @since 1.0.8
+ * @access private
+ */
+ function handle_multiline_regexps($matches) {
+ $before = $this->_hmr_before;
+ $after = $this->_hmr_after;
+ if ($this->_hmr_replace) {
+ $replace = $this->_hmr_replace;
+ $search = array();
+
+ foreach (array_keys($matches) as $k) {
+ $search[] = '\\' . $k;
+ }
+
+ $before = str_replace($search, $matches, $before);
+ $after = str_replace($search, $matches, $after);
+ $replace = str_replace($search, $matches, $replace);
+ } else {
+ $replace = $matches[0];
+ }
+ return $before
+ . '<|!REG3XP' . $this->_hmr_key .'!>'
+ . str_replace("\n", "|>\n<|!REG3XP" . $this->_hmr_key . '!>', $replace)
+ . '|>'
+ . $after;
+ }
+
+ /**
+ * Takes a string that has no strings or comments in it, and highlights
+ * stuff like keywords, numbers and methods.
+ *
+ * @param string The string to parse for keyword, numbers etc.
+ * @since 1.0.0
+ * @access private
+ * @todo BUGGY! Why? Why not build string and return?
+ */
+ function parse_non_string_part($stuff_to_parse) {
+ $stuff_to_parse = ' ' . $this->hsc($stuff_to_parse);
+
+ // Highlight keywords
+ $disallowed_before = "(?<![a-zA-Z0-9\$_\|\#|^&";
+ $disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;";
+ if ($this->lexic_permissions['STRINGS']) {
+ $quotemarks = preg_quote(implode($this->language_data['QUOTEMARKS']), '/');
+ $disallowed_before .= $quotemarks;
+ $disallowed_after .= $quotemarks;
+ }
+ $disallowed_before .= "])";
+ $disallowed_after .= "])";
+
+ $parser_control_pergroup = false;
+ if (isset($this->language_data['PARSER_CONTROL'])) {
+ if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) {
+ $x = 0; // check wether per-keyword-group parser_control is enabled
+ if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
+ $disallowed_before = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
+ ++$x;
+ }
+ if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
+ $disallowed_after = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
+ ++$x;
+ }
+ $parser_control_pergroup = (count($this->language_data['PARSER_CONTROL']['KEYWORDS']) - $x) > 0;
+ }
+ }
+
+ foreach (array_keys($this->language_data['KEYWORDS']) as $k) {
+ if (!isset($this->lexic_permissions['KEYWORDS'][$k]) ||
+ $this->lexic_permissions['KEYWORDS'][$k]) {
+
+ $case_sensitive = $this->language_data['CASE_SENSITIVE'][$k];
+ $modifiers = $case_sensitive ? '' : 'i';
+
+ // NEW in 1.0.8 - per-keyword-group parser control
+ $disallowed_before_local = $disallowed_before;
+ $disallowed_after_local = $disallowed_after;
+ if ($parser_control_pergroup && isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k])) {
+ if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'])) {
+ $disallowed_before_local =
+ $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'];
+ }
+
+ if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'])) {
+ $disallowed_after_local =
+ $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'];
+ }
+ }
+
+ $this->_kw_replace_group = $k;
+
+ //NEW in 1.0.8, the cached regexp list
+ // since we don't want PHP / PCRE to crash due to too large patterns we split them into smaller chunks
+ for ($set = 0, $set_length = count($this->language_data['CACHED_KEYWORD_LISTS'][$k]); $set < $set_length; ++$set) {
+ $keywordset =& $this->language_data['CACHED_KEYWORD_LISTS'][$k][$set];
+ // Might make a more unique string for putting the number in soon
+ // Basically, we don't put the styles in yet because then the styles themselves will
+ // get highlighted if the language has a CSS keyword in it (like CSS, for example ;))
+ $stuff_to_parse = preg_replace_callback(
+ "/$disallowed_before_local({$keywordset})(?!\<DOT\>(?:htm|php|aspx?))$disallowed_after_local/$modifiers",
+ array($this, 'handle_keyword_replace'),
+ $stuff_to_parse
+ );
+ }
+ }
+ }
+
+ // Regular expressions
+ foreach ($this->language_data['REGEXPS'] as $key => $regexp) {
+ if ($this->lexic_permissions['REGEXPS'][$key]) {
+ if (is_array($regexp)) {
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ // produce valid HTML when we match multiple lines
+ $this->_hmr_replace = $regexp[GESHI_REPLACE];
+ $this->_hmr_before = $regexp[GESHI_BEFORE];
+ $this->_hmr_key = $key;
+ $this->_hmr_after = $regexp[GESHI_AFTER];
+ $stuff_to_parse = preg_replace_callback(
+ "/" . $regexp[GESHI_SEARCH] . "/{$regexp[GESHI_MODIFIERS]}",
+ array($this, 'handle_multiline_regexps'),
+ $stuff_to_parse);
+ $this->_hmr_replace = false;
+ $this->_hmr_before = '';
+ $this->_hmr_after = '';
+ } else {
+ $stuff_to_parse = preg_replace(
+ '/' . $regexp[GESHI_SEARCH] . '/' . $regexp[GESHI_MODIFIERS],
+ $regexp[GESHI_BEFORE] . '<|!REG3XP'. $key .'!>' . $regexp[GESHI_REPLACE] . '|>' . $regexp[GESHI_AFTER],
+ $stuff_to_parse);
+ }
+ } else {
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ // produce valid HTML when we match multiple lines
+ $this->_hmr_key = $key;
+ $stuff_to_parse = preg_replace_callback( "/(" . $regexp . ")/",
+ array($this, 'handle_multiline_regexps'), $stuff_to_parse);
+ $this->_hmr_key = '';
+ } else {
+ $stuff_to_parse = preg_replace( "/(" . $regexp . ")/", "<|!REG3XP$key!>\\1|>", $stuff_to_parse);
+ }
+ }
+ }
+ }
+
+ // Highlight numbers. As of 1.0.8 we support different types of numbers
+ $numbers_found = false;
+
+ if ($this->lexic_permissions['NUMBERS'] && preg_match($this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'], $stuff_to_parse )) {
+ $numbers_found = true;
+
+ //For each of the formats ...
+ foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
+ //Check if it should be highlighted ...
+ $stuff_to_parse = preg_replace($regexp, "<|/NUM!$id/>\\1|>", $stuff_to_parse);
+ }
+ }
+
+ //
+ // Now that's all done, replace /[number]/ with the correct styles
+ //
+ foreach (array_keys($this->language_data['KEYWORDS']) as $k) {
+ if (!$this->use_classes) {
+ $attributes = ' style="' .
+ (isset($this->language_data['STYLES']['KEYWORDS'][$k]) ?
+ $this->language_data['STYLES']['KEYWORDS'][$k] : "") . '"';
+ } else {
+ $attributes = ' class="kw' . $k . '"';
+ }
+ $stuff_to_parse = str_replace("<|/$k/>", "<|$attributes>", $stuff_to_parse);
+ }
+
+ if ($numbers_found) {
+ // Put number styles in
+ foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) {
+ //Commented out for now, as this needs some review ...
+ // if ($numbers_permissions & $id) {
+ //Get the appropriate style ...
+ //Checking for unset styles is done by the style cache builder ...
+ if (!$this->use_classes) {
+ $attributes = ' style="' . $this->language_data['STYLES']['NUMBERS'][$id] . '"';
+ } else {
+ $attributes = ' class="nu'.$id.'"';
+ }
+
+ //Set in the correct styles ...
+ $stuff_to_parse = str_replace("/NUM!$id/", $attributes, $stuff_to_parse);
+ // }
+ }
+ }
+
+ // Highlight methods and fields in objects
+ if ($this->lexic_permissions['METHODS'] && $this->language_data['OOLANG']) {
+ $oolang_spaces = "[\s]*";
+ $oolang_before = "";
+ $oolang_after = "[a-zA-Z][a-zA-Z0-9_]*";
+ if (isset($this->language_data['PARSER_CONTROL'])) {
+ if (isset($this->language_data['PARSER_CONTROL']['OOLANG'])) {
+ if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_BEFORE'])) {
+ $oolang_before = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_BEFORE'];
+ }
+ if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_AFTER'])) {
+ $oolang_after = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_AFTER'];
+ }
+ if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_SPACES'])) {
+ $oolang_spaces = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_SPACES'];
+ }
+ }
+ }
+
+ foreach ($this->language_data['OBJECT_SPLITTERS'] as $key => $splitter) {
+ if (false !== strpos($stuff_to_parse, $splitter)) {
+ if (!$this->use_classes) {
+ $attributes = ' style="' . $this->language_data['STYLES']['METHODS'][$key] . '"';
+ } else {
+ $attributes = ' class="me' . $key . '"';
+ }
+ $stuff_to_parse = preg_replace("/($oolang_before)(" . preg_quote($this->language_data['OBJECT_SPLITTERS'][$key], '/') . ")($oolang_spaces)($oolang_after)/", "\\1\\2\\3<|$attributes>\\4|>", $stuff_to_parse);
+ }
+ }
+ }
+
+ //
+ // Highlight brackets. Yes, I've tried adding a semi-colon to this list.
+ // You try it, and see what happens ;)
+ // TODO: Fix lexic permissions not converting entities if shouldn't
+ // be highlighting regardless
+ //
+ if ($this->lexic_permissions['BRACKETS']) {
+ $stuff_to_parse = str_replace( $this->language_data['CACHE_BRACKET_MATCH'],
+ $this->language_data['CACHE_BRACKET_REPLACE'], $stuff_to_parse );
+ }
+
+
+ //FIX for symbol highlighting ...
+ if ($this->lexic_permissions['SYMBOLS'] && !empty($this->language_data['SYMBOLS'])) {
+ //Get all matches and throw away those witin a block that is already highlighted... (i.e. matched by a regexp)
+ $n_symbols = preg_match_all("/<\|(?:<DOT>|[^>])+>(?:(?!\|>).*?)\|>|<\/a>|(?:" . $this->language_data['SYMBOL_SEARCH'] . ")+(?![^<]+?>)/", $stuff_to_parse, $pot_symbols, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
+ $global_offset = 0;
+ for ($s_id = 0; $s_id < $n_symbols; ++$s_id) {
+ $symbol_match = $pot_symbols[$s_id][0][0];
+ if (strpos($symbol_match, '<') !== false || strpos($symbol_match, '>') !== false) {
+ // already highlighted blocks _must_ include either < or >
+ // so if this conditional applies, we have to skip this match
+ // BenBE: UNLESS the block contains <SEMI> or <PIPE>
+ if(strpos($symbol_match, '<SEMI>') === false &&
+ strpos($symbol_match, '<PIPE>') === false) {
+ continue;
+ }
+ }
+
+ // if we reach this point, we have a valid match which needs to be highlighted
+
+ $symbol_length = strlen($symbol_match);
+ $symbol_offset = $pot_symbols[$s_id][0][1];
+ unset($pot_symbols[$s_id]);
+ $symbol_end = $symbol_length + $symbol_offset;
+ $symbol_hl = "";
+
+ // if we have multiple styles, we have to handle them properly
+ if ($this->language_data['MULTIPLE_SYMBOL_GROUPS']) {
+ $old_sym = -1;
+ // Split the current stuff to replace into its atomic symbols ...
+ preg_match_all("/" . $this->language_data['SYMBOL_SEARCH'] . "/", $symbol_match, $sym_match_syms, PREG_PATTERN_ORDER);
+ foreach ($sym_match_syms[0] as $sym_ms) {
+ //Check if consequtive symbols belong to the same group to save output ...
+ if (isset($this->language_data['SYMBOL_DATA'][$sym_ms])
+ && ($this->language_data['SYMBOL_DATA'][$sym_ms] != $old_sym)) {
+ if (-1 != $old_sym) {
+ $symbol_hl .= "|>";
+ }
+ $old_sym = $this->language_data['SYMBOL_DATA'][$sym_ms];
+ if (!$this->use_classes) {
+ $symbol_hl .= '<| style="' . $this->language_data['STYLES']['SYMBOLS'][$old_sym] . '">';
+ } else {
+ $symbol_hl .= '<| class="sy' . $old_sym . '">';
+ }
+ }
+ $symbol_hl .= $sym_ms;
+ }
+ unset($sym_match_syms);
+
+ //Close remaining tags and insert the replacement at the right position ...
+ //Take caution if symbol_hl is empty to avoid doubled closing spans.
+ if (-1 != $old_sym) {
+ $symbol_hl .= "|>";
+ }
+ } else {
+ if (!$this->use_classes) {
+ $symbol_hl = '<| style="' . $this->language_data['STYLES']['SYMBOLS'][0] . '">';
+ } else {
+ $symbol_hl = '<| class="sy0">';
+ }
+ $symbol_hl .= $symbol_match . '|>';
+ }
+
+ $stuff_to_parse = substr_replace($stuff_to_parse, $symbol_hl, $symbol_offset + $global_offset, $symbol_length);
+
+ // since we replace old text with something of different size,
+ // we'll have to keep track of the differences
+ $global_offset += strlen($symbol_hl) - $symbol_length;
+ }
+ }
+ //FIX for symbol highlighting ...
+
+ // Add class/style for regexps
+ foreach (array_keys($this->language_data['REGEXPS']) as $key) {
+ if ($this->lexic_permissions['REGEXPS'][$key]) {
+ if (is_callable($this->language_data['STYLES']['REGEXPS'][$key])) {
+ $this->_rx_key = $key;
+ $stuff_to_parse = preg_replace_callback("/!REG3XP$key!(.*)\|>/U",
+ array($this, 'handle_regexps_callback'),
+ $stuff_to_parse);
+ } else {
+ if (!$this->use_classes) {
+ $attributes = ' style="' . $this->language_data['STYLES']['REGEXPS'][$key] . '"';
+ } else {
+ if (is_array($this->language_data['REGEXPS'][$key]) &&
+ array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$key])) {
+ $attributes = ' class="' .
+ $this->language_data['REGEXPS'][$key][GESHI_CLASS] . '"';
+ } else {
+ $attributes = ' class="re' . $key . '"';
+ }
+ }
+ $stuff_to_parse = str_replace("!REG3XP$key!", "$attributes", $stuff_to_parse);
+ }
+ }
+ }
+
+ // Replace <DOT> with . for urls
+ $stuff_to_parse = str_replace('<DOT>', '.', $stuff_to_parse);
+ // Replace <|UR1| with <a href= for urls also
+ if (isset($this->link_styles[GESHI_LINK])) {
+ if ($this->use_classes) {
+ $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' href=', $stuff_to_parse);
+ } else {
+ $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' style="' . $this->link_styles[GESHI_LINK] . '" href=', $stuff_to_parse);
+ }
+ } else {
+ $stuff_to_parse = str_replace('<|UR1|', '<a' . $this->link_target . ' href=', $stuff_to_parse);
+ }
+
+ //
+ // NOW we add the span thingy ;)
+ //
+
+ $stuff_to_parse = str_replace('<|', '<span', $stuff_to_parse);
+ $stuff_to_parse = str_replace ( '|>', '</span>', $stuff_to_parse );
+ return substr($stuff_to_parse, 1);
+ }
+
+ /**
+ * Sets the time taken to parse the code
+ *
+ * @param microtime The time when parsing started
+ * @param microtime The time when parsing ended
+ * @since 1.0.2
+ * @access private
+ */
+ function set_time($start_time, $end_time) {
+ $start = explode(' ', $start_time);
+ $end = explode(' ', $end_time);
+ $this->time = $end[0] + $end[1] - $start[0] - $start[1];
+ }
+
+ /**
+ * Gets the time taken to parse the code
+ *
+ * @return double The time taken to parse the code
+ * @since 1.0.2
+ */
+ function get_time() {
+ return $this->time;
+ }
+
+ /**
+ * Merges arrays recursively, overwriting values of the first array with values of later arrays
+ *
+ * @since 1.0.8
+ * @access private
+ */
+ function merge_arrays() {
+ $arrays = func_get_args();
+ $narrays = count($arrays);
+
+ // check arguments
+ // comment out if more performance is necessary (in this case the foreach loop will trigger a warning if the argument is not an array)
+ for ($i = 0; $i < $narrays; $i ++) {
+ if (!is_array($arrays[$i])) {
+ // also array_merge_recursive returns nothing in this case
+ trigger_error('Argument #' . ($i+1) . ' is not an array - trying to merge array with scalar! Returning false!', E_USER_WARNING);
+ return false;
+ }
+ }
+
+ // the first array is in the output set in every case
+ $ret = $arrays[0];
+
+ // merege $ret with the remaining arrays
+ for ($i = 1; $i < $narrays; $i ++) {
+ foreach ($arrays[$i] as $key => $value) {
+ if (is_array($value) && isset($ret[$key])) {
+ // if $ret[$key] is not an array you try to merge an scalar value with an array - the result is not defined (incompatible arrays)
+ // in this case the call will trigger an E_USER_WARNING and the $ret[$key] will be false.
+ $ret[$key] = $this->merge_arrays($ret[$key], $value);
+ } else {
+ $ret[$key] = $value;
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Gets language information and stores it for later use
+ *
+ * @param string The filename of the language file you want to load
+ * @since 1.0.0
+ * @access private
+ * @todo Needs to load keys for lexic permissions for keywords, regexps etc
+ */
+ function load_language($file_name) {
+ if ($file_name == $this->loaded_language) {
+ // this file is already loaded!
+ return;
+ }
+
+ //Prepare some stuff before actually loading the language file
+ $this->loaded_language = $file_name;
+ $this->parse_cache_built = false;
+ $this->enable_highlighting();
+ $language_data = array();
+
+ //Load the language file
+ require $file_name;
+
+ // Perhaps some checking might be added here later to check that
+ // $language data is a valid thing but maybe not
+ $this->language_data = $language_data;
+
+ // Set strict mode if should be set
+ $this->strict_mode = $this->language_data['STRICT_MODE_APPLIES'];
+
+ // Set permissions for all lexics to true
+ // so they'll be highlighted by default
+ foreach (array_keys($this->language_data['KEYWORDS']) as $key) {
+ if (!empty($this->language_data['KEYWORDS'][$key])) {
+ $this->lexic_permissions['KEYWORDS'][$key] = true;
+ } else {
+ $this->lexic_permissions['KEYWORDS'][$key] = false;
+ }
+ }
+
+ foreach (array_keys($this->language_data['COMMENT_SINGLE']) as $key) {
+ $this->lexic_permissions['COMMENTS'][$key] = true;
+ }
+ foreach (array_keys($this->language_data['REGEXPS']) as $key) {
+ $this->lexic_permissions['REGEXPS'][$key] = true;
+ }
+
+ // for BenBE and future code reviews:
+ // we can use empty here since we only check for existance and emptiness of an array
+ // if it is not an array at all but rather false or null this will work as intended as well
+ // even if $this->language_data['PARSER_CONTROL'] is undefined this won't trigger a notice
+ if (!empty($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS'])) {
+ foreach ($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS'] as $flag => $value) {
+ // it's either true or false and maybe is true as well
+ $perm = $value !== GESHI_NEVER;
+ if ($flag == 'ALL') {
+ $this->enable_highlighting($perm);
+ continue;
+ }
+ if (!isset($this->lexic_permissions[$flag])) {
+ // unknown lexic permission
+ continue;
+ }
+ if (is_array($this->lexic_permissions[$flag])) {
+ foreach ($this->lexic_permissions[$flag] as $key => $val) {
+ $this->lexic_permissions[$flag][$key] = $perm;
+ }
+ } else {
+ $this->lexic_permissions[$flag] = $perm;
+ }
+ }
+ unset($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS']);
+ }
+
+ //Fix: Problem where hardescapes weren't handled if no ESCAPE_CHAR was given
+ //You need to set one for HARDESCAPES only in this case.
+ if(!isset($this->language_data['HARDCHAR'])) {
+ $this->language_data['HARDCHAR'] = $this->language_data['ESCAPE_CHAR'];
+ }
+
+ //NEW in 1.0.8: Allow styles to be loaded from a separate file to override defaults
+ $style_filename = substr($file_name, 0, -4) . '.style.php';
+ if (is_readable($style_filename)) {
+ //Clear any style_data that could have been set before ...
+ if (isset($style_data)) {
+ unset($style_data);
+ }
+
+ //Read the Style Information from the style file
+ include $style_filename;
+
+ //Apply the new styles to our current language styles
+ if (isset($style_data) && is_array($style_data)) {
+ $this->language_data['STYLES'] =
+ $this->merge_arrays($this->language_data['STYLES'], $style_data);
+ }
+ }
+ }
+
+ /**
+ * Takes the parsed code and various options, and creates the HTML
+ * surrounding it to make it look nice.
+ *
+ * @param string The code already parsed (reference!)
+ * @since 1.0.0
+ * @access private
+ */
+ function finalise(&$parsed_code) {
+ // Remove end parts of important declarations
+ // This is BUGGY!! My fault for bad code: fix coming in 1.2
+ // @todo Remove this crap
+ if ($this->enable_important_blocks &&
+ (strpos($parsed_code, $this->hsc(GESHI_START_IMPORTANT)) === false)) {
+ $parsed_code = str_replace($this->hsc(GESHI_END_IMPORTANT), '', $parsed_code);
+ }
+
+ // Add HTML whitespace stuff if we're using the <div> header
+ if ($this->header_type != GESHI_HEADER_PRE && $this->header_type != GESHI_HEADER_PRE_VALID) {
+ $this->indent($parsed_code);
+ }
+
+ // purge some unnecessary stuff
+ /** NOTE: memorypeak #1 */
+ $parsed_code = preg_replace('#<span[^>]+>(\s*)</span>#', '\\1', $parsed_code);
+
+ // If we are using IDs for line numbers, there needs to be an overall
+ // ID set to prevent collisions.
+ if ($this->add_ids && !$this->overall_id) {
+ $this->overall_id = 'geshi-' . substr(md5(microtime()), 0, 4);
+ }
+
+ // Get code into lines
+ /** NOTE: memorypeak #2 */
+ $code = explode("\n", $parsed_code);
+ $parsed_code = $this->header();
+
+ // If we're using line numbers, we insert <li>s and appropriate
+ // markup to style them (otherwise we don't need to do anything)
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS && $this->header_type != GESHI_HEADER_PRE_TABLE) {
+ // If we're using the <pre> header, we shouldn't add newlines because
+ // the <pre> will line-break them (and the <li>s already do this for us)
+ $ls = ($this->header_type != GESHI_HEADER_PRE && $this->header_type != GESHI_HEADER_PRE_VALID) ? "\n" : '';
+
+ // Set vars to defaults for following loop
+ $i = 0;
+
+ // Foreach line...
+ for ($i = 0, $n = count($code); $i < $n;) {
+ //Reset the attributes for a new line ...
+ $attrs = array();
+
+ // Make lines have at least one space in them if they're empty
+ // BenBE: Checking emptiness using trim instead of relying on blanks
+ if ('' == trim($code[$i])) {
+ $code[$i] = '&nbsp;';
+ }
+
+ // If this is a "special line"...
+ if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
+ $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
+ // Set the attributes to style the line
+ if ($this->use_classes) {
+ //$attr = ' class="li2"';
+ $attrs['class'][] = 'li2';
+ $def_attr = ' class="de2"';
+ } else {
+ //$attr = ' style="' . $this->line_style2 . '"';
+ $attrs['style'][] = $this->line_style2;
+ // This style "covers up" the special styles set for special lines
+ // so that styles applied to special lines don't apply to the actual
+ // code on that line
+ $def_attr = ' style="' . $this->code_style . '"';
+ }
+ } else {
+ if ($this->use_classes) {
+ //$attr = ' class="li1"';
+ $attrs['class'][] = 'li1';
+ $def_attr = ' class="de1"';
+ } else {
+ //$attr = ' style="' . $this->line_style1 . '"';
+ $attrs['style'][] = $this->line_style1;
+ $def_attr = ' style="' . $this->code_style . '"';
+ }
+ }
+
+ //Check which type of tag to insert for this line
+ if ($this->header_type == GESHI_HEADER_PRE_VALID) {
+ $start = "<pre$def_attr>";
+ $end = '</pre>';
+ } else {
+ // Span or div?
+ $start = "<div$def_attr>";
+ $end = '</div>';
+ }
+
+ ++$i;
+
+ // Are we supposed to use ids? If so, add them
+ if ($this->add_ids) {
+ $attrs['id'][] = "$this->overall_id-$i";
+ }
+
+ //Is this some line with extra styles???
+ if (in_array($i, $this->highlight_extra_lines)) {
+ if ($this->use_classes) {
+ if (isset($this->highlight_extra_lines_styles[$i])) {
+ $attrs['class'][] = "lx$i";
+ } else {
+ $attrs['class'][] = "ln-xtra";
+ }
+ } else {
+ array_push($attrs['style'], $this->get_line_style($i));
+ }
+ }
+
+ // Add in the line surrounded by appropriate list HTML
+ $attr_string = '';
+ foreach ($attrs as $key => $attr) {
+ $attr_string .= ' ' . $key . '="' . implode(' ', $attr) . '"';
+ }
+
+ $parsed_code .= "<li$attr_string>$start{$code[$i-1]}$end</li>$ls";
+ unset($code[$i - 1]);
+ }
+ } else {
+ $n = count($code);
+ if ($this->use_classes) {
+ $attributes = ' class="de1"';
+ } else {
+ $attributes = ' style="'. $this->code_style .'"';
+ }
+ if ($this->header_type == GESHI_HEADER_PRE_VALID) {
+ $parsed_code .= '<pre'. $attributes .'>';
+ } elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) {
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ if ($this->use_classes) {
+ $attrs = ' class="ln"';
+ } else {
+ $attrs = ' style="'. $this->table_linenumber_style .'"';
+ }
+ $parsed_code .= '<td'.$attrs.'><pre'.$attributes.'>';
+ // get linenumbers
+ // we don't merge it with the for below, since it should be better for
+ // memory consumption this way
+ // @todo: but... actually it would still be somewhat nice to merge the two loops
+ // the mem peaks are at different positions
+ for ($i = 0; $i < $n; ++$i) {
+ $close = 0;
+ // fancy lines
+ if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
+ $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
+ // Set the attributes to style the line
+ if ($this->use_classes) {
+ $parsed_code .= '<span class="xtra li2"><span class="de2">';
+ } else {
+ // This style "covers up" the special styles set for special lines
+ // so that styles applied to special lines don't apply to the actual
+ // code on that line
+ $parsed_code .= '<span style="display:block;' . $this->line_style2 . '">'
+ .'<span style="' . $this->code_style .'">';
+ }
+ $close += 2;
+ }
+ //Is this some line with extra styles???
+ if (in_array($i + 1, $this->highlight_extra_lines)) {
+ if ($this->use_classes) {
+ if (isset($this->highlight_extra_lines_styles[$i])) {
+ $parsed_code .= "<span class=\"xtra lx$i\">";
+ } else {
+ $parsed_code .= "<span class=\"xtra ln-xtra\">";
+ }
+ } else {
+ $parsed_code .= "<span style=\"display:block;" . $this->get_line_style($i) . "\">";
+ }
+ ++$close;
+ }
+ $parsed_code .= $this->line_numbers_start + $i;
+ if ($close) {
+ $parsed_code .= str_repeat('</span>', $close);
+ } elseif ($i != $n) {
+ $parsed_code .= "\n";
+ }
+ }
+ $parsed_code .= '</pre></td><td'.$attributes.'>';
+ }
+ $parsed_code .= '<pre'. $attributes .'>';
+ }
+ // No line numbers, but still need to handle highlighting lines extra.
+ // Have to use divs so the full width of the code is highlighted
+ $close = 0;
+ for ($i = 0; $i < $n; ++$i) {
+ // Make lines have at least one space in them if they're empty
+ // BenBE: Checking emptiness using trim instead of relying on blanks
+ if ('' == trim($code[$i])) {
+ $code[$i] = '&nbsp;';
+ }
+ // fancy lines
+ if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS &&
+ $i % $this->line_nth_row == ($this->line_nth_row - 1)) {
+ // Set the attributes to style the line
+ if ($this->use_classes) {
+ $parsed_code .= '<span class="xtra li2"><span class="de2">';
+ } else {
+ // This style "covers up" the special styles set for special lines
+ // so that styles applied to special lines don't apply to the actual
+ // code on that line
+ $parsed_code .= '<span style="display:block;' . $this->line_style2 . '">'
+ .'<span style="' . $this->code_style .'">';
+ }
+ $close += 2;
+ }
+ //Is this some line with extra styles???
+ if (in_array($i + 1, $this->highlight_extra_lines)) {
+ if ($this->use_classes) {
+ if (isset($this->highlight_extra_lines_styles[$i])) {
+ $parsed_code .= "<span class=\"xtra lx$i\">";
+ } else {
+ $parsed_code .= "<span class=\"xtra ln-xtra\">";
+ }
+ } else {
+ $parsed_code .= "<span style=\"display:block;" . $this->get_line_style($i) . "\">";
+ }
+ ++$close;
+ }
+
+ $parsed_code .= $code[$i];
+
+ if ($close) {
+ $parsed_code .= str_repeat('</span>', $close);
+ $close = 0;
+ }
+ elseif ($i + 1 < $n) {
+ $parsed_code .= "\n";
+ }
+ unset($code[$i]);
+ }
+
+ if ($this->header_type == GESHI_HEADER_PRE_VALID || $this->header_type == GESHI_HEADER_PRE_TABLE) {
+ $parsed_code .= '</pre>';
+ }
+ if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ $parsed_code .= '</td>';
+ }
+ }
+
+ $parsed_code .= $this->footer();
+ }
+
+ /**
+ * Creates the header for the code block (with correct attributes)
+ *
+ * @return string The header for the code block
+ * @since 1.0.0
+ * @access private
+ */
+ function header() {
+ // Get attributes needed
+ /**
+ * @todo Document behaviour change - class is outputted regardless of whether
+ * we're using classes or not. Same with style
+ */
+ $attributes = ' class="' . $this->_genCSSName($this->language);
+ if ($this->overall_class != '') {
+ $attributes .= " ".$this->_genCSSName($this->overall_class);
+ }
+ $attributes .= '"';
+
+ if ($this->overall_id != '') {
+ $attributes .= " id=\"{$this->overall_id}\"";
+ }
+ if ($this->overall_style != '' && !$this->use_classes) {
+ $attributes .= ' style="' . $this->overall_style . '"';
+ }
+
+ $ol_attributes = '';
+
+ if ($this->line_numbers_start != 1) {
+ $ol_attributes .= ' start="' . $this->line_numbers_start . '"';
+ }
+
+ // Get the header HTML
+ $header = $this->header_content;
+ if ($header) {
+ if ($this->header_type == GESHI_HEADER_PRE || $this->header_type == GESHI_HEADER_PRE_VALID) {
+ $header = str_replace("\n", '', $header);
+ }
+ $header = $this->replace_keywords($header);
+
+ if ($this->use_classes) {
+ $attr = ' class="head"';
+ } else {
+ $attr = " style=\"{$this->header_content_style}\"";
+ }
+ if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ $header = "<thead><tr><td colspan=\"2\" $attr>$header</td></tr></thead>";
+ } else {
+ $header = "<div$attr>$header</div>";
+ }
+ }
+
+ if (GESHI_HEADER_NONE == $this->header_type) {
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ return "$header<ol$attributes$ol_attributes>";
+ }
+ return $header . ($this->force_code_block ? '<div>' : '');
+ }
+
+ // Work out what to return and do it
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ if ($this->header_type == GESHI_HEADER_PRE) {
+ return "<pre$attributes>$header<ol$ol_attributes>";
+ } elseif ($this->header_type == GESHI_HEADER_DIV ||
+ $this->header_type == GESHI_HEADER_PRE_VALID) {
+ return "<div$attributes>$header<ol$ol_attributes>";
+ } elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) {
+ return "<table$attributes>$header<tbody><tr class=\"li1\">";
+ }
+ } else {
+ if ($this->header_type == GESHI_HEADER_PRE) {
+ return "<pre$attributes>$header" .
+ ($this->force_code_block ? '<div>' : '');
+ } else {
+ return "<div$attributes>$header" .
+ ($this->force_code_block ? '<div>' : '');
+ }
+ }
+ }
+
+ /**
+ * Returns the footer for the code block.
+ *
+ * @return string The footer for the code block
+ * @since 1.0.0
+ * @access private
+ */
+ function footer() {
+ $footer = $this->footer_content;
+ if ($footer) {
+ if ($this->header_type == GESHI_HEADER_PRE) {
+ $footer = str_replace("\n", '', $footer);;
+ }
+ $footer = $this->replace_keywords($footer);
+
+ if ($this->use_classes) {
+ $attr = ' class="foot"';
+ } else {
+ $attr = " style=\"{$this->footer_content_style}\"";
+ }
+ if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ $footer = "<tfoot><tr><td colspan=\"2\">$footer</td></tr></tfoot>";
+ } else {
+ $footer = "<div$attr>$footer</div>";
+ }
+ }
+
+ if (GESHI_HEADER_NONE == $this->header_type) {
+ return ($this->line_numbers != GESHI_NO_LINE_NUMBERS) ? '</ol>' . $footer : $footer;
+ }
+
+ if ($this->header_type == GESHI_HEADER_DIV || $this->header_type == GESHI_HEADER_PRE_VALID) {
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ return "</ol>$footer</div>";
+ }
+ return ($this->force_code_block ? '</div>' : '') .
+ "$footer</div>";
+ }
+ elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) {
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ return "</tr></tbody>$footer</table>";
+ }
+ return ($this->force_code_block ? '</div>' : '') .
+ "$footer</div>";
+ }
+ else {
+ if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ return "</ol>$footer</pre>";
+ }
+ return ($this->force_code_block ? '</div>' : '') .
+ "$footer</pre>";
+ }
+ }
+
+ /**
+ * Replaces certain keywords in the header and footer with
+ * certain configuration values
+ *
+ * @param string The header or footer content to do replacement on
+ * @return string The header or footer with replaced keywords
+ * @since 1.0.2
+ * @access private
+ */
+ function replace_keywords($instr) {
+ $keywords = $replacements = array();
+
+ $keywords[] = '<TIME>';
+ $keywords[] = '{TIME}';
+ $replacements[] = $replacements[] = number_format($time = $this->get_time(), 3);
+
+ $keywords[] = '<LANGUAGE>';
+ $keywords[] = '{LANGUAGE}';
+ $replacements[] = $replacements[] = $this->language_data['LANG_NAME'];
+
+ $keywords[] = '<VERSION>';
+ $keywords[] = '{VERSION}';
+ $replacements[] = $replacements[] = GESHI_VERSION;
+
+ $keywords[] = '<SPEED>';
+ $keywords[] = '{SPEED}';
+ if ($time <= 0) {
+ $speed = 'N/A';
+ } else {
+ $speed = strlen($this->source) / $time;
+ if ($speed >= 1024) {
+ $speed = sprintf("%.2f KB/s", $speed / 1024.0);
+ } else {
+ $speed = sprintf("%.0f B/s", $speed);
+ }
+ }
+ $replacements[] = $replacements[] = $speed;
+
+ return str_replace($keywords, $replacements, $instr);
+ }
+
+ /**
+ * Secure replacement for PHP built-in function htmlspecialchars().
+ *
+ * See ticket #427 (http://wush.net/trac/wikka/ticket/427) for the rationale
+ * for this replacement function.
+ *
+ * The INTERFACE for this function is almost the same as that for
+ * htmlspecialchars(), with the same default for quote style; however, there
+ * is no 'charset' parameter. The reason for this is as follows:
+ *
+ * The PHP docs say:
+ * "The third argument charset defines character set used in conversion."
+ *
+ * I suspect PHP's htmlspecialchars() is working at the byte-value level and
+ * thus _needs_ to know (or asssume) a character set because the special
+ * characters to be replaced could exist at different code points in
+ * different character sets. (If indeed htmlspecialchars() works at
+ * byte-value level that goes some way towards explaining why the
+ * vulnerability would exist in this function, too, and not only in
+ * htmlentities() which certainly is working at byte-value level.)
+ *
+ * This replacement function however works at character level and should
+ * therefore be "immune" to character set differences - so no charset
+ * parameter is needed or provided. If a third parameter is passed, it will
+ * be silently ignored.
+ *
+ * In the OUTPUT there is a minor difference in that we use '&#39;' instead
+ * of PHP's '&#039;' for a single quote: this provides compatibility with
+ * get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES)
+ * (see comment by mikiwoz at yahoo dot co dot uk on
+ * http://php.net/htmlspecialchars); it also matches the entity definition
+ * for XML 1.0
+ * (http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters).
+ * Like PHP we use a numeric character reference instead of '&apos;' for the
+ * single quote. For the other special characters we use the named entity
+ * references, as PHP is doing.
+ *
+ * @author {@link http://wikkawiki.org/JavaWoman Marjolein Katsma}
+ *
+ * @license http://www.gnu.org/copyleft/lgpl.html
+ * GNU Lesser General Public License
+ * @copyright Copyright 2007, {@link http://wikkawiki.org/CreditsPage
+ * Wikka Development Team}
+ *
+ * @access private
+ * @param string $string string to be converted
+ * @param integer $quote_style
+ * - ENT_COMPAT: escapes &, <, > and double quote (default)
+ * - ENT_NOQUOTES: escapes only &, < and >
+ * - ENT_QUOTES: escapes &, <, >, double and single quotes
+ * @return string converted string
+ * @since 1.0.7.18
+ */
+ function hsc($string, $quote_style = ENT_COMPAT) {
+ // init
+ static $aTransSpecchar = array(
+ '&' => '&amp;',
+ '"' => '&quot;',
+ '<' => '&lt;',
+ '>' => '&gt;',
+
+ //This fix is related to SF#1923020, but has to be applied
+ //regardless of actually highlighting symbols.
+
+ //Circumvent a bug with symbol highlighting
+ //This is required as ; would produce undesirable side-effects if it
+ //was not to be processed as an entity.
+ ';' => '<SEMI>', // Force ; to be processed as entity
+ '|' => '<PIPE>' // Force | to be processed as entity
+ ); // ENT_COMPAT set
+
+ switch ($quote_style) {
+ case ENT_NOQUOTES: // don't convert double quotes
+ unset($aTransSpecchar['"']);
+ break;
+ case ENT_QUOTES: // convert single quotes as well
+ $aTransSpecchar["'"] = '&#39;'; // (apos) htmlspecialchars() uses '&#039;'
+ break;
+ }
+
+ // return translated string
+ return strtr($string, $aTransSpecchar);
+ }
+
+ function _genCSSName($name){
+ return (is_numeric($name[0]) ? '_' : '') . $name;
+ }
+
+ /**
+ * Returns a stylesheet for the highlighted code. If $economy mode
+ * is true, we only return the stylesheet declarations that matter for
+ * this code block instead of the whole thing
+ *
+ * @param boolean Whether to use economy mode or not
+ * @return string A stylesheet built on the data for the current language
+ * @since 1.0.0
+ */
+ function get_stylesheet($economy_mode = true) {
+ // If there's an error, chances are that the language file
+ // won't have populated the language data file, so we can't
+ // risk getting a stylesheet...
+ if ($this->error) {
+ return '';
+ }
+
+ //Check if the style rearrangements have been processed ...
+ //This also does some preprocessing to check which style groups are useable ...
+ if(!isset($this->language_data['NUMBERS_CACHE'])) {
+ $this->build_style_cache();
+ }
+
+ // First, work out what the selector should be. If there's an ID,
+ // that should be used, the same for a class. Otherwise, a selector
+ // of '' means that these styles will be applied anywhere
+ if ($this->overall_id) {
+ $selector = '#' . $this->_genCSSName($this->overall_id);
+ } else {
+ $selector = '.' . $this->_genCSSName($this->language);
+ if ($this->overall_class) {
+ $selector .= '.' . $this->_genCSSName($this->overall_class);
+ }
+ }
+ $selector .= ' ';
+
+ // Header of the stylesheet
+ if (!$economy_mode) {
+ $stylesheet = "/**\n".
+ " * GeSHi Dynamically Generated Stylesheet\n".
+ " * --------------------------------------\n".
+ " * Dynamically generated stylesheet for {$this->language}\n".
+ " * CSS class: {$this->overall_class}, CSS id: {$this->overall_id}\n".
+ " * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" .
+ " * (http://qbnz.com/highlighter/ and http://geshi.org/)\n".
+ " * --------------------------------------\n".
+ " */\n";
+ } else {
+ $stylesheet = "/**\n".
+ " * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" .
+ " * (http://qbnz.com/highlighter/ and http://geshi.org/)\n".
+ " */\n";
+ }
+
+ // Set the <ol> to have no effect at all if there are line numbers
+ // (<ol>s have margins that should be destroyed so all layout is
+ // controlled by the set_overall_style method, which works on the
+ // <pre> or <div> container). Additionally, set default styles for lines
+ if (!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) {
+ //$stylesheet .= "$selector, {$selector}ol, {$selector}ol li {margin: 0;}\n";
+ $stylesheet .= "$selector.de1, $selector.de2 {{$this->code_style}}\n";
+ }
+
+ // Add overall styles
+ // note: neglect economy_mode, empty styles are meaningless
+ if ($this->overall_style != '') {
+ $stylesheet .= "$selector {{$this->overall_style}}\n";
+ }
+
+ // Add styles for links
+ // note: economy mode does not make _any_ sense here
+ // either the style is empty and thus no selector is needed
+ // or the appropriate key is given.
+ foreach ($this->link_styles as $key => $style) {
+ if ($style != '') {
+ switch ($key) {
+ case GESHI_LINK:
+ $stylesheet .= "{$selector}a:link {{$style}}\n";
+ break;
+ case GESHI_HOVER:
+ $stylesheet .= "{$selector}a:hover {{$style}}\n";
+ break;
+ case GESHI_ACTIVE:
+ $stylesheet .= "{$selector}a:active {{$style}}\n";
+ break;
+ case GESHI_VISITED:
+ $stylesheet .= "{$selector}a:visited {{$style}}\n";
+ break;
+ }
+ }
+ }
+
+ // Header and footer
+ // note: neglect economy_mode, empty styles are meaningless
+ if ($this->header_content_style != '') {
+ $stylesheet .= "$selector.head {{$this->header_content_style}}\n";
+ }
+ if ($this->footer_content_style != '') {
+ $stylesheet .= "$selector.foot {{$this->footer_content_style}}\n";
+ }
+
+ // Styles for important stuff
+ // note: neglect economy_mode, empty styles are meaningless
+ if ($this->important_styles != '') {
+ $stylesheet .= "$selector.imp {{$this->important_styles}}\n";
+ }
+
+ // Simple line number styles
+ if ((!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) && $this->line_style1 != '') {
+ $stylesheet .= "{$selector}li, {$selector}.li1 {{$this->line_style1}}\n";
+ }
+ if ((!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) && $this->table_linenumber_style != '') {
+ $stylesheet .= "{$selector}.ln {{$this->table_linenumber_style}}\n";
+ }
+ // If there is a style set for fancy line numbers, echo it out
+ if ((!$economy_mode || $this->line_numbers == GESHI_FANCY_LINE_NUMBERS) && $this->line_style2 != '') {
+ $stylesheet .= "{$selector}.li2 {{$this->line_style2}}\n";
+ }
+
+ // note: empty styles are meaningless
+ foreach ($this->language_data['STYLES']['KEYWORDS'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode ||
+ (isset($this->lexic_permissions['KEYWORDS'][$group]) &&
+ $this->lexic_permissions['KEYWORDS'][$group]))) {
+ $stylesheet .= "$selector.kw$group {{$styles}}\n";
+ }
+ }
+ foreach ($this->language_data['STYLES']['COMMENTS'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode ||
+ (isset($this->lexic_permissions['COMMENTS'][$group]) &&
+ $this->lexic_permissions['COMMENTS'][$group]) ||
+ (!empty($this->language_data['COMMENT_REGEXP']) &&
+ !empty($this->language_data['COMMENT_REGEXP'][$group])))) {
+ $stylesheet .= "$selector.co$group {{$styles}}\n";
+ }
+ }
+ foreach ($this->language_data['STYLES']['ESCAPE_CHAR'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode || $this->lexic_permissions['ESCAPE_CHAR'])) {
+ // NEW: since 1.0.8 we have to handle hardescapes
+ if ($group === 'HARD') {
+ $group = '_h';
+ }
+ $stylesheet .= "$selector.es$group {{$styles}}\n";
+ }
+ }
+ foreach ($this->language_data['STYLES']['BRACKETS'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode || $this->lexic_permissions['BRACKETS'])) {
+ $stylesheet .= "$selector.br$group {{$styles}}\n";
+ }
+ }
+ foreach ($this->language_data['STYLES']['SYMBOLS'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode || $this->lexic_permissions['SYMBOLS'])) {
+ $stylesheet .= "$selector.sy$group {{$styles}}\n";
+ }
+ }
+ foreach ($this->language_data['STYLES']['STRINGS'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode || $this->lexic_permissions['STRINGS'])) {
+ // NEW: since 1.0.8 we have to handle hardquotes
+ if ($group === 'HARD') {
+ $group = '_h';
+ }
+ $stylesheet .= "$selector.st$group {{$styles}}\n";
+ }
+ }
+ foreach ($this->language_data['STYLES']['NUMBERS'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode || $this->lexic_permissions['NUMBERS'])) {
+ $stylesheet .= "$selector.nu$group {{$styles}}\n";
+ }
+ }
+ foreach ($this->language_data['STYLES']['METHODS'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode || $this->lexic_permissions['METHODS'])) {
+ $stylesheet .= "$selector.me$group {{$styles}}\n";
+ }
+ }
+ // note: neglect economy_mode, empty styles are meaningless
+ foreach ($this->language_data['STYLES']['SCRIPT'] as $group => $styles) {
+ if ($styles != '') {
+ $stylesheet .= "$selector.sc$group {{$styles}}\n";
+ }
+ }
+ foreach ($this->language_data['STYLES']['REGEXPS'] as $group => $styles) {
+ if ($styles != '' && (!$economy_mode ||
+ (isset($this->lexic_permissions['REGEXPS'][$group]) &&
+ $this->lexic_permissions['REGEXPS'][$group]))) {
+ if (is_array($this->language_data['REGEXPS'][$group]) &&
+ array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$group])) {
+ $stylesheet .= "$selector.";
+ $stylesheet .= $this->language_data['REGEXPS'][$group][GESHI_CLASS];
+ $stylesheet .= " {{$styles}}\n";
+ } else {
+ $stylesheet .= "$selector.re$group {{$styles}}\n";
+ }
+ }
+ }
+ // Styles for lines being highlighted extra
+ if (!$economy_mode || (count($this->highlight_extra_lines)!=count($this->highlight_extra_lines_styles))) {
+ $stylesheet .= "{$selector}.ln-xtra, {$selector}li.ln-xtra, {$selector}div.ln-xtra {{$this->highlight_extra_lines_style}}\n";
+ }
+ $stylesheet .= "{$selector}span.xtra { display:block; }\n";
+ foreach ($this->highlight_extra_lines_styles as $lineid => $linestyle) {
+ $stylesheet .= "{$selector}.lx$lineid, {$selector}li.lx$lineid, {$selector}div.lx$lineid {{$linestyle}}\n";
+ }
+
+ return $stylesheet;
+ }
+
+ /**
+ * Get's the style that is used for the specified line
+ *
+ * @param int The line number information is requested for
+ * @access private
+ * @since 1.0.7.21
+ */
+ function get_line_style($line) {
+ //$style = null;
+ $style = null;
+ if (isset($this->highlight_extra_lines_styles[$line])) {
+ $style = $this->highlight_extra_lines_styles[$line];
+ } else { // if no "extra" style assigned
+ $style = $this->highlight_extra_lines_style;
+ }
+
+ return $style;
+ }
+
+ /**
+ * this functions creates an optimized regular expression list
+ * of an array of strings.
+ *
+ * Example:
+ * <code>$list = array('faa', 'foo', 'foobar');
+ * => string 'f(aa|oo(bar)?)'</code>
+ *
+ * @param $list array of (unquoted) strings
+ * @param $regexp_delimiter your regular expression delimiter, @see preg_quote()
+ * @return string for regular expression
+ * @author Milian Wolff <mail@milianw.de>
+ * @since 1.0.8
+ * @access private
+ */
+ function optimize_regexp_list($list, $regexp_delimiter = '/') {
+ $regex_chars = array('.', '\\', '+', '-', '*', '?', '[', '^', ']', '$',
+ '(', ')', '{', '}', '=', '!', '<', '>', '|', ':', $regexp_delimiter);
+ sort($list);
+ $regexp_list = array('');
+ $num_subpatterns = 0;
+ $list_key = 0;
+
+ // the tokens which we will use to generate the regexp list
+ $tokens = array();
+ $prev_keys = array();
+ // go through all entries of the list and generate the token list
+ $cur_len = 0;
+ for ($i = 0, $i_max = count($list); $i < $i_max; ++$i) {
+ if ($cur_len > GESHI_MAX_PCRE_LENGTH) {
+ // seems like the length of this pcre is growing exorbitantly
+ $regexp_list[++$list_key] = $this->_optimize_regexp_list_tokens_to_string($tokens);
+ $num_subpatterns = substr_count($regexp_list[$list_key], '(?:');
+ $tokens = array();
+ $cur_len = 0;
+ }
+ $level = 0;
+ $entry = preg_quote((string) $list[$i], $regexp_delimiter);
+ $pointer = &$tokens;
+ // properly assign the new entry to the correct position in the token array
+ // possibly generate smaller common denominator keys
+ while (true) {
+ // get the common denominator
+ if (isset($prev_keys[$level])) {
+ if ($prev_keys[$level] == $entry) {
+ // this is a duplicate entry, skip it
+ continue 2;
+ }
+ $char = 0;
+ while (isset($entry[$char]) && isset($prev_keys[$level][$char])
+ && $entry[$char] == $prev_keys[$level][$char]) {
+ ++$char;
+ }
+ if ($char > 0) {
+ // this entry has at least some chars in common with the current key
+ if ($char == strlen($prev_keys[$level])) {
+ // current key is totally matched, i.e. this entry has just some bits appended
+ $pointer = &$pointer[$prev_keys[$level]];
+ } else {
+ // only part of the keys match
+ $new_key_part1 = substr($prev_keys[$level], 0, $char);
+ $new_key_part2 = substr($prev_keys[$level], $char);
+
+ if (in_array($new_key_part1[0], $regex_chars)
+ || in_array($new_key_part2[0], $regex_chars)) {
+ // this is bad, a regex char as first character
+ $pointer[$entry] = array('' => true);
+ array_splice($prev_keys, $level, count($prev_keys), $entry);
+ $cur_len += strlen($entry);
+ continue;
+ } else {
+ // relocate previous tokens
+ $pointer[$new_key_part1] = array($new_key_part2 => $pointer[$prev_keys[$level]]);
+ unset($pointer[$prev_keys[$level]]);
+ $pointer = &$pointer[$new_key_part1];
+ // recreate key index
+ array_splice($prev_keys, $level, count($prev_keys), array($new_key_part1, $new_key_part2));
+ $cur_len += strlen($new_key_part2);
+ }
+ }
+ ++$level;
+ $entry = substr($entry, $char);
+ continue;
+ }
+ // else: fall trough, i.e. no common denominator was found
+ }
+ if ($level == 0 && !empty($tokens)) {
+ // we can dump current tokens into the string and throw them away afterwards
+ $new_entry = $this->_optimize_regexp_list_tokens_to_string($tokens);
+ $new_subpatterns = substr_count($new_entry, '(?:');
+ if (GESHI_MAX_PCRE_SUBPATTERNS && $num_subpatterns + $new_subpatterns > GESHI_MAX_PCRE_SUBPATTERNS) {
+ $regexp_list[++$list_key] = $new_entry;
+ $num_subpatterns = $new_subpatterns;
+ } else {
+ if (!empty($regexp_list[$list_key])) {
+ $new_entry = '|' . $new_entry;
+ }
+ $regexp_list[$list_key] .= $new_entry;
+ $num_subpatterns += $new_subpatterns;
+ }
+ $tokens = array();
+ $cur_len = 0;
+ }
+ // no further common denominator found
+ $pointer[$entry] = array('' => true);
+ array_splice($prev_keys, $level, count($prev_keys), $entry);
+
+ $cur_len += strlen($entry);
+ break;
+ }
+ unset($list[$i]);
+ }
+ // make sure the last tokens get converted as well
+ $new_entry = $this->_optimize_regexp_list_tokens_to_string($tokens);
+ if (GESHI_MAX_PCRE_SUBPATTERNS && $num_subpatterns + substr_count($new_entry, '(?:') > GESHI_MAX_PCRE_SUBPATTERNS) {
+ if ( !empty($regexp_list[$list_key]) ) {
+ ++$list_key;
+ }
+ $regexp_list[$list_key] = $new_entry;
+ } else {
+ if (!empty($regexp_list[$list_key])) {
+ $new_entry = '|' . $new_entry;
+ }
+ $regexp_list[$list_key] .= $new_entry;
+ }
+ return $regexp_list;
+ }
+ /**
+ * this function creates the appropriate regexp string of an token array
+ * you should not call this function directly, @see $this->optimize_regexp_list().
+ *
+ * @param &$tokens array of tokens
+ * @param $recursed bool to know wether we recursed or not
+ * @return string
+ * @author Milian Wolff <mail@milianw.de>
+ * @since 1.0.8
+ * @access private
+ */
+ function _optimize_regexp_list_tokens_to_string(&$tokens, $recursed = false) {
+ $list = '';
+ foreach ($tokens as $token => $sub_tokens) {
+ $list .= $token;
+ $close_entry = isset($sub_tokens['']);
+ unset($sub_tokens['']);
+ if (!empty($sub_tokens)) {
+ $list .= '(?:' . $this->_optimize_regexp_list_tokens_to_string($sub_tokens, true) . ')';
+ if ($close_entry) {
+ // make sub_tokens optional
+ $list .= '?';
+ }
+ }
+ $list .= '|';
+ }
+ if (!$recursed) {
+ // do some optimizations
+ // common trailing strings
+ // BUGGY!
+ //$list = preg_replace_callback('#(?<=^|\:|\|)\w+?(\w+)(?:\|.+\1)+(?=\|)#', create_function(
+ // '$matches', 'return "(?:" . preg_replace("#" . preg_quote($matches[1], "#") . "(?=\||$)#", "", $matches[0]) . ")" . $matches[1];'), $list);
+ // (?:p)? => p?
+ $list = preg_replace('#\(\?\:(.)\)\?#', '\1?', $list);
+ // (?:a|b|c|d|...)? => [abcd...]?
+ // TODO: a|bb|c => [ac]|bb
+ static $callback_2;
+ if (!isset($callback_2)) {
+ $callback_2 = create_function('$matches', 'return "[" . str_replace("|", "", $matches[1]) . "]";');
+ }
+ $list = preg_replace_callback('#\(\?\:((?:.\|)+.)\)#', $callback_2, $list);
+ }
+ // return $list without trailing pipe
+ return substr($list, 0, -1);
+ }
+} // End Class GeSHi
+
+
+if (!function_exists('geshi_highlight')) {
+ /**
+ * Easy way to highlight stuff. Behaves just like highlight_string
+ *
+ * @param string The code to highlight
+ * @param string The language to highlight the code in
+ * @param string The path to the language files. You can leave this blank if you need
+ * as from version 1.0.7 the path should be automatically detected
+ * @param boolean Whether to return the result or to echo
+ * @return string The code highlighted (if $return is true)
+ * @since 1.0.2
+ */
+ function geshi_highlight($string, $language, $path = null, $return = false) {
+ $geshi = new GeSHi($string, $language, $path);
+ $geshi->set_header_type(GESHI_HEADER_NONE);
+
+ if ($return) {
+ return '<code>' . $geshi->parse_code() . '</code>';
+ }
+
+ echo '<code>' . $geshi->parse_code() . '</code>';
+
+ if ($geshi->error()) {
+ return false;
+ }
+ return true;
+ }
+}
+
?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/4cs.php b/plugins/wp-syntax/geshi/geshi/4cs.php
index c00792e6..5209c51e 100644
--- a/plugins/wp-syntax/geshi/geshi/4cs.php
+++ b/plugins/wp-syntax/geshi/geshi/4cs.php
@@ -4,7 +4,7 @@
* ------
* Author: Jason Curl (jason.curl@continental-corporation.com)
* Copyright: (c) 2009 Jason Curl
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/09/05
*
* 4CS language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/6502acme.php b/plugins/wp-syntax/geshi/geshi/6502acme.php
index 07f9eaf9..203e04df 100644
--- a/plugins/wp-syntax/geshi/geshi/6502acme.php
+++ b/plugins/wp-syntax/geshi/geshi/6502acme.php
@@ -4,7 +4,7 @@
* -------
* Author: Warren Willmey
* Copyright: (c) 2010 Warren Willmey.
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/05/26
*
* MOS 6502 (more specifically 6510) ACME Cross Assembler 0.93 by Marco Baye language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/6502kickass.php b/plugins/wp-syntax/geshi/geshi/6502kickass.php
index f4a4bd86..80428262 100644
--- a/plugins/wp-syntax/geshi/geshi/6502kickass.php
+++ b/plugins/wp-syntax/geshi/geshi/6502kickass.php
@@ -4,7 +4,7 @@
* -------
* Author: Warren Willmey
* Copyright: (c) 2010 Warren Willmey.
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/06/07
*
* MOS 6502 (6510) Kick Assembler 3.13 language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/6502tasm.php b/plugins/wp-syntax/geshi/geshi/6502tasm.php
index 391e0170..86aa479d 100644
--- a/plugins/wp-syntax/geshi/geshi/6502tasm.php
+++ b/plugins/wp-syntax/geshi/geshi/6502tasm.php
@@ -4,7 +4,7 @@
* -------
* Author: Warren Willmey
* Copyright: (c) 2010 Warren Willmey.
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/06/02
*
* MOS 6502 (6510) TASM/64TASS (64TASS being the super set of TASM) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/68000devpac.php b/plugins/wp-syntax/geshi/geshi/68000devpac.php
index d0f3a507..f46387ae 100644
--- a/plugins/wp-syntax/geshi/geshi/68000devpac.php
+++ b/plugins/wp-syntax/geshi/geshi/68000devpac.php
@@ -4,7 +4,7 @@
* -------
* Author: Warren Willmey
* Copyright: (c) 2010 Warren Willmey.
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/06/09
*
* Motorola 68000 - HiSoft Devpac ST 2 Assembler language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/abap.php b/plugins/wp-syntax/geshi/geshi/abap.php
index 8b510df0..5acd261c 100644
--- a/plugins/wp-syntax/geshi/geshi/abap.php
+++ b/plugins/wp-syntax/geshi/geshi/abap.php
@@ -7,7 +7,7 @@
* - Sandra Rossi (sandra.rossi@gmail.com)
* - Jacob Laursen (jlu@kmd.dk)
* Copyright: (c) 2007 Andres Picazo
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* ABAP language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/actionscript.php b/plugins/wp-syntax/geshi/geshi/actionscript.php
index 276cf4fe..08e5b49a 100644
--- a/plugins/wp-syntax/geshi/geshi/actionscript.php
+++ b/plugins/wp-syntax/geshi/geshi/actionscript.php
@@ -4,7 +4,7 @@
* ----------------
* Author: Steffen Krause (Steffen.krause@muse.de)
* Copyright: (c) 2004 Steffen Krause, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/20
*
* Actionscript language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/actionscript3.php b/plugins/wp-syntax/geshi/geshi/actionscript3.php
index ceaa61d1..189d714b 100644
--- a/plugins/wp-syntax/geshi/geshi/actionscript3.php
+++ b/plugins/wp-syntax/geshi/geshi/actionscript3.php
@@ -4,7 +4,7 @@
* ----------------
* Author: Jordi Boggiano (j.boggiano@seld.be)
* Copyright: (c) 2007 Jordi Boggiano (http://www.seld.be/), Benny Baumann (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/11/26
*
* ActionScript3 language file for GeSHi.
@@ -60,7 +60,7 @@ $language_data = array (
'COMMENT_MULTI' => array('/*' => '*/'),
'COMMENT_REGEXP' => array(
//Regular expressions
- 2 => "/(?<=[\\s^])(s|tr|y)\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/(?:\\\\.|(?!\n)[^\\/\\\\])*\\/[msixpogcde]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])(m|q[qrwx]?)?\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[msixpogc]*(?=[\\s$\\.\\,\\;\\)])/iU",
+ 2 => "/(?<=[\\s^])(s|tr|y)\\/(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])+(?<!\s)\\/(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])*(?<!\s)\\/[msixpogcde]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])(m|q[qrwx]?)?\\/(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])+(?<!\s)\\/[msixpogc]*(?=[\\s$\\.\\,\\;\\)])/iU",
),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
@@ -72,7 +72,7 @@ $language_data = array (
'private', 'null', 'new', 'is', 'internal', 'instanceof', 'in',
'import', 'if', 'get', 'for', 'false', 'else', 'each', 'do',
'delete', 'default', 'continue', 'catch', 'case', 'break', 'as',
- 'extends'
+ 'extends', 'override'
),
2 => array(
'var'
diff --git a/plugins/wp-syntax/geshi/geshi/ada.php b/plugins/wp-syntax/geshi/geshi/ada.php
index eb98c978..c4ef2c39 100644
--- a/plugins/wp-syntax/geshi/geshi/ada.php
+++ b/plugins/wp-syntax/geshi/geshi/ada.php
@@ -4,7 +4,7 @@
* -------
* Author: Tux (tux@inmail.cz)
* Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/29
*
* Ada language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/algol68.php b/plugins/wp-syntax/geshi/geshi/algol68.php
index e9f19da4..5b1e5aa7 100644
--- a/plugins/wp-syntax/geshi/geshi/algol68.php
+++ b/plugins/wp-syntax/geshi/geshi/algol68.php
@@ -1,49 +1,147 @@
<?php
-/**
+/*************************************************************************************
* algol68.php
* --------
* Author: Neville Dempsey (NevilleD.sourceforge@sgr-a.net)
* Copyright: (c) 2010 Neville Dempsey (https://sourceforge.net/projects/algol68/files/)
- * Release Version: v.v.v.v
+ * Release Version: 1.0.8.11
* Date Started: 2010/04/24
*
* ALGOL 68 language file for GeSHi.
*
* CHANGES
* -------
- * yyyy/mm/dd (v.v.v.v)
- * - First Release
+ * 2010/04/24 (1.0.8.8.0)
+ * - First Release - machine generated by http://rosettacode.org/geshi/
+ * 2010/05/24 (1.0.8.8.1)
+ * - #2324 - converted comment detection to RegEx
+ * 2010/06/16 (1.0.8.8.2)
+ * - separate symbols from keywords - quick fix
+ * 2010/06/16 (1.0.8.8.3)
+ * - reverse length order symbols
+ * - Add RegEx for BITS and REAL literals (INT to do)
+ * - recognise LONG and SHORT prefixes to literals
+ * 2010/07/23 (1.0.8.8.4)
+ * - fix errors detected by langcheck.php, eg rm tab, fix indenting, rm duplicate keywords, fix symbols as keywords etc
+ * - removed bulk of local variables from name space.
+ * - unfolded arrays
*
* TODO (updated yyyy/mm/dd)
* -------------------------
+ * - Use "Parser Control" to fix KEYWORD parsing, eg: (INT minus one= -1; print(ABSminus one))
+ * - Parse $FORMATS$ more fully - if possible.
+ * - Pull reserved words from the source of A68G and A68RS
+ * - Pull stdlib PROC/OP/MODE symbols from the soruce of A68G and A68RS
+ * - Pull PROC/OP/MODE extensions from the soruce of A68G and A68RS
+ * - Use RegEx to detect extended precision PROC names, eg 'long long sin' etc
+ * - Use RegEx to detect white space std PROC names, eg 'new line'
+ * - Use RegEx to detect white space ext PROC names, eg 'cgs speed of light'
+ * - Use RegEx to detect BOLD symbols, eg userdefined MODEs and OPs
+ * - Add REgEx for INT literals - Adding INT breaks formatting...
+ * - Adding PIPE as a key word breaks formatting of "|" symbols!!
*
+ *************************************************************************************
*
+ * This file is part of GeSHi.
*
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
*
- * This file is part of GeSHi.
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * GeSHi is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * GeSHi is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GeSHi; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+ ************************************************************************************/
+
+if(!function_exists('geshi_langfile_algol68_vars')) {
+ function geshi_langfile_algol68_vars(){
+ $pre='(?<![0-9a-z_\.])';
+ $post='?(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)';
+ $post=""; # assuming the RegEx is greedy #
+
+ $_="\s*";
+
+ $srad="Rr"; $rrad="[".$srad."]"; # either one digit, OR opt-space in digits #
+ $sbin="0-1"; $rbin="[".$sbin."]"; $_bin=$rbin."(?:[".$sbin."\s]*".$rbin."|)";
+ $snib="0-3"; $rnib="[".$snib."]"; $_nib=$rnib."(?:[".$snib."\s]*".$rnib."|)";
+ $soct="0-7"; $roct="[".$soct."]"; $_oct=$roct."(?:[".$soct."\s]*".$roct."|)";
+ $sdec="0-9"; $rdec="[".$sdec."]"; $_dec=$rdec."(?:[".$sdec."\s]*".$rdec."|)";
+ $shex="0-9A-Fa-f"; $rhex="[".$shex."]"; $_hex=$rhex."(?:[".$shex."\s]*".$rhex."|)";
+
+ # Define BITS: #
+ $prebits=$pre; $postbits=$post;
+ $bl="2".$_.$rrad.$_.$_bin;
+ $bl=$bl."|"."2".$_.$rrad.$_.$_bin;
+ $bl=$bl."|"."4".$_.$rrad.$_.$_nib;
+ $bl=$bl."|"."8".$_.$rrad.$_.$_oct;
+ $bl=$bl."|"."1".$_."0".$_.$rrad.$_.$_dec;
+ $bl=$bl."|"."1".$_."6".$_.$rrad.$_.$_hex;
+
+ # Define INT: #
+ $preint=$pre; $postint=$post;
+ # for some reason ".0 e - 2" is not recognised, but ".0 e + 2" IS!
+ # work around: remove spaces between sign and digits! Maybe because
+ # of the Unary '-' Operator
+ $sign_="(?:-|\-|[-]|[\-]|\+|)"; # attempts #
+
+ $sign_="(?:-\s*|\+\s*|)"; # n.b. sign is followed by white space #
+
+ $_int=$sign_.$_dec;
+ $il= $_int; # +_9 #
+
+ $GESHI_NUMBER_INT_BASIC='(?:(?<![0-9a-z_\.%])|(?<=\.\.))(?<![\d\.]e[+\-])([1-9]\d*?|0)(?![0-9a-z]|\.(?:[eE][+\-]?)?\d)';
+
+ # Define REAL: #
+ $prereal=$pre; $postreal=$post;
+ $sexp="Ee\\\\"; $_exp="(?:â¨|[".$sexp."])".$_.$_int;
+ $_decimal="[.]".$_.$_dec;
+
+ # Add permitted permutations of various parts #
+ $rl= $_int.$_.$_decimal.$_.$_exp; # +_9_._9_e_+_9 #
+ $rl=$rl."|".$_int.$_."[.]".$_.$_exp; # +_9_.___e_+_9 #
+ $rl=$rl."|".$_int.$_.$_exp; # +_9_____e_+_9 #
+ $rl=$rl."|".$sign_.$_decimal.$_.$_exp; # +___._9_e_+_9 #
+
+ $rl=$rl."|".$_int.$_.$_decimal; # +_9_._9 #
+ $rl=$rl."|".$sign_.$_decimal; # +___._9 #
+
+ # The following line damaged formatting...
+ #$rl=$rl."|".$_int; # +_9 #
+
+ # Apparently Algol68 does not support '2.', c.f. Algol 68G
+ #$rl=$rl."|".$_int.$_."[.]"; # +_9_. #
+
+ # Literal prefixes are overridden by KEYWORDS :-(
+ $LONGS="(?:(?:(LONG\s+)*|(SHORT\s+))*|)";
+
+ return array(
+ "BITS" => $prebits.$LONGS."(?:".$bl.")".$postbits,
+ "INT" => $preint.$LONGS."(?:".$il.")".$postint,
+ "REAL" => $prereal.$LONGS."(?:".$rl.")".$postreal,
+
+ "BOLD" => 'color: #b1b100; font-weight: bold;',
+ "ITALIC" => 'color: #b1b100;', # procedures traditionally italic #
+ "NONSTD" => 'color: #FF0000; font-weight: bold;', # RED #
+ "COMMENT" => 'color: #666666; font-style: italic;'
+ );
+ }
+}
+$a68=geshi_langfile_algol68_vars();
$language_data = array(
'LANG_NAME' => 'ALGOL 68',
'COMMENT_SINGLE' => array(),
'COMMENT_MULTI' => array(
- '#' => '#',
'¢' => '¢',
'£' => '£',
+ '#' => '#',
),
'COMMENT_REGEXP' => array(
1 => '/\bCO((?:MMENT)?)\b.*?\bCO\\1\b/i',
@@ -53,42 +151,59 @@ $language_data = array(
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"'),
'ESCAPE_CHAR' => '"',
+ 'NUMBERS' => GESHI_NUMBER_HEX_SUFFIX, # Warning: Feature!! #
+# GESHI_NUMBER_HEX_SUFFIX, # Attempt ignore default #
'KEYWORDS' => array(
- 1 => array('KEEP', 'FINISH', 'USE', 'SYSPROCS', 'IOSTATE', 'USING', 'ENVIRON'),
- 2 => array('CASE', 'IN', 'OUSE', 'IN', 'OUT', 'ESAC', '(', '|', '|:', ')', 'FOR', 'FROM', 'TO', 'BY', 'WHILE', 'DO', 'OD', 'IF', 'THEN', 'ELIF', 'THEN', 'ELSE', 'FI', 'PAR', 'BEGIN', 'EXIT', 'END', 'GO', 'GOTO', 'FORALL', 'UPTO', 'DOWNTO', 'FOREACH', 'ASSERT'),
- 3 => array('BITS', 'BOOL', 'BYTES', 'CHAR', 'COMPL', 'INT', 'REAL', 'SEMA', 'STRING', 'VOID', 'COMPLEX', 'VECTOR'),
- 4 => array('MODE', 'OP', 'PRIO', 'PROC'),
- 5 => array('FLEX', 'HEAP', 'LOC', 'LONG', 'REF', 'SHORT', 'EITHER'),
- 6 => array('CHANNEL', 'FILE', 'FORMAT', 'STRUCT', 'UNION'),
- 7 => array('OF', 'AT', '@', 'IS', ':=:', 'ISNT', ':/=:', ':≠:', 'CTB', 'CT', '::', 'CTAB', '::=', 'TRUE', 'FALSE', 'EMPTY', 'NIL', '○', 'SKIP', '~'),
- 8 => array('NOT', 'UP', 'DOWN', 'LWB', 'UPB', '-', 'ABS', 'ARG', 'BIN', 'ENTIER', 'LENG', 'LEVEL', 'ODD', 'REPR', 'ROUND', 'SHORTEN', 'CONJ', 'SIGN'),
- 9 => array('¬', '↑', '↓', '⌊', '⌈', '~', '⎩', '⎧'),
- 10 => array('+*', 'I', '+×', '⊥', '!', 'â¨'),
- 11 => array('SHL', 'SHR', '**', 'UP', 'DOWN', 'LWB', 'UPB', '↑', '↓', '⌊', '⌈', '⎩', '⎧'),
- 12 => array('*', '/', '%', 'OVER', '%*', 'MOD', 'ELEM', '×', '÷', '÷×', '÷*', '%×', '□', '÷:'),
- 13 => array('-', '+'),
- 14 => array('<', 'LT', '<=', 'LE', '>=', 'GE', '>', 'GT', '≤', '≥'),
- 15 => array('=', 'EQ', '/=', 'NE', '≠', '~='),
- 16 => array('&', 'AND', '∧', 'OR', '∨'),
+# Extensions
+ 1 => array('KEEP', 'FINISH', 'USE', 'SYSPROCS', 'IOSTATE', 'USING', 'ENVIRON', 'PROGRAM', 'CONTEXT'),
+# 2 => array('CASE', 'IN', 'OUSE', 'IN', 'OUT', 'ESAC', '(', '|', '|:', ')', 'FOR', 'FROM', 'TO', 'BY', 'WHILE', 'DO', 'OD', 'IF', 'THEN', 'ELIF', 'THEN', 'ELSE', 'FI', 'PAR', 'BEGIN', 'EXIT', 'END', 'GO', 'GOTO', 'FORALL', 'UPTO', 'DOWNTO', 'FOREACH', 'ASSERT'), #
+ 2 => array('CASE', 'IN', 'OUSE', /* 'IN',*/ 'OUT', 'ESAC', 'PAR', 'BEGIN', 'EXIT', 'END', 'GO TO', 'GOTO', 'FOR', 'FROM', 'TO', 'BY', 'WHILE', 'DO', 'OD', 'IF', 'THEN', 'ELIF', /* 'THEN',*/ 'ELSE', 'FI' ),
+ 3 => array('BITS', 'BOOL', 'BYTES', 'CHAR', 'COMPL', 'INT', 'REAL', 'SEMA', 'STRING', 'VOID'),
+ 4 => array('MODE', 'OP', 'PRIO', 'PROC', 'FLEX', 'HEAP', 'LOC', 'REF', 'LONG', 'SHORT', 'EITHER'),
+# Extensions or deprecated keywords
+# 'PIPE': keyword somehow interferes with the internal operation of GeSHi
+ 5 => array('FORALL', 'UPTO', 'DOWNTO', 'FOREACH', 'ASSERT', 'CTB', 'CT', 'CTAB', 'COMPLEX', 'VECTOR', 'SOUND' /*, 'PIPE'*/),
+ 6 => array('CHANNEL', 'FILE', 'FORMAT', 'STRUCT', 'UNION', 'OF'),
+# '(', '|', '|:', ')', #
+# 7 => array('OF', 'AT', '@', 'IS', ':=:', 'ISNT', ':/=:', ':≠:', 'CTB', 'CT', '::', 'CTAB', '::=', 'TRUE', 'FALSE', 'EMPTY', 'NIL', '○', 'SKIP', '~'),
+ 7 => array('AT', 'IS', 'ISNT', 'TRUE', 'FALSE', 'EMPTY', 'NIL', 'SKIP'),
+ 8 => array('NOT', 'UP', 'DOWN', 'LWB', 'UPB', /* '-',*/ 'ABS', 'ARG', 'BIN', 'ENTIER', 'LENG', 'LEVEL', 'ODD', 'REPR', 'ROUND', 'SHORTEN', 'CONJ', 'SIGN'),
+# OPERATORS ordered roughtly by PRIORITY #
+# 9 => array('¬', '↑', '↓', '⌊', '⌈', '~', '⎩', '⎧'),
+# 10 => array('+*', 'I', '+×', '⊥', '!', 'â¨'),
+ 10 => array('I'),
+# 11 => array('SHL', 'SHR', '**', 'UP', 'DOWN', 'LWB', 'UPB', '↑', '↓', '⌊', '⌈', '⎩', '⎧'),
+ 11 => array('SHL', 'SHR', /*'UP', 'DOWN', 'LWB', 'UPB'*/),
+# 12 => array('*', '/', '%', 'OVER', '%*', 'MOD', 'ELEM', '×', '÷', '÷×', '÷*', '%×', '□', '÷:'),
+ 12 => array('OVER', 'MOD', 'ELEM'),
+# 13 => array('-', '+'),
+# 14 => array('<', 'LT', '<=', 'LE', '>=', 'GE', '>', 'GT', '≤', '≥'),
+ 14 => array('LT', 'LE', 'GE', 'GT'),
+# 15 => array('=', 'EQ', '/=', 'NE', '≠', '~='),
+ 15 => array('EQ', 'NE'),
+# 16 => array('&', 'AND', '∧', 'OR', '∨', '/\\', '\\/'),
+ 16 => array('AND', 'OR'),
17 => array('MINUSAB', 'PLUSAB', 'TIMESAB', 'DIVAB', 'OVERAB', 'MODAB', 'PLUSTO'),
- 18 => array('-:=', '+:=', '*:=', '/:=', '%:=', '%*:=', '+=:', '×:=', '÷:=', '÷×:=', '÷*:=', '%×:=', '÷::=', 'MINUS', 'PLUS', 'DIV', 'MOD', 'PRUS'),
+# 18 => array('-:=', '+:=', '*:=', '/:=', '%:=', '%*:=', '+=:', '×:=', '÷:=', '÷×:=', '÷*:=', '%×:=', '÷::=', 'MINUS', 'PLUS', 'DIV', 'MOD', 'PRUS'),
+# Extensions or deprecated keywords
+ 18 => array('MINUS', 'PLUS', 'DIV', /* 'MOD',*/ 'PRUS', 'IS NOT'),
+# Extensions or deprecated keywords
19 => array('THEF', 'ANDF', 'ORF', 'ANDTH', 'OREL', 'ANDTHEN', 'ORELSE'),
- 20 => array('int_lengths', 'intlengths', 'int_shorths', 'intshorths', 'max_int', 'maxint', 'real_lengths', 'reallengths', 'real_shorths', 'realshorths', 'bits_lengths', 'bitslengths', 'bits_shorths', 'bitsshorths', 'bytes_lengths', 'byteslengths', 'bytes_shorths', 'bytesshorths', 'max_abs_char', 'maxabschar', 'int_width', 'intwidth', 'long_int_width', 'longintwidth', 'long_long_int_width', 'longlongintwidth', 'real_width', 'realwidth', 'long_real_width', 'longrealwidth', 'long_long_real_width', 'longlongrealwidth', 'exp_width', 'expwidth', 'long_exp_width', 'longexpwidth', 'long_long_exp_width', 'longlongexpwidth', 'bits_width', 'bitswidth', 'long_bits_width', 'longbitswidth', 'long_long_bits_width', 'longlongbitswidth', 'bytes_width', 'byteswidth', 'long_bytes_width', 'longbyteswidth', 'max_real', 'maxreal', 'small_real', 'smallreal', 'long_max_int', 'longmaxint', 'long_long_max_int', 'longlongmaxint', 'long_max_real', 'longmaxreal', 'long_small_real', 'longsmallreal', 'long_long_max_real', 'longlongmaxreal', 'long_long_small_real', 'longlongsmallreal', 'long_max_bits', 'longmaxbits', 'long_long_max_bits', 'longlongmaxbits', 'null_character', 'nullcharacter', 'blank', 'flip', 'flop', 'error_char', 'errorchar', 'exp_char', 'expchar', 'newline_char', 'newlinechar', 'formfeed_char', 'formfeedchar', 'tab_char', 'tabchar'),
- 21 => array('stand_in_channel', 'standinchannel', 'stand_out_channel', 'standoutchannel', 'stand_back_channel', 'standbackchannel', 'stand_draw_channel', 'standdrawchannel', 'stand_error_channel', 'standerrorchannel'),
- 22 => array('put_possible', 'putpossible', 'get_possible', 'getpossible', 'bin_possible', 'binpossible', 'set_possible', 'setpossible', 'reset_possible', 'resetpossible', 'reidf_possible', 'reidfpossible', 'draw_possible', 'drawpossible', 'compressible', 'on_logical_file_end', 'onlogicalfileend', 'on_physical_file_end', 'onphysicalfileend', 'on_line_end', 'onlineend', 'on_page_end', 'onpageend', 'on_format_end', 'onformatend', 'on_value_error', 'onvalueerror', 'on_open_error', 'onopenerror', 'on_transput_error', 'ontransputerror', 'on_format_error', 'onformaterror', 'open', 'establish', 'create', 'associate', 'close', 'lock', 'scratch', 'space', 'new_line', 'newline', 'print', 'write_f', 'writef', 'print_f', 'printf', 'write_bin', 'writebin', 'print_bin', 'printbin', 'read_f', 'readf', 'read_bin', 'readbin', 'put_f', 'putf', 'get_f', 'getf', 'make_term', 'maketerm', 'make_device', 'makedevice', 'idf', 'term', 'read_int', 'readint', 'read_long_int', 'readlongint', 'read_long_long_int', 'readlonglongint', 'read_real', 'readreal', 'read_long_real', 'readlongreal', 'read_long_long_real', 'readlonglongreal', 'read_complex', 'readcomplex', 'read_long_complex', 'readlongcomplex', 'read_long_long_complex', 'readlonglongcomplex', 'read_bool', 'readbool', 'read_bits', 'readbits', 'read_long_bits', 'readlongbits', 'read_long_long_bits', 'readlonglongbits', 'read_char', 'readchar', 'read_string', 'readstring', 'print_int', 'printint', 'print_long_int', 'printlongint', 'print_long_long_int', 'printlonglongint', 'print_real', 'printreal', 'print_long_real', 'printlongreal', 'print_long_long_real', 'printlonglongreal', 'print_complex', 'printcomplex', 'print_long_complex', 'printlongcomplex', 'print_long_long_complex', 'printlonglongcomplex', 'print_bool', 'printbool', 'print_bits', 'printbits', 'print_long_bits', 'printlongbits', 'print_long_long_bits', 'printlonglongbits', 'print_char', 'printchar', 'print_string', 'printstring', 'whole', 'fixed', 'float'),
- 23 => array('pi', 'long_pi', 'longpi', 'long_long_pi', 'longlongpi'),
- 24 => array('sqrt', 'curt', 'cbrt', 'exp', 'ln', 'log', 'sin', 'arc_sin', 'arcsin', 'cos', 'arc_cos', 'arccos', 'tan', 'arc_tan', 'arctan', 'long_sqrt', 'longsqrt', 'long_curt', 'longcurt', 'long_cbrt', 'longcbrt', 'long_exp', 'longexp', 'long_ln', 'longln', 'long_log', 'longlog', 'long_sin', 'longsin', 'long_arc_sin', 'longarcsin', 'long_cos', 'longcos', 'long_arc_cos', 'longarccos', 'long_tan', 'longtan', 'long_arc_tan', 'longarctan', 'long_long_sqrt', 'longlongsqrt', 'long_long_curt', 'longlongcurt', 'long_long_cbrt', 'longlongcbrt', 'long_long_exp', 'longlongexp', 'long_long_ln', 'longlongln', 'long_long_log', 'longlonglog', 'long_long_sin', 'longlongsin', 'long_long_arc_sin', 'longlongarcsin', 'long_long_cos', 'longlongcos', 'long_long_arc_cos', 'longlongarccos', 'long_long_tan', 'longlongtan', 'long_long_arc_tan', 'longlongarctan'),
- 25 => array('first_random', 'firstrandom', 'next_random', 'nextrandom', 'long_next_random', 'longnextrandom', 'long_long_next_random', 'longlongnextrandom'),
- 26 => array('real', 'bits_pack', 'bitspack', 'long_bits_pack', 'longbitspack', 'long_long_bits_pack', 'longlongbitspack', 'bytes_pack', 'bytespack', 'long_bytes_pack', 'longbytespack', 'char_in_string', 'charinstring', 'last_char_in_string', 'lastcharinstring', 'string_in_string', 'stringinstring'),
- 27 => array('utc_time', 'utctime', 'local_time', 'localtime', 'argc', 'argv', 'get_env', 'getenv', 'reset_errno', 'reseterrno', 'errno', 'strerror'),
- 28 => array('sinh', 'long_sinh', 'longsinh', 'long_long_sinh', 'longlongsinh', 'arc_sinh', 'arcsinh', 'long_arc_sinh', 'longarcsinh', 'long_long_arc_sinh', 'longlongarcsinh', 'cosh', 'long_cosh', 'longcosh', 'long_long_cosh', 'longlongcosh', 'arc_cosh', 'arccosh', 'long_arc_cosh', 'longarccosh', 'long_long_arc_cosh', 'longlongarccosh', 'tanh', 'long_tanh', 'longtanh', 'long_long_tanh', 'longlongtanh', 'arc_tanh', 'arctanh', 'long_arc_tanh', 'longarctanh', 'long_long_arc_tanh', 'longlongarctanh', 'arc_tan2', 'arctan2', 'long_arc_tan2', 'longarctan2', 'long_long_arc_tan2', 'longlongarctan2'),
- 29 => array('complex_sqrt', 'complexsqrt', 'long_complex_sqrt', 'longcomplexsqrt', 'long_long_complex_sqrt', 'longlongcomplexsqrt', 'complex_exp', 'complexexp', 'long_complex_exp', 'longcomplexexp', 'long_long_complex_exp', 'longlongcomplexexp', 'complex_ln', 'complexln', 'long_complex_ln', 'longcomplexln', 'long_long_complex_ln', 'longlongcomplexln', 'complex_sin', 'complexsin', 'long_complex_sin', 'longcomplexsin', 'long_long_complex_sin', 'longlongcomplexsin', 'complex_arc_sin', 'complexarcsin', 'long_complex_arc_sin', 'longcomplexarcsin', 'long_long_complex_arc_sin', 'longlongcomplexarcsin', 'complex_cos', 'complexcos', 'long_complex_cos', 'longcomplexcos', 'long_long_complex_cos', 'longlongcomplexcos', 'complex_arc_cos', 'complexarccos', 'long_complex_arc_cos', 'longcomplexarccos', 'long_long_complex_arc_cos', 'longlongcomplexarccos', 'complex_tan', 'complextan', 'long_complex_tan', 'longcomplextan', 'long_long_complex_tan', 'longlongcomplextan', 'complex_arc_tan', 'complexarctan', 'long_complex_arc_tan', 'longcomplexarctan', 'long_long_complex_arc_tan', 'longlongcomplexarctan', 'complex_sinh', 'complexsinh', 'complex_arc_sinh', 'complexarcsinh', 'complex_cosh', 'complexcosh', 'complex_arc_cosh', 'complexarccosh', 'complex_tanh', 'complextanh', 'complex_arc_tanh', 'complexarctanh')
+# Built in procedures - from standard prelude #
+ 20 => array('int lengths', 'intlengths', 'int shorths', 'intshorths', 'max int', 'maxint', 'real lengths', 'reallengths', 'real shorths', 'realshorths', 'bits lengths', 'bitslengths', 'bits shorths', 'bitsshorths', 'bytes lengths', 'byteslengths', 'bytes shorths', 'bytesshorths', 'max abs char', 'maxabschar', 'int width', 'intwidth', 'long int width', 'longintwidth', 'long long int width', 'longlongintwidth', 'real width', 'realwidth', 'long real width', 'longrealwidth', 'long long real width', 'longlongrealwidth', 'exp width', 'expwidth', 'long exp width', 'longexpwidth', 'long long exp width', 'longlongexpwidth', 'bits width', 'bitswidth', 'long bits width', 'longbitswidth', 'long long bits width', 'longlongbitswidth', 'bytes width', 'byteswidth', 'long bytes width', 'longbyteswidth', 'max real', 'maxreal', 'small real', 'smallreal', 'long max int', 'longmaxint', 'long long max int', 'longlongmaxint', 'long max real', 'longmaxreal', 'long small real', 'longsmallreal', 'long long max real', 'longlongmaxreal', 'long long small real', 'longlongsmallreal', 'long max bits', 'longmaxbits', 'long long max bits', 'longlongmaxbits', 'null character', 'nullcharacter', 'blank', 'flip', 'flop', 'error char', 'errorchar', 'exp char', 'expchar', 'newline char', 'newlinechar', 'formfeed char', 'formfeedchar', 'tab char', 'tabchar'),
+ 21 => array('stand in channel', 'standinchannel', 'stand out channel', 'standoutchannel', 'stand back channel', 'standbackchannel', 'stand draw channel', 'standdrawchannel', 'stand error channel', 'standerrorchannel'),
+ 22 => array('put possible', 'putpossible', 'get possible', 'getpossible', 'bin possible', 'binpossible', 'set possible', 'setpossible', 'reset possible', 'resetpossible', 'reidf possible', 'reidfpossible', 'draw possible', 'drawpossible', 'compressible', 'on logical file end', 'onlogicalfileend', 'on physical file end', 'onphysicalfileend', 'on line end', 'onlineend', 'on page end', 'onpageend', 'on format end', 'onformatend', 'on value error', 'onvalueerror', 'on open error', 'onopenerror', 'on transput error', 'ontransputerror', 'on format error', 'onformaterror', 'open', 'establish', 'create', 'associate', 'close', 'lock', 'scratch', 'space', 'new line', 'newline', 'print', 'write f', 'writef', 'print f', 'printf', 'write bin', 'writebin', 'print bin', 'printbin', 'read f', 'readf', 'read bin', 'readbin', 'put f', 'putf', 'get f', 'getf', 'make term', 'maketerm', 'make device', 'makedevice', 'idf', 'term', 'read int', 'readint', 'read long int', 'readlongint', 'read long long int', 'readlonglongint', 'read real', 'readreal', 'read long real', 'readlongreal', 'read long long real', 'readlonglongreal', 'read complex', 'readcomplex', 'read long complex', 'readlongcomplex', 'read long long complex', 'readlonglongcomplex', 'read bool', 'readbool', 'read bits', 'readbits', 'read long bits', 'readlongbits', 'read long long bits', 'readlonglongbits', 'read char', 'readchar', 'read string', 'readstring', 'print int', 'printint', 'print long int', 'printlongint', 'print long long int', 'printlonglongint', 'print real', 'printreal', 'print long real', 'printlongreal', 'print long long real', 'printlonglongreal', 'print complex', 'printcomplex', 'print long complex', 'printlongcomplex', 'print long long complex', 'printlonglongcomplex', 'print bool', 'printbool', 'print bits', 'printbits', 'print long bits', 'printlongbits', 'print long long bits', 'printlonglongbits', 'print char', 'printchar', 'print string', 'printstring', 'whole', 'fixed', 'float'),
+ 23 => array('pi', 'long pi', 'longpi', 'long long pi', 'longlongpi'),
+ 24 => array('sqrt', 'curt', 'cbrt', 'exp', 'ln', 'log', 'sin', 'arc sin', 'arcsin', 'cos', 'arc cos', 'arccos', 'tan', 'arc tan', 'arctan', 'long sqrt', 'longsqrt', 'long curt', 'longcurt', 'long cbrt', 'longcbrt', 'long exp', 'longexp', 'long ln', 'longln', 'long log', 'longlog', 'long sin', 'longsin', 'long arc sin', 'longarcsin', 'long cos', 'longcos', 'long arc cos', 'longarccos', 'long tan', 'longtan', 'long arc tan', 'longarctan', 'long long sqrt', 'longlongsqrt', 'long long curt', 'longlongcurt', 'long long cbrt', 'longlongcbrt', 'long long exp', 'longlongexp', 'long long ln', 'longlongln', 'long long log', 'longlonglog', 'long long sin', 'longlongsin', 'long long arc sin', 'longlongarcsin', 'long long cos', 'longlongcos', 'long long arc cos', 'longlongarccos', 'long long tan', 'longlongtan', 'long long arc tan', 'longlongarctan'),
+ 25 => array('first random', 'firstrandom', 'next random', 'nextrandom', 'long next random', 'longnextrandom', 'long long next random', 'longlongnextrandom'),
+ 26 => array('real', 'bits pack', 'bitspack', 'long bits pack', 'longbitspack', 'long long bits pack', 'longlongbitspack', 'bytes pack', 'bytespack', 'long bytes pack', 'longbytespack', 'char in string', 'charinstring', 'last char in string', 'lastcharinstring', 'string in string', 'stringinstring'),
+ 27 => array('utc time', 'utctime', 'local time', 'localtime', 'argc', 'argv', 'get env', 'getenv', 'reset errno', 'reseterrno', 'errno', 'strerror'),
+ 28 => array('sinh', 'long sinh', 'longsinh', 'long long sinh', 'longlongsinh', 'arc sinh', 'arcsinh', 'long arc sinh', 'longarcsinh', 'long long arc sinh', 'longlongarcsinh', 'cosh', 'long cosh', 'longcosh', 'long long cosh', 'longlongcosh', 'arc cosh', 'arccosh', 'long arc cosh', 'longarccosh', 'long long arc cosh', 'longlongarccosh', 'tanh', 'long tanh', 'longtanh', 'long long tanh', 'longlongtanh', 'arc tanh', 'arctanh', 'long arc tanh', 'longarctanh', 'long long arc tanh', 'longlongarctanh', 'arc tan2', 'arctan2', 'long arc tan2', 'longarctan2', 'long long arc tan2', 'longlongarctan2'),
+ 29 => array('complex sqrt', 'complexsqrt', 'long complex sqrt', 'longcomplexsqrt', 'long long complex sqrt', 'longlongcomplexsqrt', 'complex exp', 'complexexp', 'long complex exp', 'longcomplexexp', 'long long complex exp', 'longlongcomplexexp', 'complex ln', 'complexln', 'long complex ln', 'longcomplexln', 'long long complex ln', 'longlongcomplexln', 'complex sin', 'complexsin', 'long complex sin', 'longcomplexsin', 'long long complex sin', 'longlongcomplexsin', 'complex arc sin', 'complexarcsin', 'long complex arc sin', 'longcomplexarcsin', 'long long complex arc sin', 'longlongcomplexarcsin', 'complex cos', 'complexcos', 'long complex cos', 'longcomplexcos', 'long long complex cos', 'longlongcomplexcos', 'complex arc cos', 'complexarccos', 'long complex arc cos', 'longcomplexarccos', 'long long complex arc cos', 'longlongcomplexarccos', 'complex tan', 'complextan', 'long complex tan', 'longcomplextan', 'long long complex tan', 'longlongcomplextan', 'complex arc tan', 'complexarctan', 'long complex arc tan', 'longcomplexarctan', 'long long complex arc tan', 'longlongcomplexarctan', 'complex sinh', 'complexsinh', 'complex arc sinh', 'complexarcsinh', 'complex cosh', 'complexcosh', 'complex arc cosh', 'complexarccosh', 'complex tanh', 'complextanh', 'complex arc tanh', 'complexarctanh')
),
'SYMBOLS' => array(
- 1 => array(
- '(', ')', '{', '}', '[', ']', '+', '-', '*', '/', '%', '=', '<', '>', '!', '^', '&', '|', '?', ':', ';', ','
- )
- ),
+ 1 => array( /* reverse length sorted... */ '÷×:=', '%×:=', ':≠:', '÷*:=', '÷::=', '%*:=', ':/=:', '×:=', '÷:=', '÷×', '%:=', '%×', '*:=', '+:=', '+=:', '+×', '-:=', '/:=', '::=', ':=:', '÷*', '÷:', '↑', '↓', '∧', '∨', '≠', '≤', '≥', '⊥', '⌈', '⌊', '⎧', '⎩', /* 'â¨', */ 'â–¡', 'â—‹', '%*', '**', '+*', '/=', '::', '/\\', '\\/', '<=', '>=', '|:', '~=', '¬', '×', '÷', '!', '%', '&', '(', ')', '*', '+', ',', '-', '/', ':', ';', '<', '=', '>', '?', '@', '[', ']', '^', '{', '|', '}', '~')
+ ),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => true,
@@ -99,11 +214,11 @@ $language_data = array(
6 => true,
7 => true,
8 => true,
- 9 => true,
+# 9 => true,
10 => true,
11 => true,
12 => true,
- 13 => true,
+# 13 => true,
14 => true,
15 => true,
16 => true,
@@ -123,43 +238,18 @@ $language_data = array(
),
'STYLES' => array(
'KEYWORDS' => array(
- 1 => 'color: #b1b100; font-weight: bold;',
- 2 => 'color: #b1b100; font-weight: bold;',
- 3 => 'color: #b1b100; font-weight: bold;',
- 4 => 'color: #b1b100; font-weight: bold;',
- 5 => 'color: #b1b100; font-weight: bold;',
- 6 => 'color: #b1b100; font-weight: bold;',
- 7 => 'color: #b1b100; font-weight: bold;',
- 8 => 'color: #b1b100; font-weight: bold;',
- 9 => 'color: #b1b100; font-weight: bold;',
- 10 => 'color: #b1b100; font-weight: bold;',
- 11 => 'color: #b1b100; font-weight: bold;',
- 12 => 'color: #b1b100; font-weight: bold;',
- 13 => 'color: #b1b100; font-weight: bold;',
- 14 => 'color: #b1b100; font-weight: bold;',
- 15 => 'color: #b1b100; font-weight: bold;',
- 16 => 'color: #b1b100; font-weight: bold;',
- 17 => 'color: #b1b100; font-weight: bold;',
- 18 => 'color: #b1b100; font-weight: bold;',
- 19 => 'color: #b1b100; font-weight: bold;',
- 20 => 'color: #b1b100;',
- 21 => 'color: #b1b100;',
- 22 => 'color: #b1b100;',
- 23 => 'color: #b1b100;',
- 24 => 'color: #b1b100;',
- 25 => 'color: #b1b100;',
- 26 => 'color: #b1b100;',
- 27 => 'color: #b1b100;',
- 28 => 'color: #b1b100;',
- 29 => 'color: #b1b100;'
+ 1 => $a68['NONSTD'], 2 => $a68['BOLD'], 3 => $a68['BOLD'], 4 => $a68['BOLD'],
+ 5 => $a68['NONSTD'], 6 => $a68['BOLD'], 7 => $a68['BOLD'], 8 => $a68['BOLD'],
+ /* 9 => $a68['BOLD'],*/ 10 => $a68['BOLD'], 11 => $a68['BOLD'], 12 => $a68['BOLD'],
+ /* 13 => $a68['BOLD'],*/ 14 => $a68['BOLD'], 15 => $a68['BOLD'], 16 => $a68['BOLD'], 17 => $a68['BOLD'],
+ 18 => $a68['NONSTD'], 19 => $a68['NONSTD'],
+ 20 => $a68['ITALIC'], 21 => $a68['ITALIC'], 22 => $a68['ITALIC'], 23 => $a68['ITALIC'],
+ 24 => $a68['ITALIC'], 25 => $a68['ITALIC'], 26 => $a68['ITALIC'], 27 => $a68['ITALIC'],
+ 28 => $a68['ITALIC'], 29 => $a68['ITALIC']
),
'COMMENTS' => array(
- 1 => 'color: #666666; font-style: italic;',
- 2 => 'color: #666666; font-style: italic;',
- 3 => 'color: #666666; font-style: italic;',
- 4 => 'color: #666666; font-style: italic;',
- 5 => 'color: #666666; font-style: italic;',
- 'MULTI' => 'color: #666666; font-style: italic;'
+ 1 => $a68['COMMENT'], 2 => $a68['COMMENT'], 3 => $a68['COMMENT'], /* 4 => $a68['COMMENT'],
+ 5 => $a68['COMMENT'],*/ 'MULTI' => $a68['COMMENT']
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
@@ -174,12 +264,18 @@ $language_data = array(
0 => 'color: #cc66cc;',
),
'METHODS' => array(
- 0 => 'color: #004000;'
+ 0 => 'color: #004000;',
+ 1 => 'color: #004000;'
),
'SYMBOLS' => array(
+ 0 => 'color: #339933;',
1 => 'color: #339933;'
),
- 'REGEXPS' => array(),
+ 'REGEXPS' => array(
+ 0 => 'color: #cc66cc;', # BITS #
+ 1 => 'color: #cc66cc;', # REAL #
+ /* 2 => 'color: #cc66cc;', # INT # */
+ ),
'SCRIPT' => array()
),
'URLS' => array(
@@ -191,11 +287,11 @@ $language_data = array(
6 => '',
7 => '',
8 => '',
- 9 => '',
+# 9 => '',
10 => '',
11 => '',
12 => '',
- 13 => '',
+# 13 => '',
14 => '',
15 => '',
16 => '',
@@ -215,12 +311,19 @@ $language_data = array(
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
+ 0 => '→',
1 => 'OF'
),
- 'REGEXPS' => array(),
+ 'REGEXPS' => array(
+ 0 => $a68['BITS'],
+ 1 => $a68['REAL']
+ # 2 => $a68['INT'], # Breaks formatting for some reason #
+ # 2 => $GESHI_NUMBER_INT_BASIC # Also breaks formatting #
+ ),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(),
'HIGHLIGHT_STRICT_BLOCK' => array()
);
+unset($a68);
?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/apache.php b/plugins/wp-syntax/geshi/geshi/apache.php
index ddd4d6a0..c944443c 100644
--- a/plugins/wp-syntax/geshi/geshi/apache.php
+++ b/plugins/wp-syntax/geshi/geshi/apache.php
@@ -4,7 +4,7 @@
* ----------
* Author: Tux (tux@inmail.cz)
* Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/29/07
*
* Apache language file for GeSHi.
@@ -344,6 +344,9 @@ $language_data = array (
//mod_unique_id.c
+ //mod_upload_progress
+ 'ReportUploads', 'TrackUploads', 'UploadProgressSharedMemorySize',
+
//mod_userdir.c
'UserDir',
diff --git a/plugins/wp-syntax/geshi/geshi/applescript.php b/plugins/wp-syntax/geshi/geshi/applescript.php
index 870ac0fd..603fa4a3 100644
--- a/plugins/wp-syntax/geshi/geshi/applescript.php
+++ b/plugins/wp-syntax/geshi/geshi/applescript.php
@@ -4,7 +4,7 @@
* --------
* Author: Stephan Klimek (http://www.initware.org)
* Copyright: Stephan Klimek (http://www.initware.org)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/07/20
*
* AppleScript language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/apt_sources.php b/plugins/wp-syntax/geshi/geshi/apt_sources.php
index 0512380b..9f1ed045 100644
--- a/plugins/wp-syntax/geshi/geshi/apt_sources.php
+++ b/plugins/wp-syntax/geshi/geshi/apt_sources.php
@@ -4,7 +4,7 @@
* ----------
* Author: Milian Wolff (mail@milianw.de)
* Copyright: (c) 2008 Milian Wolff (http://milianw.de)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/06/17
*
* Apt sources.list language file for GeSHi.
@@ -55,7 +55,7 @@ $language_data = array (
'stable/updates',
//Debian
'buzz', 'rex', 'bo', 'hamm', 'slink', 'potato', 'woody', 'sarge',
- 'etch', 'lenny', 'sid',
+ 'etch', 'lenny', 'wheezy', 'sid',
//Ubuntu
'warty', 'warty-updates', 'warty-security', 'warty-proposed', 'warty-backports',
'hoary', 'hoary-updates', 'hoary-security', 'hoary-proposed', 'hoary-backports',
@@ -65,7 +65,11 @@ $language_data = array (
'feisty', 'feisty-updates', 'feisty-security', 'feisty-proposed', 'feisty-backports',
'gutsy', 'gutsy-updates', 'gutsy-security', 'gutsy-proposed', 'gutsy-backports',
'hardy', 'hardy-updates', 'hardy-security', 'hardy-proposed', 'hardy-backports',
- 'intrepid', 'intrepid-updates', 'intrepid-security', 'intrepid-proposed', 'intrepid-backports'
+ 'intrepid', 'intrepid-updates', 'intrepid-security', 'intrepid-proposed', 'intrepid-backports',
+ 'jaunty', 'jaunty-updates', 'jaunty-security', 'jaunty-proposed', 'jaunty-backports',
+ 'karmic', 'karmic-updates', 'karmic-security', 'karmic-proposed', 'karmic-backports',
+ 'lucid', 'lucid-updates', 'lucid-security', 'lucid-proposed', 'lucid-backports',
+ 'maverick', 'maverick-updates', 'maverick-security', 'maverick-proposed', 'maverick-backports'
),
3 => array(
'main', 'restricted', 'preview', 'contrib', 'non-free',
@@ -141,4 +145,4 @@ $language_data = array (
'TAB_WIDTH' => 4
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/arm.php b/plugins/wp-syntax/geshi/geshi/arm.php
new file mode 100644
index 00000000..8e3c0a37
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/arm.php
@@ -0,0 +1,3318 @@
+<?php
+/*************************************************************************************
+ * arm.php
+ * -------
+ * Author: Marat Dukhan (mdukhan3.at.gatech.dot.edu)
+ * Copyright: (c) Marat Dukhan (mdukhan3.at.gatech.dot.edu)
+ * Release Version: 1.0.8.11
+ * Date Started: 2011/10/06
+ *
+ * ARM Assembler language file for GeSHi.
+ * Based on the following documents:
+ * - "ARM Architecture Reference Manual: ARMv7-A and ARMv7-R edition"
+ * - "Intel XScale Technology: Intel Wireless MMX2 Coprocessor",
+ * Revision 1.5, July 2006
+ *
+ * CHANGES
+ * -------
+ * 2011/10/06
+ * - First Release (supported UAL syntax for up to ARMv7 A/R, VFPv3, NEON, WMMX/WMMX2)
+ *
+ * TODO (updated 2011/10/06)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'ARM ASSEMBLER',
+ 'COMMENT_SINGLE' => array(
+ 1 => ';'
+ ),
+ 'COMMENT_MULTI' => array(),
+ //Line address prefix suppression
+ 'COMMENT_REGEXP' => array(
+ 2 => "/^(?:[0-9a-f]{0,4}:)?[0-9a-f]{4}(?:[0-9a-f]{4})?/mi"
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ /* Unconditional Data Processing Instructions */
+ 1 => array(
+ /* Data Processing: Unconditional Addition & Subtraction */
+ 'adc.w','adcal.w',
+ 'adc','adcal',
+ 'add.w','addal.w',
+ 'add','addal',
+ 'addw','addwal',
+ 'rsb.w','rsbal.w',
+ 'rsb','rsbal',
+ 'rsc','rscal',
+ 'sbc.w','sbcal.w',
+ 'sbc','sbcal',
+ 'sub.w','subal.w',
+ 'sub','subal',
+ 'neg.w','negal.w',
+ 'neg','negal',
+ 'adr.w','adral.w',
+ 'adr','adral',
+ /* Data Processing: Unconditional Logical */
+ 'and.w','andal.w',
+ 'and','andal',
+ 'bic.w','bical.w',
+ 'bic','bical',
+ 'orr.w','orral.w',
+ 'orr','orral',
+ 'orn.w','ornal.w',
+ 'orn','ornal',
+ 'eor.w','eoral.w',
+ 'eor','eoral',
+ 'mov.w','moval.w',
+ 'mov','moval',
+ 'movw','movwal',
+ 'movt','movtal',
+ 'cpy','cpyal',
+ 'mvn.w','mvnal.w',
+ 'mvn','mvnal',
+ /* Data Processing: Unconditional Shifts and Rotates */
+ 'asr.w','asral.w',
+ 'asr','asral',
+ 'lsl.w','lslal.w',
+ 'lsl','lslal',
+ 'lsr.w','lsral.w',
+ 'lsr','lsral',
+ 'ror.w','roral.w',
+ 'ror','roral',
+ 'rrx','rrxal',
+ /* Data Processing: Unconditional Word Multiply and Multiply-Add */
+ 'mul','mulal',
+ 'mla','mlaal',
+ 'mls','mlsal',
+ 'smull','smullal',
+ 'muls','mulsal',
+ 'umull','umullal',
+ 'smlal','smlalal',
+ 'umlal','umlalal',
+ /* Data Processing: Unconditional Halfword Multiply and Multiply-Add (ARMv5TE) */
+ 'smulbb','smulbbal',
+ 'smulbt','smulbtal',
+ 'smultb','smultbal',
+ 'smultt','smulttal',
+ 'smulwb','smulwbal',
+ 'smulwt','smulwtal',
+ 'smlalbb','smlalbbal',
+ 'smlalbt','smlalbtal',
+ 'smlaltb','smlaltbal',
+ 'smlaltt','smlalttal',
+ 'smlabb','smlabbal',
+ 'smlabt','smlabtal',
+ 'smlatb','smlatbal',
+ 'smlatt','smlattal',
+ 'smlawb','smlawbal',
+ 'smlawt','smlawtal',
+ /* Data Processing: Unconditional Bit Operations */
+ 'ubfx','ubfxal',
+ 'sbfx','sbfxal',
+ 'bfc','bfcal',
+ 'bfi','bfial',
+ 'clz','clzal',
+ /* Data Processing: Unconditional Divide (ARMv7-R) */
+ 'sdiv','sdival',
+ 'udiv','udival'
+ ),
+ /* Conditional Data Processing Instructions */
+ 2 => array(
+ /* Data Processing: Conditional Addition & Subtraction */
+ 'adceq.w','adcne.w','adccs.w','adchs.w','adccc.w','adclo.w','adcmi.w','adcpl.w','adcvs.w','adcvc.w','adchi.w','adcls.w','adcge.w','adclt.w','adcgt.w','adcle.w',
+ 'adceq','adcne','adccs','adchs','adccc','adclo','adcmi','adcpl','adcvs','adcvc','adchi','adcls','adcge','adclt','adcgt','adcle',
+ 'addeq.w','addne.w','addcs.w','addhs.w','addcc.w','addlo.w','addmi.w','addpl.w','addvs.w','addvc.w','addhi.w','addls.w','addge.w','addlt.w','addgt.w','addle.w',
+ 'addeq','addne','addcs','addhs','addcc','addlo','addmi','addpl','addvs','addvc','addhi','addls','addge','addlt','addgt','addle',
+ 'addweq','addwne','addwcs','addwhs','addwcc','addwlo','addwmi','addwpl','addwvs','addwvc','addwhi','addwls','addwge','addwlt','addwgt','addwle',
+ 'rsbeq.w','rsbne.w','rsbcs.w','rsbhs.w','rsbcc.w','rsblo.w','rsbmi.w','rsbpl.w','rsbvs.w','rsbvc.w','rsbhi.w','rsbls.w','rsbge.w','rsblt.w','rsbgt.w','rsble.w',
+ 'rsbeq','rsbne','rsbcs','rsbhs','rsbcc','rsblo','rsbmi','rsbpl','rsbvs','rsbvc','rsbhi','rsbls','rsbge','rsblt','rsbgt','rsble',
+ 'rsceq','rscne','rsccs','rschs','rsccc','rsclo','rscmi','rscpl','rscvs','rscvc','rschi','rscls','rscge','rsclt','rscgt','rscle',
+ 'sbceq.w','sbcne.w','sbccs.w','sbchs.w','sbccc.w','sbclo.w','sbcmi.w','sbcpl.w','sbcvs.w','sbcvc.w','sbchi.w','sbcls.w','sbcge.w','sbclt.w','sbcgt.w','sbcle.w',
+ 'sbceq','sbcne','sbccs','sbchs','sbccc','sbclo','sbcmi','sbcpl','sbcvs','sbcvc','sbchi','sbcls','sbcge','sbclt','sbcgt','sbcle',
+ 'subeq.w','subne.w','subcs.w','subhs.w','subcc.w','sublo.w','submi.w','subpl.w','subvs.w','subvc.w','subhi.w','subls.w','subge.w','sublt.w','subgt.w','suble.w',
+ 'subeq','subne','subcs','subhs','subcc','sublo','submi','subpl','subvs','subvc','subhi','subls','subge','sublt','subgt','suble',
+ 'negeq.w','negne.w','negcs.w','neghs.w','negcc.w','neglo.w','negmi.w','negpl.w','negvs.w','negvc.w','neghi.w','negls.w','negge.w','neglt.w','neggt.w','negle.w',
+ 'negeq','negne','negcs','neghs','negcc','neglo','negmi','negpl','negvs','negvc','neghi','negls','negge','neglt','neggt','negle',
+ 'adreq.w','adrne.w','adrcs.w','adrhs.w','adrcc.w','adrlo.w','adrmi.w','adrpl.w','adrvs.w','adrvc.w','adrhi.w','adrls.w','adrge.w','adrlt.w','adrgt.w','adrle.w',
+ 'adreq','adrne','adrcs','adrhs','adrcc','adrlo','adrmi','adrpl','adrvs','adrvc','adrhi','adrls','adrge','adrlt','adrgt','adrle',
+ /* Data Processing: Conditional Logical */
+ 'andeq.w','andne.w','andcs.w','andhs.w','andcc.w','andlo.w','andmi.w','andpl.w','andvs.w','andvc.w','andhi.w','andls.w','andge.w','andlt.w','andgt.w','andle.w',
+ 'andeq','andne','andcs','andhs','andcc','andlo','andmi','andpl','andvs','andvc','andhi','andls','andge','andlt','andgt','andle',
+ 'biceq.w','bicne.w','biccs.w','bichs.w','biccc.w','biclo.w','bicmi.w','bicpl.w','bicvs.w','bicvc.w','bichi.w','bicls.w','bicge.w','biclt.w','bicgt.w','bicle.w',
+ 'biceq','bicne','biccs','bichs','biccc','biclo','bicmi','bicpl','bicvs','bicvc','bichi','bicls','bicge','biclt','bicgt','bicle',
+ 'orreq.w','orrne.w','orrcs.w','orrhs.w','orrcc.w','orrlo.w','orrmi.w','orrpl.w','orrvs.w','orrvc.w','orrhi.w','orrls.w','orrge.w','orrlt.w','orrgt.w','orrle.w',
+ 'orreq','orrne','orrcs','orrhs','orrcc','orrlo','orrmi','orrpl','orrvs','orrvc','orrhi','orrls','orrge','orrlt','orrgt','orrle',
+ 'orneq.w','ornne.w','orncs.w','ornhs.w','orncc.w','ornlo.w','ornmi.w','ornpl.w','ornvs.w','ornvc.w','ornhi.w','ornls.w','ornge.w','ornlt.w','orngt.w','ornle.w',
+ 'orneq','ornne','orncs','ornhs','orncc','ornlo','ornmi','ornpl','ornvs','ornvc','ornhi','ornls','ornge','ornlt','orngt','ornle',
+ 'eoreq.w','eorne.w','eorcs.w','eorhs.w','eorcc.w','eorlo.w','eormi.w','eorpl.w','eorvs.w','eorvc.w','eorhi.w','eorls.w','eorge.w','eorlt.w','eorgt.w','eorle.w',
+ 'eoreq','eorne','eorcs','eorhs','eorcc','eorlo','eormi','eorpl','eorvs','eorvc','eorhi','eorls','eorge','eorlt','eorgt','eorle',
+ 'moveq.w','movne.w','movcs.w','movhs.w','movcc.w','movlo.w','movmi.w','movpl.w','movvs.w','movvc.w','movhi.w','movls.w','movge.w','movlt.w','movgt.w','movle.w',
+ 'moveq','movne','movcs','movhs','movcc','movlo','movmi','movpl','movvs','movvc','movhi','movls','movge','movlt','movgt','movle',
+ 'movweq','movwne','movwcs','movwhs','movwcc','movwlo','movwmi','movwpl','movwvs','movwvc','movwhi','movwls','movwge','movwlt','movwgt','movwle',
+ 'movteq','movtne','movtcs','movths','movtcc','movtlo','movtmi','movtpl','movtvs','movtvc','movthi','movtls','movtge','movtlt','movtgt','movtle',
+ 'cpyeq','cpyne','cpycs','cpyhs','cpycc','cpylo','cpymi','cpypl','cpyvs','cpyvc','cpyhi','cpyls','cpyge','cpylt','cpygt','cpyle',
+ 'mvneq.w','mvnne.w','mvncs.w','mvnhs.w','mvncc.w','mvnlo.w','mvnmi.w','mvnpl.w','mvnvs.w','mvnvc.w','mvnhi.w','mvnls.w','mvnge.w','mvnlt.w','mvngt.w','mvnle.w',
+ 'mvneq','mvnne','mvncs','mvnhs','mvncc','mvnlo','mvnmi','mvnpl','mvnvs','mvnvc','mvnhi','mvnls','mvnge','mvnlt','mvngt','mvnle',
+ /* Data Processing: Conditional Shifts and Rotates */
+ 'asreq.w','asrne.w','asrcs.w','asrhs.w','asrcc.w','asrlo.w','asrmi.w','asrpl.w','asrvs.w','asrvc.w','asrhi.w','asrls.w','asrge.w','asrlt.w','asrgt.w','asrle.w',
+ 'asreq','asrne','asrcs','asrhs','asrcc','asrlo','asrmi','asrpl','asrvs','asrvc','asrhi','asrls','asrge','asrlt','asrgt','asrle',
+ 'lsleq.w','lslne.w','lslcs.w','lslhs.w','lslcc.w','lsllo.w','lslmi.w','lslpl.w','lslvs.w','lslvc.w','lslhi.w','lslls.w','lslge.w','lsllt.w','lslgt.w','lslle.w',
+ 'lsleq','lslne','lslcs','lslhs','lslcc','lsllo','lslmi','lslpl','lslvs','lslvc','lslhi','lslls','lslge','lsllt','lslgt','lslle',
+ 'lsreq.w','lsrne.w','lsrcs.w','lsrhs.w','lsrcc.w','lsrlo.w','lsrmi.w','lsrpl.w','lsrvs.w','lsrvc.w','lsrhi.w','lsrls.w','lsrge.w','lsrlt.w','lsrgt.w','lsrle.w',
+ 'lsreq','lsrne','lsrcs','lsrhs','lsrcc','lsrlo','lsrmi','lsrpl','lsrvs','lsrvc','lsrhi','lsrls','lsrge','lsrlt','lsrgt','lsrle',
+ 'roreq.w','rorne.w','rorcs.w','rorhs.w','rorcc.w','rorlo.w','rormi.w','rorpl.w','rorvs.w','rorvc.w','rorhi.w','rorls.w','rorge.w','rorlt.w','rorgt.w','rorle.w',
+ 'roreq','rorne','rorcs','rorhs','rorcc','rorlo','rormi','rorpl','rorvs','rorvc','rorhi','rorls','rorge','rorlt','rorgt','rorle',
+ 'rrxeq','rrxne','rrxcs','rrxhs','rrxcc','rrxlo','rrxmi','rrxpl','rrxvs','rrxvc','rrxhi','rrxls','rrxge','rrxlt','rrxgt','rrxle',
+ /* Data Processing: Conditional Word Multiply and Multiply-Add */
+ 'muleq','mulne','mulcs','mulhs','mulcc','mullo','mulmi','mulpl','mulvs','mulvc','mulhi','mulls','mulge','mullt','mulgt','mulle',
+ 'mlaeq','mlane','mlacs','mlahs','mlacc','mlalo','mlami','mlapl','mlavs','mlavc','mlahi','mlals','mlage','mlalt','mlagt','mlale',
+ 'mlseq','mlsne','mlscs','mlshs','mlscc','mlslo','mlsmi','mlspl','mlsvs','mlsvc','mlshi','mlsls','mlsge','mlslt','mlsgt','mlsle',
+ 'smulleq','smullne','smullcs','smullhs','smullcc','smulllo','smullmi','smullpl','smullvs','smullvc','smullhi','smullls','smullge','smulllt','smullgt','smullle',
+ 'mulseq','mulsne','mulscs','mulshs','mulscc','mulslo','mulsmi','mulspl','mulsvs','mulsvc','mulshi','mulsls','mulsge','mulslt','mulsgt','mulsle',
+ 'umulleq','umullne','umullcs','umullhs','umullcc','umulllo','umullmi','umullpl','umullvs','umullvc','umullhi','umullls','umullge','umulllt','umullgt','umullle',
+ 'smlaleq','smlalne','smlalcs','smlalhs','smlalcc','smlallo','smlalmi','smlalpl','smlalvs','smlalvc','smlalhi','smlalls','smlalge','smlallt','smlalgt','smlalle',
+ 'umlaleq','umlalne','umlalcs','umlalhs','umlalcc','umlallo','umlalmi','umlalpl','umlalvs','umlalvc','umlalhi','umlalls','umlalge','umlallt','umlalgt','umlalle',
+ /* Data Processing: Conditional Halfword Multiply and Multiply-Add (ARMv5TE) */
+ 'smulbbeq','smulbbne','smulbbcs','smulbbhs','smulbbcc','smulbblo','smulbbmi','smulbbpl','smulbbvs','smulbbvc','smulbbhi','smulbbls','smulbbge','smulbblt','smulbbgt','smulbble',
+ 'smulbteq','smulbtne','smulbtcs','smulbths','smulbtcc','smulbtlo','smulbtmi','smulbtpl','smulbtvs','smulbtvc','smulbthi','smulbtls','smulbtge','smulbtlt','smulbtgt','smulbtle',
+ 'smultbeq','smultbne','smultbcs','smultbhs','smultbcc','smultblo','smultbmi','smultbpl','smultbvs','smultbvc','smultbhi','smultbls','smultbge','smultblt','smultbgt','smultble',
+ 'smultteq','smulttne','smulttcs','smultths','smulttcc','smulttlo','smulttmi','smulttpl','smulttvs','smulttvc','smultthi','smulttls','smulttge','smulttlt','smulttgt','smulttle',
+ 'smulwbeq','smulwbne','smulwbcs','smulwbhs','smulwbcc','smulwblo','smulwbmi','smulwbpl','smulwbvs','smulwbvc','smulwbhi','smulwbls','smulwbge','smulwblt','smulwbgt','smulwble',
+ 'smulwteq','smulwtne','smulwtcs','smulwths','smulwtcc','smulwtlo','smulwtmi','smulwtpl','smulwtvs','smulwtvc','smulwthi','smulwtls','smulwtge','smulwtlt','smulwtgt','smulwtle',
+ 'smlalbbeq','smlalbbne','smlalbbcs','smlalbbhs','smlalbbcc','smlalbblo','smlalbbmi','smlalbbpl','smlalbbvs','smlalbbvc','smlalbbhi','smlalbbls','smlalbbge','smlalbblt','smlalbbgt','smlalbble',
+ 'smlalbteq','smlalbtne','smlalbtcs','smlalbths','smlalbtcc','smlalbtlo','smlalbtmi','smlalbtpl','smlalbtvs','smlalbtvc','smlalbthi','smlalbtls','smlalbtge','smlalbtlt','smlalbtgt','smlalbtle',
+ 'smlaltbeq','smlaltbne','smlaltbcs','smlaltbhs','smlaltbcc','smlaltblo','smlaltbmi','smlaltbpl','smlaltbvs','smlaltbvc','smlaltbhi','smlaltbls','smlaltbge','smlaltblt','smlaltbgt','smlaltble',
+ 'smlaltteq','smlalttne','smlalttcs','smlaltths','smlalttcc','smlalttlo','smlalttmi','smlalttpl','smlalttvs','smlalttvc','smlaltthi','smlalttls','smlalttge','smlalttlt','smlalttgt','smlalttle',
+ 'smlabbeq','smlabbne','smlabbcs','smlabbhs','smlabbcc','smlabblo','smlabbmi','smlabbpl','smlabbvs','smlabbvc','smlabbhi','smlabbls','smlabbge','smlabblt','smlabbgt','smlabble',
+ 'smlabteq','smlabtne','smlabtcs','smlabths','smlabtcc','smlabtlo','smlabtmi','smlabtpl','smlabtvs','smlabtvc','smlabthi','smlabtls','smlabtge','smlabtlt','smlabtgt','smlabtle',
+ 'smlatbeq','smlatbne','smlatbcs','smlatbhs','smlatbcc','smlatblo','smlatbmi','smlatbpl','smlatbvs','smlatbvc','smlatbhi','smlatbls','smlatbge','smlatblt','smlatbgt','smlatble',
+ 'smlatteq','smlattne','smlattcs','smlatths','smlattcc','smlattlo','smlattmi','smlattpl','smlattvs','smlattvc','smlatthi','smlattls','smlattge','smlattlt','smlattgt','smlattle',
+ 'smlawbeq','smlawbne','smlawbcs','smlawbhs','smlawbcc','smlawblo','smlawbmi','smlawbpl','smlawbvs','smlawbvc','smlawbhi','smlawbls','smlawbge','smlawblt','smlawbgt','smlawble',
+ 'smlawteq','smlawtne','smlawtcs','smlawths','smlawtcc','smlawtlo','smlawtmi','smlawtpl','smlawtvs','smlawtvc','smlawthi','smlawtls','smlawtge','smlawtlt','smlawtgt','smlawtle',
+ /* Data Processing: Conditional Bit Operations */
+ 'ubfxeq','ubfxne','ubfxcs','ubfxhs','ubfxcc','ubfxlo','ubfxmi','ubfxpl','ubfxvs','ubfxvc','ubfxhi','ubfxls','ubfxge','ubfxlt','ubfxgt','ubfxle',
+ 'sbfxeq','sbfxne','sbfxcs','sbfxhs','sbfxcc','sbfxlo','sbfxmi','sbfxpl','sbfxvs','sbfxvc','sbfxhi','sbfxls','sbfxge','sbfxlt','sbfxgt','sbfxle',
+ 'bfceq','bfcne','bfccs','bfchs','bfccc','bfclo','bfcmi','bfcpl','bfcvs','bfcvc','bfchi','bfcls','bfcge','bfclt','bfcgt','bfcle',
+ 'bfieq','bfine','bfics','bfihs','bficc','bfilo','bfimi','bfipl','bfivs','bfivc','bfihi','bfils','bfige','bfilt','bfigt','bfile',
+ 'clzeq','clzne','clzcs','clzhs','clzcc','clzlo','clzmi','clzpl','clzvs','clzvc','clzhi','clzls','clzge','clzlt','clzgt','clzle',
+ /* ARMv7-R: Conditional Divide */
+ 'sdiveq','sdivne','sdivcs','sdivhs','sdivcc','sdivlo','sdivmi','sdivpl','sdivvs','sdivvc','sdivhi','sdivls','sdivge','sdivlt','sdivgt','sdivle',
+ 'udiveq','udivne','udivcs','udivhs','udivcc','udivlo','udivmi','udivpl','udivvs','udivvc','udivhi','udivls','udivge','udivlt','udivgt','udivle'
+ ),
+ /* Unconditional Memory Access */
+ 3 => array(
+ /* Memory Access: Unconditional Memory Loads and Prefetches */
+ 'ldm.w','ldmal.w',
+ 'ldm','ldmal',
+ 'ldmda','ldmdaal',
+ 'ldmdb','ldmdbal',
+ 'ldmib','ldmibal',
+ 'ldmia','ldmiaal',
+ 'ldmea','ldmeaal',
+ 'ldmed','ldmedal',
+ 'ldmfa','ldmfaal',
+ 'ldmfd','ldmfdal',
+ 'ldrd','ldrdal',
+ 'ldr.w','ldral.w',
+ 'ldr','ldral',
+ 'ldrh.w','ldrhal.w',
+ 'ldrh','ldrhal',
+ 'ldrb.w','ldrbal.w',
+ 'ldrb','ldrbal',
+ 'ldrsh.w','ldrshal.w',
+ 'ldrsh','ldrshal',
+ 'ldrsb.w','ldrsbal.w',
+ 'ldrsb','ldrsbal',
+ 'ldrt','ldrtal',
+ 'ldrht','ldrhtal',
+ 'ldrbt','ldrbtal',
+ 'ldrsht','ldrshtal',
+ 'ldrsbt','ldrsbtal',
+ 'pop.w','popal.w',
+ 'pop','popal',
+ 'pld','pldal',
+ 'pldw','pldwal',
+ 'pli','plial',
+ /* Memory Access: Unconditional Memory Stores */
+ 'stm.w','stmal.w',
+ 'stm','stmal',
+ 'stmda','stmdaal',
+ 'stmdb','stmdbal',
+ 'stmib','stmibal',
+ 'stmia','stmiaal',
+ 'stmea','stmeaal',
+ 'stmed','stmedal',
+ 'stdfa','stdfaal',
+ 'stdfd','stdfdal',
+ 'strd','strdal',
+ 'str.w','stral.w',
+ 'str','stral',
+ 'strh.w','strhal.w',
+ 'strh','strhal',
+ 'strb.w','strbal.w',
+ 'strb','strbal',
+ 'strt','strtal',
+ 'strht','strhtal',
+ 'strbt','strbtal',
+ 'push.w','pushal.w',
+ 'push','pushal'
+ ),
+ /* Conditional Memory Access */
+ 4 => array(
+ /* Memory Access: Conditional Memory Loads and Prefetches */
+ 'ldmeq.w','ldmne.w','ldmcs.w','ldmhs.w','ldmcc.w','ldmlo.w','ldmmi.w','ldmpl.w','ldmvs.w','ldmvc.w','ldmhi.w','ldmls.w','ldmge.w','ldmlt.w','ldmgt.w','ldmle.w',
+ 'ldmeq','ldmne','ldmcs','ldmhs','ldmcc','ldmlo','ldmmi','ldmpl','ldmvs','ldmvc','ldmhi','ldmls','ldmge','ldmlt','ldmgt','ldmle',
+ 'ldmdaeq','ldmdane','ldmdacs','ldmdahs','ldmdacc','ldmdalo','ldmdami','ldmdapl','ldmdavs','ldmdavc','ldmdahi','ldmdals','ldmdage','ldmdalt','ldmdagt','ldmdale',
+ 'ldmdbeq','ldmdbne','ldmdbcs','ldmdbhs','ldmdbcc','ldmdblo','ldmdbmi','ldmdbpl','ldmdbvs','ldmdbvc','ldmdbhi','ldmdbls','ldmdbge','ldmdblt','ldmdbgt','ldmdble',
+ 'ldmibeq','ldmibne','ldmibcs','ldmibhs','ldmibcc','ldmiblo','ldmibmi','ldmibpl','ldmibvs','ldmibvc','ldmibhi','ldmibls','ldmibge','ldmiblt','ldmibgt','ldmible',
+ 'ldmiaeq','ldmiane','ldmiacs','ldmiahs','ldmiacc','ldmialo','ldmiami','ldmiapl','ldmiavs','ldmiavc','ldmiahi','ldmials','ldmiage','ldmialt','ldmiagt','ldmiale',
+ 'ldmeaeq','ldmeane','ldmeacs','ldmeahs','ldmeacc','ldmealo','ldmeami','ldmeapl','ldmeavs','ldmeavc','ldmeahi','ldmeals','ldmeage','ldmealt','ldmeagt','ldmeale',
+ 'ldmedeq','ldmedne','ldmedcs','ldmedhs','ldmedcc','ldmedlo','ldmedmi','ldmedpl','ldmedvs','ldmedvc','ldmedhi','ldmedls','ldmedge','ldmedlt','ldmedgt','ldmedle',
+ 'ldmfaeq','ldmfane','ldmfacs','ldmfahs','ldmfacc','ldmfalo','ldmfami','ldmfapl','ldmfavs','ldmfavc','ldmfahi','ldmfals','ldmfage','ldmfalt','ldmfagt','ldmfale',
+ 'ldmfdeq','ldmfdne','ldmfdcs','ldmfdhs','ldmfdcc','ldmfdlo','ldmfdmi','ldmfdpl','ldmfdvs','ldmfdvc','ldmfdhi','ldmfdls','ldmfdge','ldmfdlt','ldmfdgt','ldmfdle',
+ 'ldrdeq','ldrdne','ldrdcs','ldrdhs','ldrdcc','ldrdlo','ldrdmi','ldrdpl','ldrdvs','ldrdvc','ldrdhi','ldrdls','ldrdge','ldrdlt','ldrdgt','ldrdle',
+ 'ldreq.w','ldrne.w','ldrcs.w','ldrhs.w','ldrcc.w','ldrlo.w','ldrmi.w','ldrpl.w','ldrvs.w','ldrvc.w','ldrhi.w','ldrls.w','ldrge.w','ldrlt.w','ldrgt.w','ldrle.w',
+ 'ldreq','ldrne','ldrcs','ldrhs','ldrcc','ldrlo','ldrmi','ldrpl','ldrvs','ldrvc','ldrhi','ldrls','ldrge','ldrlt','ldrgt','ldrle',
+ 'ldrheq.w','ldrhne.w','ldrhcs.w','ldrhhs.w','ldrhcc.w','ldrhlo.w','ldrhmi.w','ldrhpl.w','ldrhvs.w','ldrhvc.w','ldrhhi.w','ldrhls.w','ldrhge.w','ldrhlt.w','ldrhgt.w','ldrhle.w',
+ 'ldrheq','ldrhne','ldrhcs','ldrhhs','ldrhcc','ldrhlo','ldrhmi','ldrhpl','ldrhvs','ldrhvc','ldrhhi','ldrhls','ldrhge','ldrhlt','ldrhgt','ldrhle',
+ 'ldrbeq.w','ldrbne.w','ldrbcs.w','ldrbhs.w','ldrbcc.w','ldrblo.w','ldrbmi.w','ldrbpl.w','ldrbvs.w','ldrbvc.w','ldrbhi.w','ldrbls.w','ldrbge.w','ldrblt.w','ldrbgt.w','ldrble.w',
+ 'ldrbeq','ldrbne','ldrbcs','ldrbhs','ldrbcc','ldrblo','ldrbmi','ldrbpl','ldrbvs','ldrbvc','ldrbhi','ldrbls','ldrbge','ldrblt','ldrbgt','ldrble',
+ 'ldrsheq.w','ldrshne.w','ldrshcs.w','ldrshhs.w','ldrshcc.w','ldrshlo.w','ldrshmi.w','ldrshpl.w','ldrshvs.w','ldrshvc.w','ldrshhi.w','ldrshls.w','ldrshge.w','ldrshlt.w','ldrshgt.w','ldrshle.w',
+ 'ldrsheq','ldrshne','ldrshcs','ldrshhs','ldrshcc','ldrshlo','ldrshmi','ldrshpl','ldrshvs','ldrshvc','ldrshhi','ldrshls','ldrshge','ldrshlt','ldrshgt','ldrshle',
+ 'ldrsbeq.w','ldrsbne.w','ldrsbcs.w','ldrsbhs.w','ldrsbcc.w','ldrsblo.w','ldrsbmi.w','ldrsbpl.w','ldrsbvs.w','ldrsbvc.w','ldrsbhi.w','ldrsbls.w','ldrsbge.w','ldrsblt.w','ldrsbgt.w','ldrsble.w',
+ 'ldrsbeq','ldrsbne','ldrsbcs','ldrsbhs','ldrsbcc','ldrsblo','ldrsbmi','ldrsbpl','ldrsbvs','ldrsbvc','ldrsbhi','ldrsbls','ldrsbge','ldrsblt','ldrsbgt','ldrsble',
+ 'ldrteq','ldrtne','ldrtcs','ldrths','ldrtcc','ldrtlo','ldrtmi','ldrtpl','ldrtvs','ldrtvc','ldrthi','ldrtls','ldrtge','ldrtlt','ldrtgt','ldrtle',
+ 'ldrhteq','ldrhtne','ldrhtcs','ldrhths','ldrhtcc','ldrhtlo','ldrhtmi','ldrhtpl','ldrhtvs','ldrhtvc','ldrhthi','ldrhtls','ldrhtge','ldrhtlt','ldrhtgt','ldrhtle',
+ 'ldrbteq','ldrbtne','ldrbtcs','ldrbths','ldrbtcc','ldrbtlo','ldrbtmi','ldrbtpl','ldrbtvs','ldrbtvc','ldrbthi','ldrbtls','ldrbtge','ldrbtlt','ldrbtgt','ldrbtle',
+ 'ldrshteq','ldrshtne','ldrshtcs','ldrshths','ldrshtcc','ldrshtlo','ldrshtmi','ldrshtpl','ldrshtvs','ldrshtvc','ldrshthi','ldrshtls','ldrshtge','ldrshtlt','ldrshtgt','ldrshtle',
+ 'ldrsbteq','ldrsbtne','ldrsbtcs','ldrsbths','ldrsbtcc','ldrsbtlo','ldrsbtmi','ldrsbtpl','ldrsbtvs','ldrsbtvc','ldrsbthi','ldrsbtls','ldrsbtge','ldrsbtlt','ldrsbtgt','ldrsbtle',
+ 'popeq.w','popne.w','popcs.w','pophs.w','popcc.w','poplo.w','popmi.w','poppl.w','popvs.w','popvc.w','pophi.w','popls.w','popge.w','poplt.w','popgt.w','pople.w',
+ 'popeq','popne','popcs','pophs','popcc','poplo','popmi','poppl','popvs','popvc','pophi','popls','popge','poplt','popgt','pople',
+ 'pldeq','pldne','pldcs','pldhs','pldcc','pldlo','pldmi','pldpl','pldvs','pldvc','pldhi','pldls','pldge','pldlt','pldgt','pldle',
+ 'pldweq','pldwne','pldwcs','pldwhs','pldwcc','pldwlo','pldwmi','pldwpl','pldwvs','pldwvc','pldwhi','pldwls','pldwge','pldwlt','pldwgt','pldwle',
+ 'plieq','pline','plics','plihs','plicc','plilo','plimi','plipl','plivs','plivc','plihi','plils','plige','plilt','pligt','plile',
+ /* Memory Access: Conditional Memory Stores */
+ 'stmeq.w','stmne.w','stmcs.w','stmhs.w','stmcc.w','stmlo.w','stmmi.w','stmpl.w','stmvs.w','stmvc.w','stmhi.w','stmls.w','stmge.w','stmlt.w','stmgt.w','stmle.w',
+ 'stmeq','stmne','stmcs','stmhs','stmcc','stmlo','stmmi','stmpl','stmvs','stmvc','stmhi','stmls','stmge','stmlt','stmgt','stmle',
+ 'stmdaeq','stmdane','stmdacs','stmdahs','stmdacc','stmdalo','stmdami','stmdapl','stmdavs','stmdavc','stmdahi','stmdals','stmdage','stmdalt','stmdagt','stmdale',
+ 'stmdbeq','stmdbne','stmdbcs','stmdbhs','stmdbcc','stmdblo','stmdbmi','stmdbpl','stmdbvs','stmdbvc','stmdbhi','stmdbls','stmdbge','stmdblt','stmdbgt','stmdble',
+ 'stmibeq','stmibne','stmibcs','stmibhs','stmibcc','stmiblo','stmibmi','stmibpl','stmibvs','stmibvc','stmibhi','stmibls','stmibge','stmiblt','stmibgt','stmible',
+ 'stmiaeq','stmiane','stmiacs','stmiahs','stmiacc','stmialo','stmiami','stmiapl','stmiavs','stmiavc','stmiahi','stmials','stmiage','stmialt','stmiagt','stmiale',
+ 'stmeaeq','stmeane','stmeacs','stmeahs','stmeacc','stmealo','stmeami','stmeapl','stmeavs','stmeavc','stmeahi','stmeals','stmeage','stmealt','stmeagt','stmeale',
+ 'stmedeq','stmedne','stmedcs','stmedhs','stmedcc','stmedlo','stmedmi','stmedpl','stmedvs','stmedvc','stmedhi','stmedls','stmedge','stmedlt','stmedgt','stmedle',
+ 'stdfaeq','stdfane','stdfacs','stdfahs','stdfacc','stdfalo','stdfami','stdfapl','stdfavs','stdfavc','stdfahi','stdfals','stdfage','stdfalt','stdfagt','stdfale',
+ 'stdfdeq','stdfdne','stdfdcs','stdfdhs','stdfdcc','stdfdlo','stdfdmi','stdfdpl','stdfdvs','stdfdvc','stdfdhi','stdfdls','stdfdge','stdfdlt','stdfdgt','stdfdle',
+ 'strdeq','strdne','strdcs','strdhs','strdcc','strdlo','strdmi','strdpl','strdvs','strdvc','strdhi','strdls','strdge','strdlt','strdgt','strdle',
+ 'streq.w','strne.w','strcs.w','strhs.w','strcc.w','strlo.w','strmi.w','strpl.w','strvs.w','strvc.w','strhi.w','strls.w','strge.w','strlt.w','strgt.w','strle.w',
+ 'streq','strne','strcs','strhs','strcc','strlo','strmi','strpl','strvs','strvc','strhi','strls','strge','strlt','strgt','strle',
+ 'strheq.w','strhne.w','strhcs.w','strhhs.w','strhcc.w','strhlo.w','strhmi.w','strhpl.w','strhvs.w','strhvc.w','strhhi.w','strhls.w','strhge.w','strhlt.w','strhgt.w','strhle.w',
+ 'strheq','strhne','strhcs','strhhs','strhcc','strhlo','strhmi','strhpl','strhvs','strhvc','strhhi','strhls','strhge','strhlt','strhgt','strhle',
+ 'strbeq.w','strbne.w','strbcs.w','strbhs.w','strbcc.w','strblo.w','strbmi.w','strbpl.w','strbvs.w','strbvc.w','strbhi.w','strbls.w','strbge.w','strblt.w','strbgt.w','strble.w',
+ 'strbeq','strbne','strbcs','strbhs','strbcc','strblo','strbmi','strbpl','strbvs','strbvc','strbhi','strbls','strbge','strblt','strbgt','strble',
+ 'strteq','strtne','strtcs','strths','strtcc','strtlo','strtmi','strtpl','strtvs','strtvc','strthi','strtls','strtge','strtlt','strtgt','strtle',
+ 'strhteq','strhtne','strhtcs','strhths','strhtcc','strhtlo','strhtmi','strhtpl','strhtvs','strhtvc','strhthi','strhtls','strhtge','strhtlt','strhtgt','strhtle',
+ 'strbteq','strbtne','strbtcs','strbths','strbtcc','strbtlo','strbtmi','strbtpl','strbtvs','strbtvc','strbthi','strbtls','strbtge','strbtlt','strbtgt','strbtle',
+ 'pusheq.w','pushne.w','pushcs.w','pushhs.w','pushcc.w','pushlo.w','pushmi.w','pushpl.w','pushvs.w','pushvc.w','pushhi.w','pushls.w','pushge.w','pushlt.w','pushgt.w','pushle.w',
+ 'pusheq','pushne','pushcs','pushhs','pushcc','pushlo','pushmi','pushpl','pushvs','pushvc','pushhi','pushls','pushge','pushlt','pushgt','pushle'
+ ),
+ /* Unconditional Flags-Affecting Instructions */
+ 5 => array(
+ /* Set Flags: Unconditional Addition and Subtraction */
+ 'adds.w','addsal.w',
+ 'adds','addsal',
+ 'subs.w','subsal.w',
+ 'subs','subsal',
+ 'rsbs.w','rsbsal.w',
+ 'rsbs','rsbsal',
+ 'negs.w','negsal.w',
+ 'negs','negsal',
+ 'adcs.w','adcsal.w',
+ 'adcs','adcsal',
+ 'sbcs.w','sbcsal.w',
+ 'sbcs','sbcsal',
+ 'rscs','rscsal',
+ 'cmp.w','cmpal.w',
+ 'cmp','cmpal',
+ 'cmn.w','cmnal.w',
+ 'cmn','cmnal',
+ /* Set Flags: Unconditional Logical */
+ 'ands.w','andsal.w',
+ 'ands','andsal',
+ 'bics.w','bicsal.w',
+ 'bics','bicsal',
+ 'orrs.w','orrsal.w',
+ 'orrs','orrsal',
+ 'orns.w','ornsal.w',
+ 'orns','ornsal',
+ 'eors.w','eorsal.w',
+ 'eors','eorsal',
+ 'mvns.w','mvnsal.w',
+ 'mvns','mvnsal',
+ 'movs.w','movsal.w',
+ 'movs','movsal',
+ 'teq','teqal',
+ 'tst.w','tstal.w',
+ 'tst','tstal',
+ 'mrs','mrsal',
+ 'msr','msral',
+ /* Set Flags: Unconditional Shifts and Rotates */
+ 'asrs.w','asrsal.w',
+ 'asrs','asrsal',
+ 'lsls.w','lslsal.w',
+ 'lsls','lslsal',
+ 'lsrs.w','lsrsal.w',
+ 'lsrs','lsrsal',
+ 'rors.w','rorsal.w',
+ 'rors','rorsal',
+ 'rrxs','rrxsal',
+ /* Set Flags: Unconditional Multiply and Multiply-Add */
+ 'mlas','mlasal',
+ 'smulls','smullsal',
+ 'umulls','umullsal',
+ 'smlals','smlalsal',
+ 'umlals','umlalsal'
+ ),
+ /* Conditional Flags-Affecting Instructions */
+ 6 => array(
+ /* Set Flags: Conditional Addition and Subtraction */
+ 'addseq.w','addsne.w','addscs.w','addshs.w','addscc.w','addslo.w','addsmi.w','addspl.w','addsvs.w','addsvc.w','addshi.w','addsls.w','addsge.w','addslt.w','addsgt.w','addsle.w',
+ 'addseq','addsne','addscs','addshs','addscc','addslo','addsmi','addspl','addsvs','addsvc','addshi','addsls','addsge','addslt','addsgt','addsle',
+ 'subseq.w','subsne.w','subscs.w','subshs.w','subscc.w','subslo.w','subsmi.w','subspl.w','subsvs.w','subsvc.w','subshi.w','subsls.w','subsge.w','subslt.w','subsgt.w','subsle.w',
+ 'subseq','subsne','subscs','subshs','subscc','subslo','subsmi','subspl','subsvs','subsvc','subshi','subsls','subsge','subslt','subsgt','subsle',
+ 'rsbseq.w','rsbsne.w','rsbscs.w','rsbshs.w','rsbscc.w','rsbslo.w','rsbsmi.w','rsbspl.w','rsbsvs.w','rsbsvc.w','rsbshi.w','rsbsls.w','rsbsge.w','rsbslt.w','rsbsgt.w','rsbsle.w',
+ 'rsbseq','rsbsne','rsbscs','rsbshs','rsbscc','rsbslo','rsbsmi','rsbspl','rsbsvs','rsbsvc','rsbshi','rsbsls','rsbsge','rsbslt','rsbsgt','rsbsle',
+ 'negseq.w','negsne.w','negscs.w','negshs.w','negscc.w','negslo.w','negsmi.w','negspl.w','negsvs.w','negsvc.w','negshi.w','negsls.w','negsge.w','negslt.w','negsgt.w','negsle.w',
+ 'negseq','negsne','negscs','negshs','negscc','negslo','negsmi','negspl','negsvs','negsvc','negshi','negsls','negsge','negslt','negsgt','negsle',
+ 'adcseq.w','adcsne.w','adcscs.w','adcshs.w','adcscc.w','adcslo.w','adcsmi.w','adcspl.w','adcsvs.w','adcsvc.w','adcshi.w','adcsls.w','adcsge.w','adcslt.w','adcsgt.w','adcsle.w',
+ 'adcseq','adcsne','adcscs','adcshs','adcscc','adcslo','adcsmi','adcspl','adcsvs','adcsvc','adcshi','adcsls','adcsge','adcslt','adcsgt','adcsle',
+ 'sbcseq.w','sbcsne.w','sbcscs.w','sbcshs.w','sbcscc.w','sbcslo.w','sbcsmi.w','sbcspl.w','sbcsvs.w','sbcsvc.w','sbcshi.w','sbcsls.w','sbcsge.w','sbcslt.w','sbcsgt.w','sbcsle.w',
+ 'sbcseq','sbcsne','sbcscs','sbcshs','sbcscc','sbcslo','sbcsmi','sbcspl','sbcsvs','sbcsvc','sbcshi','sbcsls','sbcsge','sbcslt','sbcsgt','sbcsle',
+ 'rscseq','rscsne','rscscs','rscshs','rscscc','rscslo','rscsmi','rscspl','rscsvs','rscsvc','rscshi','rscsls','rscsge','rscslt','rscsgt','rscsle',
+ 'cmpeq.w','cmpne.w','cmpcs.w','cmphs.w','cmpcc.w','cmplo.w','cmpmi.w','cmppl.w','cmpvs.w','cmpvc.w','cmphi.w','cmpls.w','cmpge.w','cmplt.w','cmpgt.w','cmple.w',
+ 'cmpeq','cmpne','cmpcs','cmphs','cmpcc','cmplo','cmpmi','cmppl','cmpvs','cmpvc','cmphi','cmpls','cmpge','cmplt','cmpgt','cmple',
+ 'cmneq.w','cmnne.w','cmncs.w','cmnhs.w','cmncc.w','cmnlo.w','cmnmi.w','cmnpl.w','cmnvs.w','cmnvc.w','cmnhi.w','cmnls.w','cmnge.w','cmnlt.w','cmngt.w','cmnle.w',
+ 'cmneq','cmnne','cmncs','cmnhs','cmncc','cmnlo','cmnmi','cmnpl','cmnvs','cmnvc','cmnhi','cmnls','cmnge','cmnlt','cmngt','cmnle',
+ /* Set Flags: Conditional Logical */
+ 'andseq.w','andsne.w','andscs.w','andshs.w','andscc.w','andslo.w','andsmi.w','andspl.w','andsvs.w','andsvc.w','andshi.w','andsls.w','andsge.w','andslt.w','andsgt.w','andsle.w',
+ 'andseq','andsne','andscs','andshs','andscc','andslo','andsmi','andspl','andsvs','andsvc','andshi','andsls','andsge','andslt','andsgt','andsle',
+ 'bicseq.w','bicsne.w','bicscs.w','bicshs.w','bicscc.w','bicslo.w','bicsmi.w','bicspl.w','bicsvs.w','bicsvc.w','bicshi.w','bicsls.w','bicsge.w','bicslt.w','bicsgt.w','bicsle.w',
+ 'bicseq','bicsne','bicscs','bicshs','bicscc','bicslo','bicsmi','bicspl','bicsvs','bicsvc','bicshi','bicsls','bicsge','bicslt','bicsgt','bicsle',
+ 'orrseq.w','orrsne.w','orrscs.w','orrshs.w','orrscc.w','orrslo.w','orrsmi.w','orrspl.w','orrsvs.w','orrsvc.w','orrshi.w','orrsls.w','orrsge.w','orrslt.w','orrsgt.w','orrsle.w',
+ 'orrseq','orrsne','orrscs','orrshs','orrscc','orrslo','orrsmi','orrspl','orrsvs','orrsvc','orrshi','orrsls','orrsge','orrslt','orrsgt','orrsle',
+ 'ornseq.w','ornsne.w','ornscs.w','ornshs.w','ornscc.w','ornslo.w','ornsmi.w','ornspl.w','ornsvs.w','ornsvc.w','ornshi.w','ornsls.w','ornsge.w','ornslt.w','ornsgt.w','ornsle.w',
+ 'ornseq','ornsne','ornscs','ornshs','ornscc','ornslo','ornsmi','ornspl','ornsvs','ornsvc','ornshi','ornsls','ornsge','ornslt','ornsgt','ornsle',
+ 'eorseq.w','eorsne.w','eorscs.w','eorshs.w','eorscc.w','eorslo.w','eorsmi.w','eorspl.w','eorsvs.w','eorsvc.w','eorshi.w','eorsls.w','eorsge.w','eorslt.w','eorsgt.w','eorsle.w',
+ 'eorseq','eorsne','eorscs','eorshs','eorscc','eorslo','eorsmi','eorspl','eorsvs','eorsvc','eorshi','eorsls','eorsge','eorslt','eorsgt','eorsle',
+ 'mvnseq.w','mvnsne.w','mvnscs.w','mvnshs.w','mvnscc.w','mvnslo.w','mvnsmi.w','mvnspl.w','mvnsvs.w','mvnsvc.w','mvnshi.w','mvnsls.w','mvnsge.w','mvnslt.w','mvnsgt.w','mvnsle.w',
+ 'mvnseq','mvnsne','mvnscs','mvnshs','mvnscc','mvnslo','mvnsmi','mvnspl','mvnsvs','mvnsvc','mvnshi','mvnsls','mvnsge','mvnslt','mvnsgt','mvnsle',
+ 'movseq.w','movsne.w','movscs.w','movshs.w','movscc.w','movslo.w','movsmi.w','movspl.w','movsvs.w','movsvc.w','movshi.w','movsls.w','movsge.w','movslt.w','movsgt.w','movsle.w',
+ 'movseq','movsne','movscs','movshs','movscc','movslo','movsmi','movspl','movsvs','movsvc','movshi','movsls','movsge','movslt','movsgt','movsle',
+ 'teqeq','teqne','teqcs','teqhs','teqcc','teqlo','teqmi','teqpl','teqvs','teqvc','teqhi','teqls','teqge','teqlt','teqgt','teqle',
+ 'tsteq.w','tstne.w','tstcs.w','tsths.w','tstcc.w','tstlo.w','tstmi.w','tstpl.w','tstvs.w','tstvc.w','tsthi.w','tstls.w','tstge.w','tstlt.w','tstgt.w','tstle.w',
+ 'tsteq','tstne','tstcs','tsths','tstcc','tstlo','tstmi','tstpl','tstvs','tstvc','tsthi','tstls','tstge','tstlt','tstgt','tstle',
+ 'mrseq','mrsne','mrscs','mrshs','mrscc','mrslo','mrsmi','mrspl','mrsvs','mrsvc','mrshi','mrsls','mrsge','mrslt','mrsgt','mrsle',
+ 'msreq','msrne','msrcs','msrhs','msrcc','msrlo','msrmi','msrpl','msrvs','msrvc','msrhi','msrls','msrge','msrlt','msrgt','msrle',
+ /* Set Flags: Conditional Shifts and Rotates */
+ 'asrseq.w','asrsne.w','asrscs.w','asrshs.w','asrscc.w','asrslo.w','asrsmi.w','asrspl.w','asrsvs.w','asrsvc.w','asrshi.w','asrsls.w','asrsge.w','asrslt.w','asrsgt.w','asrsle.w',
+ 'asrseq','asrsne','asrscs','asrshs','asrscc','asrslo','asrsmi','asrspl','asrsvs','asrsvc','asrshi','asrsls','asrsge','asrslt','asrsgt','asrsle',
+ 'lslseq.w','lslsne.w','lslscs.w','lslshs.w','lslscc.w','lslslo.w','lslsmi.w','lslspl.w','lslsvs.w','lslsvc.w','lslshi.w','lslsls.w','lslsge.w','lslslt.w','lslsgt.w','lslsle.w',
+ 'lslseq','lslsne','lslscs','lslshs','lslscc','lslslo','lslsmi','lslspl','lslsvs','lslsvc','lslshi','lslsls','lslsge','lslslt','lslsgt','lslsle',
+ 'lsrseq.w','lsrsne.w','lsrscs.w','lsrshs.w','lsrscc.w','lsrslo.w','lsrsmi.w','lsrspl.w','lsrsvs.w','lsrsvc.w','lsrshi.w','lsrsls.w','lsrsge.w','lsrslt.w','lsrsgt.w','lsrsle.w',
+ 'lsrseq','lsrsne','lsrscs','lsrshs','lsrscc','lsrslo','lsrsmi','lsrspl','lsrsvs','lsrsvc','lsrshi','lsrsls','lsrsge','lsrslt','lsrsgt','lsrsle',
+ 'rorseq.w','rorsne.w','rorscs.w','rorshs.w','rorscc.w','rorslo.w','rorsmi.w','rorspl.w','rorsvs.w','rorsvc.w','rorshi.w','rorsls.w','rorsge.w','rorslt.w','rorsgt.w','rorsle.w',
+ 'rorseq','rorsne','rorscs','rorshs','rorscc','rorslo','rorsmi','rorspl','rorsvs','rorsvc','rorshi','rorsls','rorsge','rorslt','rorsgt','rorsle',
+ 'rrxseq','rrxsne','rrxscs','rrxshs','rrxscc','rrxslo','rrxsmi','rrxspl','rrxsvs','rrxsvc','rrxshi','rrxsls','rrxsge','rrxslt','rrxsgt','rrxsle',
+ /* Set Flags: Conditional Multiply and Multiply-Add */
+ 'mlaseq','mlasne','mlascs','mlashs','mlascc','mlaslo','mlasmi','mlaspl','mlasvs','mlasvc','mlashi','mlasls','mlasge','mlaslt','mlasgt','mlasle',
+ 'smullseq','smullsne','smullscs','smullshs','smullscc','smullslo','smullsmi','smullspl','smullsvs','smullsvc','smullshi','smullsls','smullsge','smullslt','smullsgt','smullsle',
+ 'umullseq','umullsne','umullscs','umullshs','umullscc','umullslo','umullsmi','umullspl','umullsvs','umullsvc','umullshi','umullsls','umullsge','umullslt','umullsgt','umullsle',
+ 'smlalseq','smlalsne','smlalscs','smlalshs','smlalscc','smlalslo','smlalsmi','smlalspl','smlalsvs','smlalsvc','smlalshi','smlalsls','smlalsge','smlalslt','smlalsgt','smlalsle',
+ 'umlalseq','umlalsne','umlalscs','umlalshs','umlalscc','umlalslo','umlalsmi','umlalspl','umlalsvs','umlalsvc','umlalshi','umlalsls','umlalsge','umlalslt','umlalsgt','umlalsle'
+ ),
+ /* Unconditional Flow Control Instructions */
+ 7 => array(
+ /* Flow Control: Unconditional Branch and If-Then-Else */
+ 'b.w','bal.w',
+ 'b','bal',
+ 'bl','blal',
+ 'bx','bxal',
+ 'blx','blxal',
+ 'bxj','bxjal',
+ 'cbnz',
+ 'cbz',
+ 'tbb','tbbal',
+ 'tbh','tbhal',
+ 'it',
+ 'itt',
+ 'ite',
+ 'ittt',
+ 'itet',
+ 'itte',
+ 'itee',
+ 'itttt',
+ 'itett',
+ 'ittet',
+ 'iteet',
+ 'ittte',
+ 'itete',
+ 'ittee',
+ 'iteee'
+ ),
+ /* Conditional Flow Control Instructions */
+ 8 => array(
+ /* Flow Control: Conditional Branch and If-Then-Else */
+ 'beq.w','bne.w','bcs.w','bhs.w','bcc.w','blo.w','bmi.w','bpl.w','bvs.w','bvc.w','bhi.w','bls.w','bge.w','blt.w','bgt.w','ble.w',
+ 'beq','bne','bcs','bhs','bcc','blo','bmi','bpl','bvs','bvc','bhi','bls','bge','blt','bgt','ble',
+ 'bleq','blne','blcs','blhs','blcc','bllo','blmi','blpl','blvs','blvc','blhi','blls','blge','bllt','blgt','blle',
+ 'bxeq','bxne','bxcs','bxhs','bxcc','bxlo','bxmi','bxpl','bxvs','bxvc','bxhi','bxls','bxge','bxlt','bxgt','bxle',
+ 'blxeq','blxne','blxcs','blxhs','blxcc','blxlo','blxmi','blxpl','blxvs','blxvc','blxhi','blxls','blxge','blxlt','blxgt','blxle',
+ 'bxjeq','bxjne','bxjcs','bxjhs','bxjcc','bxjlo','bxjmi','bxjpl','bxjvs','bxjvc','bxjhi','bxjls','bxjge','bxjlt','bxjgt','bxjle',
+ 'tbbeq','tbbne','tbbcs','tbbhs','tbbcc','tbblo','tbbmi','tbbpl','tbbvs','tbbvc','tbbhi','tbbls','tbbge','tbblt','tbbgt','tbble',
+ 'tbheq','tbhne','tbhcs','tbhhs','tbhcc','tbhlo','tbhmi','tbhpl','tbhvs','tbhvc','tbhhi','tbhls','tbhge','tbhlt','tbhgt','tbhle'
+ ),
+ /* Unconditional Syncronization Instructions */
+ 9 => array(
+ /* Synchronization: Unconditional Loads, Stores and Barriers */
+ 'ldrexd','ldrexdal',
+ 'ldrex','ldrexal',
+ 'ldrexh','ldrexhal',
+ 'ldrexb','ldrexbal',
+ 'strexd','strexdal',
+ 'strex','strexal',
+ 'strexh','strexhal',
+ 'strexb','strexbal',
+ 'clrex','clrexal',
+ 'swp','swpal',
+ 'swpb','swpbal',
+ 'dbc','dbcal',
+ 'dsb','dsbal',
+ 'isb','isbal',
+ 'yield.w','yieldal.w',
+ 'yield','yieldal',
+ 'nop.w','nopal.w',
+ 'nop','nopal'
+ ),
+ /* Conditional Syncronization Instructions */
+ 10 => array(
+ /* Synchronization: Conditional Loads, Stores and Barriers */
+ 'ldrexdeq','ldrexdne','ldrexdcs','ldrexdhs','ldrexdcc','ldrexdlo','ldrexdmi','ldrexdpl','ldrexdvs','ldrexdvc','ldrexdhi','ldrexdls','ldrexdge','ldrexdlt','ldrexdgt','ldrexdle',
+ 'ldrexeq','ldrexne','ldrexcs','ldrexhs','ldrexcc','ldrexlo','ldrexmi','ldrexpl','ldrexvs','ldrexvc','ldrexhi','ldrexls','ldrexge','ldrexlt','ldrexgt','ldrexle',
+ 'ldrexheq','ldrexhne','ldrexhcs','ldrexhhs','ldrexhcc','ldrexhlo','ldrexhmi','ldrexhpl','ldrexhvs','ldrexhvc','ldrexhhi','ldrexhls','ldrexhge','ldrexhlt','ldrexhgt','ldrexhle',
+ 'ldrexbeq','ldrexbne','ldrexbcs','ldrexbhs','ldrexbcc','ldrexblo','ldrexbmi','ldrexbpl','ldrexbvs','ldrexbvc','ldrexbhi','ldrexbls','ldrexbge','ldrexblt','ldrexbgt','ldrexble',
+ 'strexdeq','strexdne','strexdcs','strexdhs','strexdcc','strexdlo','strexdmi','strexdpl','strexdvs','strexdvc','strexdhi','strexdls','strexdge','strexdlt','strexdgt','strexdle',
+ 'strexeq','strexne','strexcs','strexhs','strexcc','strexlo','strexmi','strexpl','strexvs','strexvc','strexhi','strexls','strexge','strexlt','strexgt','strexle',
+ 'strexheq','strexhne','strexhcs','strexhhs','strexhcc','strexhlo','strexhmi','strexhpl','strexhvs','strexhvc','strexhhi','strexhls','strexhge','strexhlt','strexhgt','strexhle',
+ 'strexbeq','strexbne','strexbcs','strexbhs','strexbcc','strexblo','strexbmi','strexbpl','strexbvs','strexbvc','strexbhi','strexbls','strexbge','strexblt','strexbgt','strexble',
+ 'clrexeq','clrexne','clrexcs','clrexhs','clrexcc','clrexlo','clrexmi','clrexpl','clrexvs','clrexvc','clrexhi','clrexls','clrexge','clrexlt','clrexgt','clrexle',
+ 'swpeq','swpne','swpcs','swphs','swpcc','swplo','swpmi','swppl','swpvs','swpvc','swphi','swpls','swpge','swplt','swpgt','swple',
+ 'swpbeq','swpbne','swpbcs','swpbhs','swpbcc','swpblo','swpbmi','swpbpl','swpbvs','swpbvc','swpbhi','swpbls','swpbge','swpblt','swpbgt','swpble',
+ 'dbceq','dbcne','dbccs','dbchs','dbccc','dbclo','dbcmi','dbcpl','dbcvs','dbcvc','dbchi','dbcls','dbcge','dbclt','dbcgt','dbcle',
+ 'dsbeq','dsbne','dsbcs','dsbhs','dsbcc','dsblo','dsbmi','dsbpl','dsbvs','dsbvc','dsbhi','dsbls','dsbge','dsblt','dsbgt','dsble',
+ 'isbeq','isbne','isbcs','isbhs','isbcc','isblo','isbmi','isbpl','isbvs','isbvc','isbhi','isbls','isbge','isblt','isbgt','isble',
+ 'yieldeq.w','yieldne.w','yieldcs.w','yieldhs.w','yieldcc.w','yieldlo.w','yieldmi.w','yieldpl.w','yieldvs.w','yieldvc.w','yieldhi.w','yieldls.w','yieldge.w','yieldlt.w','yieldgt.w','yieldle.w',
+ 'yieldeq','yieldne','yieldcs','yieldhs','yieldcc','yieldlo','yieldmi','yieldpl','yieldvs','yieldvc','yieldhi','yieldls','yieldge','yieldlt','yieldgt','yieldle',
+ 'nopeq.w','nopne.w','nopcs.w','nophs.w','nopcc.w','noplo.w','nopmi.w','noppl.w','nopvs.w','nopvc.w','nophi.w','nopls.w','nopge.w','noplt.w','nopgt.w','nople.w',
+ 'nopeq','nopne','nopcs','nophs','nopcc','noplo','nopmi','noppl','nopvs','nopvc','nophi','nopls','nopge','noplt','nopgt','nople'
+ ),
+ /* Unconditional ARMv6 SIMD */
+ 11 => array(
+ /* ARMv6 SIMD: Unconditional Addition, Subtraction & Saturation */
+ 'sadd16','sadd16al',
+ 'sadd8','sadd8al',
+ 'uadd16','uadd16al',
+ 'uadd8','uadd8al',
+ 'ssub16','ssub16al',
+ 'ssub8','ssub8al',
+ 'usub16','usub16al',
+ 'usub8','usub8al',
+ 'sasx','sasxal',
+ 'ssax','ssaxal',
+ 'uasx','uasxal',
+ 'usax','usaxal',
+ 'usad8','usad8al',
+ 'usada8','usada8al',
+ /* ARMv6 SIMD: Unconditional Halving Addition & Subtraction */
+ 'shadd16','shadd16al',
+ 'shadd8','shadd8al',
+ 'uhadd16','uhadd16al',
+ 'uhadd8','uhadd8al',
+ 'shsub16','shsub16al',
+ 'shsub8','shsub8al',
+ 'uhsub16','uhsub16al',
+ 'uhsub8','uhsub8al',
+ 'shasx','shasxal',
+ 'shsax','shsaxal',
+ 'uhasx','uhasxal',
+ 'uhsax','uhsaxal',
+ /* ARMv6 SIMD: Unconditional Saturating Operations */
+ 'qadd','qaddal',
+ 'qadd16','qadd16al',
+ 'qadd8','qadd8al',
+ 'uqadd16','uqadd16al',
+ 'uqadd8','uqadd8al',
+ 'qsub','qsubal',
+ 'qsub16','qsub16al',
+ 'qsub8','qsub8al',
+ 'uqsub16','uqsub16al',
+ 'uqsub8','uqsub8al',
+ 'qasx','qasxal',
+ 'qsax','qsaxal',
+ 'uqasx','uqasxal',
+ 'uqsax','uqsaxal',
+ 'qdadd','qdaddal',
+ 'qdsub','qdsubal',
+ 'ssat','ssatal',
+ 'ssat16','ssat16al',
+ 'usat','usatal',
+ 'usat16','usat16al',
+ /* ARMv6 SIMD: Unconditional Permutation and Combine Operations */
+ 'sxtah','sxtahal',
+ 'sxtab','sxtabal',
+ 'sxtab16','sxtab16al',
+ 'uxtah','uxtahal',
+ 'uxtab','uxtabal',
+ 'uxtab16','uxtab16al',
+ 'sxth.w','sxthal.w',
+ 'sxth','sxthal',
+ 'sxtb.w','sxtbal.w',
+ 'sxtb','sxtbal',
+ 'sxtb16','sxtb16al',
+ 'uxth.w','uxthal.w',
+ 'uxth','uxthal',
+ 'uxtb.w','uxtbal.w',
+ 'uxtb','uxtbal',
+ 'uxtb16','uxtb16al',
+ 'pkhbt','pkhbtal',
+ 'pkhtb','pkhtbal',
+ 'rbit','rbital',
+ 'rev.w','reval.w',
+ 'rev','reval',
+ 'rev16.w','rev16al.w',
+ 'rev16','rev16al',
+ 'revsh.w','revshal.w',
+ 'revsh','revshal',
+ 'sel','selal',
+ /* ARMv6 SIMD: Unconditional Multiply and Multiply-Add */
+ 'smlad','smladal',
+ 'smladx','smladxal',
+ 'smlsd','smlsdal',
+ 'smlsdx','smlsdxal',
+ 'smlald','smlaldal',
+ 'smlaldx','smlaldxal',
+ 'smlsld','smlsldal',
+ 'smlsldx','smlsldxal',
+ 'smmul','smmulal',
+ 'smmulr','smmulral',
+ 'smmla','smmlaal',
+ 'smmlar','smmlaral',
+ 'smmls','smmlsal',
+ 'smmlsr','smmlsral',
+ 'smuad','smuadal',
+ 'smuadx','smuadxal',
+ 'smusd','smusdal',
+ 'smusdx','smusdxal',
+ 'umaal','umaalal'
+ ),
+ /* Conditional ARMv6 SIMD */
+ 12 => array(
+ /* ARMv6 SIMD: Conditional Addition, Subtraction & Saturation */
+ 'sadd16eq','sadd16ne','sadd16cs','sadd16hs','sadd16cc','sadd16lo','sadd16mi','sadd16pl','sadd16vs','sadd16vc','sadd16hi','sadd16ls','sadd16ge','sadd16lt','sadd16gt','sadd16le',
+ 'sadd8eq','sadd8ne','sadd8cs','sadd8hs','sadd8cc','sadd8lo','sadd8mi','sadd8pl','sadd8vs','sadd8vc','sadd8hi','sadd8ls','sadd8ge','sadd8lt','sadd8gt','sadd8le',
+ 'uadd16eq','uadd16ne','uadd16cs','uadd16hs','uadd16cc','uadd16lo','uadd16mi','uadd16pl','uadd16vs','uadd16vc','uadd16hi','uadd16ls','uadd16ge','uadd16lt','uadd16gt','uadd16le',
+ 'uadd8eq','uadd8ne','uadd8cs','uadd8hs','uadd8cc','uadd8lo','uadd8mi','uadd8pl','uadd8vs','uadd8vc','uadd8hi','uadd8ls','uadd8ge','uadd8lt','uadd8gt','uadd8le',
+ 'ssub16eq','ssub16ne','ssub16cs','ssub16hs','ssub16cc','ssub16lo','ssub16mi','ssub16pl','ssub16vs','ssub16vc','ssub16hi','ssub16ls','ssub16ge','ssub16lt','ssub16gt','ssub16le',
+ 'ssub8eq','ssub8ne','ssub8cs','ssub8hs','ssub8cc','ssub8lo','ssub8mi','ssub8pl','ssub8vs','ssub8vc','ssub8hi','ssub8ls','ssub8ge','ssub8lt','ssub8gt','ssub8le',
+ 'usub16eq','usub16ne','usub16cs','usub16hs','usub16cc','usub16lo','usub16mi','usub16pl','usub16vs','usub16vc','usub16hi','usub16ls','usub16ge','usub16lt','usub16gt','usub16le',
+ 'usub8eq','usub8ne','usub8cs','usub8hs','usub8cc','usub8lo','usub8mi','usub8pl','usub8vs','usub8vc','usub8hi','usub8ls','usub8ge','usub8lt','usub8gt','usub8le',
+ 'sasxeq','sasxne','sasxcs','sasxhs','sasxcc','sasxlo','sasxmi','sasxpl','sasxvs','sasxvc','sasxhi','sasxls','sasxge','sasxlt','sasxgt','sasxle',
+ 'ssaxeq','ssaxne','ssaxcs','ssaxhs','ssaxcc','ssaxlo','ssaxmi','ssaxpl','ssaxvs','ssaxvc','ssaxhi','ssaxls','ssaxge','ssaxlt','ssaxgt','ssaxle',
+ 'uasxeq','uasxne','uasxcs','uasxhs','uasxcc','uasxlo','uasxmi','uasxpl','uasxvs','uasxvc','uasxhi','uasxls','uasxge','uasxlt','uasxgt','uasxle',
+ 'usaxeq','usaxne','usaxcs','usaxhs','usaxcc','usaxlo','usaxmi','usaxpl','usaxvs','usaxvc','usaxhi','usaxls','usaxge','usaxlt','usaxgt','usaxle',
+ 'usad8eq','usad8ne','usad8cs','usad8hs','usad8cc','usad8lo','usad8mi','usad8pl','usad8vs','usad8vc','usad8hi','usad8ls','usad8ge','usad8lt','usad8gt','usad8le',
+ 'usada8eq','usada8ne','usada8cs','usada8hs','usada8cc','usada8lo','usada8mi','usada8pl','usada8vs','usada8vc','usada8hi','usada8ls','usada8ge','usada8lt','usada8gt','usada8le',
+ /* ARMv6 SIMD: Conditional Halving Addition & Subtraction */
+ 'shadd16eq','shadd16ne','shadd16cs','shadd16hs','shadd16cc','shadd16lo','shadd16mi','shadd16pl','shadd16vs','shadd16vc','shadd16hi','shadd16ls','shadd16ge','shadd16lt','shadd16gt','shadd16le',
+ 'shadd8eq','shadd8ne','shadd8cs','shadd8hs','shadd8cc','shadd8lo','shadd8mi','shadd8pl','shadd8vs','shadd8vc','shadd8hi','shadd8ls','shadd8ge','shadd8lt','shadd8gt','shadd8le',
+ 'uhadd16eq','uhadd16ne','uhadd16cs','uhadd16hs','uhadd16cc','uhadd16lo','uhadd16mi','uhadd16pl','uhadd16vs','uhadd16vc','uhadd16hi','uhadd16ls','uhadd16ge','uhadd16lt','uhadd16gt','uhadd16le',
+ 'uhadd8eq','uhadd8ne','uhadd8cs','uhadd8hs','uhadd8cc','uhadd8lo','uhadd8mi','uhadd8pl','uhadd8vs','uhadd8vc','uhadd8hi','uhadd8ls','uhadd8ge','uhadd8lt','uhadd8gt','uhadd8le',
+ 'shsub16eq','shsub16ne','shsub16cs','shsub16hs','shsub16cc','shsub16lo','shsub16mi','shsub16pl','shsub16vs','shsub16vc','shsub16hi','shsub16ls','shsub16ge','shsub16lt','shsub16gt','shsub16le',
+ 'shsub8eq','shsub8ne','shsub8cs','shsub8hs','shsub8cc','shsub8lo','shsub8mi','shsub8pl','shsub8vs','shsub8vc','shsub8hi','shsub8ls','shsub8ge','shsub8lt','shsub8gt','shsub8le',
+ 'uhsub16eq','uhsub16ne','uhsub16cs','uhsub16hs','uhsub16cc','uhsub16lo','uhsub16mi','uhsub16pl','uhsub16vs','uhsub16vc','uhsub16hi','uhsub16ls','uhsub16ge','uhsub16lt','uhsub16gt','uhsub16le',
+ 'uhsub8eq','uhsub8ne','uhsub8cs','uhsub8hs','uhsub8cc','uhsub8lo','uhsub8mi','uhsub8pl','uhsub8vs','uhsub8vc','uhsub8hi','uhsub8ls','uhsub8ge','uhsub8lt','uhsub8gt','uhsub8le',
+ 'shasxeq','shasxne','shasxcs','shasxhs','shasxcc','shasxlo','shasxmi','shasxpl','shasxvs','shasxvc','shasxhi','shasxls','shasxge','shasxlt','shasxgt','shasxle',
+ 'shsaxeq','shsaxne','shsaxcs','shsaxhs','shsaxcc','shsaxlo','shsaxmi','shsaxpl','shsaxvs','shsaxvc','shsaxhi','shsaxls','shsaxge','shsaxlt','shsaxgt','shsaxle',
+ 'uhasxeq','uhasxne','uhasxcs','uhasxhs','uhasxcc','uhasxlo','uhasxmi','uhasxpl','uhasxvs','uhasxvc','uhasxhi','uhasxls','uhasxge','uhasxlt','uhasxgt','uhasxle',
+ 'uhsaxeq','uhsaxne','uhsaxcs','uhsaxhs','uhsaxcc','uhsaxlo','uhsaxmi','uhsaxpl','uhsaxvs','uhsaxvc','uhsaxhi','uhsaxls','uhsaxge','uhsaxlt','uhsaxgt','uhsaxle',
+ /* ARMv6 SIMD: Conditional Saturating Operations */
+ 'qaddeq','qaddne','qaddcs','qaddhs','qaddcc','qaddlo','qaddmi','qaddpl','qaddvs','qaddvc','qaddhi','qaddls','qaddge','qaddlt','qaddgt','qaddle',
+ 'qadd16eq','qadd16ne','qadd16cs','qadd16hs','qadd16cc','qadd16lo','qadd16mi','qadd16pl','qadd16vs','qadd16vc','qadd16hi','qadd16ls','qadd16ge','qadd16lt','qadd16gt','qadd16le',
+ 'qadd8eq','qadd8ne','qadd8cs','qadd8hs','qadd8cc','qadd8lo','qadd8mi','qadd8pl','qadd8vs','qadd8vc','qadd8hi','qadd8ls','qadd8ge','qadd8lt','qadd8gt','qadd8le',
+ 'uqadd16eq','uqadd16ne','uqadd16cs','uqadd16hs','uqadd16cc','uqadd16lo','uqadd16mi','uqadd16pl','uqadd16vs','uqadd16vc','uqadd16hi','uqadd16ls','uqadd16ge','uqadd16lt','uqadd16gt','uqadd16le',
+ 'uqadd8eq','uqadd8ne','uqadd8cs','uqadd8hs','uqadd8cc','uqadd8lo','uqadd8mi','uqadd8pl','uqadd8vs','uqadd8vc','uqadd8hi','uqadd8ls','uqadd8ge','uqadd8lt','uqadd8gt','uqadd8le',
+ 'qsubeq','qsubne','qsubcs','qsubhs','qsubcc','qsublo','qsubmi','qsubpl','qsubvs','qsubvc','qsubhi','qsubls','qsubge','qsublt','qsubgt','qsuble',
+ 'qsub16eq','qsub16ne','qsub16cs','qsub16hs','qsub16cc','qsub16lo','qsub16mi','qsub16pl','qsub16vs','qsub16vc','qsub16hi','qsub16ls','qsub16ge','qsub16lt','qsub16gt','qsub16le',
+ 'qsub8eq','qsub8ne','qsub8cs','qsub8hs','qsub8cc','qsub8lo','qsub8mi','qsub8pl','qsub8vs','qsub8vc','qsub8hi','qsub8ls','qsub8ge','qsub8lt','qsub8gt','qsub8le',
+ 'uqsub16eq','uqsub16ne','uqsub16cs','uqsub16hs','uqsub16cc','uqsub16lo','uqsub16mi','uqsub16pl','uqsub16vs','uqsub16vc','uqsub16hi','uqsub16ls','uqsub16ge','uqsub16lt','uqsub16gt','uqsub16le',
+ 'uqsub8eq','uqsub8ne','uqsub8cs','uqsub8hs','uqsub8cc','uqsub8lo','uqsub8mi','uqsub8pl','uqsub8vs','uqsub8vc','uqsub8hi','uqsub8ls','uqsub8ge','uqsub8lt','uqsub8gt','uqsub8le',
+ 'qasxeq','qasxne','qasxcs','qasxhs','qasxcc','qasxlo','qasxmi','qasxpl','qasxvs','qasxvc','qasxhi','qasxls','qasxge','qasxlt','qasxgt','qasxle',
+ 'qsaxeq','qsaxne','qsaxcs','qsaxhs','qsaxcc','qsaxlo','qsaxmi','qsaxpl','qsaxvs','qsaxvc','qsaxhi','qsaxls','qsaxge','qsaxlt','qsaxgt','qsaxle',
+ 'uqasxeq','uqasxne','uqasxcs','uqasxhs','uqasxcc','uqasxlo','uqasxmi','uqasxpl','uqasxvs','uqasxvc','uqasxhi','uqasxls','uqasxge','uqasxlt','uqasxgt','uqasxle',
+ 'uqsaxeq','uqsaxne','uqsaxcs','uqsaxhs','uqsaxcc','uqsaxlo','uqsaxmi','uqsaxpl','uqsaxvs','uqsaxvc','uqsaxhi','uqsaxls','uqsaxge','uqsaxlt','uqsaxgt','uqsaxle',
+ 'qdaddeq','qdaddne','qdaddcs','qdaddhs','qdaddcc','qdaddlo','qdaddmi','qdaddpl','qdaddvs','qdaddvc','qdaddhi','qdaddls','qdaddge','qdaddlt','qdaddgt','qdaddle',
+ 'qdsubeq','qdsubne','qdsubcs','qdsubhs','qdsubcc','qdsublo','qdsubmi','qdsubpl','qdsubvs','qdsubvc','qdsubhi','qdsubls','qdsubge','qdsublt','qdsubgt','qdsuble',
+ 'ssateq','ssatne','ssatcs','ssaths','ssatcc','ssatlo','ssatmi','ssatpl','ssatvs','ssatvc','ssathi','ssatls','ssatge','ssatlt','ssatgt','ssatle',
+ 'ssat16eq','ssat16ne','ssat16cs','ssat16hs','ssat16cc','ssat16lo','ssat16mi','ssat16pl','ssat16vs','ssat16vc','ssat16hi','ssat16ls','ssat16ge','ssat16lt','ssat16gt','ssat16le',
+ 'usateq','usatne','usatcs','usaths','usatcc','usatlo','usatmi','usatpl','usatvs','usatvc','usathi','usatls','usatge','usatlt','usatgt','usatle',
+ 'usat16eq','usat16ne','usat16cs','usat16hs','usat16cc','usat16lo','usat16mi','usat16pl','usat16vs','usat16vc','usat16hi','usat16ls','usat16ge','usat16lt','usat16gt','usat16le',
+ /* ARMv6 SIMD: Conditional Permutation and Combine Operations */
+ 'sxtaheq','sxtahne','sxtahcs','sxtahhs','sxtahcc','sxtahlo','sxtahmi','sxtahpl','sxtahvs','sxtahvc','sxtahhi','sxtahls','sxtahge','sxtahlt','sxtahgt','sxtahle',
+ 'sxtabeq','sxtabne','sxtabcs','sxtabhs','sxtabcc','sxtablo','sxtabmi','sxtabpl','sxtabvs','sxtabvc','sxtabhi','sxtabls','sxtabge','sxtablt','sxtabgt','sxtable',
+ 'sxtab16eq','sxtab16ne','sxtab16cs','sxtab16hs','sxtab16cc','sxtab16lo','sxtab16mi','sxtab16pl','sxtab16vs','sxtab16vc','sxtab16hi','sxtab16ls','sxtab16ge','sxtab16lt','sxtab16gt','sxtab16le',
+ 'uxtaheq','uxtahne','uxtahcs','uxtahhs','uxtahcc','uxtahlo','uxtahmi','uxtahpl','uxtahvs','uxtahvc','uxtahhi','uxtahls','uxtahge','uxtahlt','uxtahgt','uxtahle',
+ 'uxtabeq','uxtabne','uxtabcs','uxtabhs','uxtabcc','uxtablo','uxtabmi','uxtabpl','uxtabvs','uxtabvc','uxtabhi','uxtabls','uxtabge','uxtablt','uxtabgt','uxtable',
+ 'uxtab16eq','uxtab16ne','uxtab16cs','uxtab16hs','uxtab16cc','uxtab16lo','uxtab16mi','uxtab16pl','uxtab16vs','uxtab16vc','uxtab16hi','uxtab16ls','uxtab16ge','uxtab16lt','uxtab16gt','uxtab16le',
+ 'sxtheq.w','sxthne.w','sxthcs.w','sxthhs.w','sxthcc.w','sxthlo.w','sxthmi.w','sxthpl.w','sxthvs.w','sxthvc.w','sxthhi.w','sxthls.w','sxthge.w','sxthlt.w','sxthgt.w','sxthle.w',
+ 'sxtheq','sxthne','sxthcs','sxthhs','sxthcc','sxthlo','sxthmi','sxthpl','sxthvs','sxthvc','sxthhi','sxthls','sxthge','sxthlt','sxthgt','sxthle',
+ 'sxtbeq.w','sxtbne.w','sxtbcs.w','sxtbhs.w','sxtbcc.w','sxtblo.w','sxtbmi.w','sxtbpl.w','sxtbvs.w','sxtbvc.w','sxtbhi.w','sxtbls.w','sxtbge.w','sxtblt.w','sxtbgt.w','sxtble.w',
+ 'sxtbeq','sxtbne','sxtbcs','sxtbhs','sxtbcc','sxtblo','sxtbmi','sxtbpl','sxtbvs','sxtbvc','sxtbhi','sxtbls','sxtbge','sxtblt','sxtbgt','sxtble',
+ 'sxtb16eq','sxtb16ne','sxtb16cs','sxtb16hs','sxtb16cc','sxtb16lo','sxtb16mi','sxtb16pl','sxtb16vs','sxtb16vc','sxtb16hi','sxtb16ls','sxtb16ge','sxtb16lt','sxtb16gt','sxtb16le',
+ 'uxtheq.w','uxthne.w','uxthcs.w','uxthhs.w','uxthcc.w','uxthlo.w','uxthmi.w','uxthpl.w','uxthvs.w','uxthvc.w','uxthhi.w','uxthls.w','uxthge.w','uxthlt.w','uxthgt.w','uxthle.w',
+ 'uxtheq','uxthne','uxthcs','uxthhs','uxthcc','uxthlo','uxthmi','uxthpl','uxthvs','uxthvc','uxthhi','uxthls','uxthge','uxthlt','uxthgt','uxthle',
+ 'uxtbeq.w','uxtbne.w','uxtbcs.w','uxtbhs.w','uxtbcc.w','uxtblo.w','uxtbmi.w','uxtbpl.w','uxtbvs.w','uxtbvc.w','uxtbhi.w','uxtbls.w','uxtbge.w','uxtblt.w','uxtbgt.w','uxtble.w',
+ 'uxtbeq','uxtbne','uxtbcs','uxtbhs','uxtbcc','uxtblo','uxtbmi','uxtbpl','uxtbvs','uxtbvc','uxtbhi','uxtbls','uxtbge','uxtblt','uxtbgt','uxtble',
+ 'uxtb16eq','uxtb16ne','uxtb16cs','uxtb16hs','uxtb16cc','uxtb16lo','uxtb16mi','uxtb16pl','uxtb16vs','uxtb16vc','uxtb16hi','uxtb16ls','uxtb16ge','uxtb16lt','uxtb16gt','uxtb16le',
+ 'pkhbteq','pkhbtne','pkhbtcs','pkhbths','pkhbtcc','pkhbtlo','pkhbtmi','pkhbtpl','pkhbtvs','pkhbtvc','pkhbthi','pkhbtls','pkhbtge','pkhbtlt','pkhbtgt','pkhbtle',
+ 'pkhtbeq','pkhtbne','pkhtbcs','pkhtbhs','pkhtbcc','pkhtblo','pkhtbmi','pkhtbpl','pkhtbvs','pkhtbvc','pkhtbhi','pkhtbls','pkhtbge','pkhtblt','pkhtbgt','pkhtble',
+ 'rbiteq','rbitne','rbitcs','rbiths','rbitcc','rbitlo','rbitmi','rbitpl','rbitvs','rbitvc','rbithi','rbitls','rbitge','rbitlt','rbitgt','rbitle',
+ 'reveq.w','revne.w','revcs.w','revhs.w','revcc.w','revlo.w','revmi.w','revpl.w','revvs.w','revvc.w','revhi.w','revls.w','revge.w','revlt.w','revgt.w','revle.w',
+ 'reveq','revne','revcs','revhs','revcc','revlo','revmi','revpl','revvs','revvc','revhi','revls','revge','revlt','revgt','revle',
+ 'rev16eq.w','rev16ne.w','rev16cs.w','rev16hs.w','rev16cc.w','rev16lo.w','rev16mi.w','rev16pl.w','rev16vs.w','rev16vc.w','rev16hi.w','rev16ls.w','rev16ge.w','rev16lt.w','rev16gt.w','rev16le.w',
+ 'rev16eq','rev16ne','rev16cs','rev16hs','rev16cc','rev16lo','rev16mi','rev16pl','rev16vs','rev16vc','rev16hi','rev16ls','rev16ge','rev16lt','rev16gt','rev16le',
+ 'revsheq.w','revshne.w','revshcs.w','revshhs.w','revshcc.w','revshlo.w','revshmi.w','revshpl.w','revshvs.w','revshvc.w','revshhi.w','revshls.w','revshge.w','revshlt.w','revshgt.w','revshle.w',
+ 'revsheq','revshne','revshcs','revshhs','revshcc','revshlo','revshmi','revshpl','revshvs','revshvc','revshhi','revshls','revshge','revshlt','revshgt','revshle',
+ 'seleq','selne','selcs','selhs','selcc','sello','selmi','selpl','selvs','selvc','selhi','sells','selge','sellt','selgt','selle',
+ /* ARMv6 SIMD: Conditional Multiply and Multiply-Add */
+ 'smladeq','smladne','smladcs','smladhs','smladcc','smladlo','smladmi','smladpl','smladvs','smladvc','smladhi','smladls','smladge','smladlt','smladgt','smladle',
+ 'smladxeq','smladxne','smladxcs','smladxhs','smladxcc','smladxlo','smladxmi','smladxpl','smladxvs','smladxvc','smladxhi','smladxls','smladxge','smladxlt','smladxgt','smladxle',
+ 'smlsdeq','smlsdne','smlsdcs','smlsdhs','smlsdcc','smlsdlo','smlsdmi','smlsdpl','smlsdvs','smlsdvc','smlsdhi','smlsdls','smlsdge','smlsdlt','smlsdgt','smlsdle',
+ 'smlsdxeq','smlsdxne','smlsdxcs','smlsdxhs','smlsdxcc','smlsdxlo','smlsdxmi','smlsdxpl','smlsdxvs','smlsdxvc','smlsdxhi','smlsdxls','smlsdxge','smlsdxlt','smlsdxgt','smlsdxle',
+ 'smlaldeq','smlaldne','smlaldcs','smlaldhs','smlaldcc','smlaldlo','smlaldmi','smlaldpl','smlaldvs','smlaldvc','smlaldhi','smlaldls','smlaldge','smlaldlt','smlaldgt','smlaldle',
+ 'smlaldxeq','smlaldxne','smlaldxcs','smlaldxhs','smlaldxcc','smlaldxlo','smlaldxmi','smlaldxpl','smlaldxvs','smlaldxvc','smlaldxhi','smlaldxls','smlaldxge','smlaldxlt','smlaldxgt','smlaldxle',
+ 'smlsldeq','smlsldne','smlsldcs','smlsldhs','smlsldcc','smlsldlo','smlsldmi','smlsldpl','smlsldvs','smlsldvc','smlsldhi','smlsldls','smlsldge','smlsldlt','smlsldgt','smlsldle',
+ 'smlsldxeq','smlsldxne','smlsldxcs','smlsldxhs','smlsldxcc','smlsldxlo','smlsldxmi','smlsldxpl','smlsldxvs','smlsldxvc','smlsldxhi','smlsldxls','smlsldxge','smlsldxlt','smlsldxgt','smlsldxle',
+ 'smmuleq','smmulne','smmulcs','smmulhs','smmulcc','smmullo','smmulmi','smmulpl','smmulvs','smmulvc','smmulhi','smmulls','smmulge','smmullt','smmulgt','smmulle',
+ 'smmulreq','smmulrne','smmulrcs','smmulrhs','smmulrcc','smmulrlo','smmulrmi','smmulrpl','smmulrvs','smmulrvc','smmulrhi','smmulrls','smmulrge','smmulrlt','smmulrgt','smmulrle',
+ 'smmlaeq','smmlane','smmlacs','smmlahs','smmlacc','smmlalo','smmlami','smmlapl','smmlavs','smmlavc','smmlahi','smmlals','smmlage','smmlalt','smmlagt','smmlale',
+ 'smmlareq','smmlarne','smmlarcs','smmlarhs','smmlarcc','smmlarlo','smmlarmi','smmlarpl','smmlarvs','smmlarvc','smmlarhi','smmlarls','smmlarge','smmlarlt','smmlargt','smmlarle',
+ 'smmlseq','smmlsne','smmlscs','smmlshs','smmlscc','smmlslo','smmlsmi','smmlspl','smmlsvs','smmlsvc','smmlshi','smmlsls','smmlsge','smmlslt','smmlsgt','smmlsle',
+ 'smmlsreq','smmlsrne','smmlsrcs','smmlsrhs','smmlsrcc','smmlsrlo','smmlsrmi','smmlsrpl','smmlsrvs','smmlsrvc','smmlsrhi','smmlsrls','smmlsrge','smmlsrlt','smmlsrgt','smmlsrle',
+ 'smuadeq','smuadne','smuadcs','smuadhs','smuadcc','smuadlo','smuadmi','smuadpl','smuadvs','smuadvc','smuadhi','smuadls','smuadge','smuadlt','smuadgt','smuadle',
+ 'smuadxeq','smuadxne','smuadxcs','smuadxhs','smuadxcc','smuadxlo','smuadxmi','smuadxpl','smuadxvs','smuadxvc','smuadxhi','smuadxls','smuadxge','smuadxlt','smuadxgt','smuadxle',
+ 'smusdeq','smusdne','smusdcs','smusdhs','smusdcc','smusdlo','smusdmi','smusdpl','smusdvs','smusdvc','smusdhi','smusdls','smusdge','smusdlt','smusdgt','smusdle',
+ 'smusdxeq','smusdxne','smusdxcs','smusdxhs','smusdxcc','smusdxlo','smusdxmi','smusdxpl','smusdxvs','smusdxvc','smusdxhi','smusdxls','smusdxge','smusdxlt','smusdxgt','smusdxle',
+ 'umaaleq','umaalne','umaalcs','umaalhs','umaalcc','umaallo','umaalmi','umaalpl','umaalvs','umaalvc','umaalhi','umaalls','umaalge','umaallt','umaalgt','umaalle'
+ ),
+ /* Unconditional Coprocessor Instructions */
+ 13 => array(
+ /* Data Processing: Unconditional Coprocessor Instructions */
+ 'cdp','cdpal',
+ 'cdp2','cdp2al',
+ 'ldc','ldcal',
+ 'ldcl','ldclal',
+ 'ldc2','ldc2al',
+ 'ldc2l','ldc2lal',
+ 'stc','stcal',
+ 'stcl','stclal',
+ 'stc2','stc2al',
+ 'stc2l','stc2lal',
+ 'mcr','mcral',
+ 'mcr2','mcr2al',
+ 'mcrr','mcrral',
+ 'mcrr2','mcrr2al',
+ 'mrc','mrcal',
+ 'mrc2','mrc2al',
+ 'mrrc','mrrcal',
+ 'mrrc2','mrrc2al'
+ ),
+ /* Conditional Coprocessor Instructions */
+ 14 => array(
+ /* Data Processing: Conditional Coprocessor Instructions */
+ 'cdpeq','cdpne','cdpcs','cdphs','cdpcc','cdplo','cdpmi','cdppl','cdpvs','cdpvc','cdphi','cdpls','cdpge','cdplt','cdpgt','cdple',
+ 'cdp2eq','cdp2ne','cdp2cs','cdp2hs','cdp2cc','cdp2lo','cdp2mi','cdp2pl','cdp2vs','cdp2vc','cdp2hi','cdp2ls','cdp2ge','cdp2lt','cdp2gt','cdp2le',
+ 'ldceq','ldcne','ldccs','ldchs','ldccc','ldclo','ldcmi','ldcpl','ldcvs','ldcvc','ldchi','ldcls','ldcge','ldclt','ldcgt','ldcle',
+ 'ldcleq','ldclne','ldclcs','ldclhs','ldclcc','ldcllo','ldclmi','ldclpl','ldclvs','ldclvc','ldclhi','ldclls','ldclge','ldcllt','ldclgt','ldclle',
+ 'ldc2eq','ldc2ne','ldc2cs','ldc2hs','ldc2cc','ldc2lo','ldc2mi','ldc2pl','ldc2vs','ldc2vc','ldc2hi','ldc2ls','ldc2ge','ldc2lt','ldc2gt','ldc2le',
+ 'ldc2leq','ldc2lne','ldc2lcs','ldc2lhs','ldc2lcc','ldc2llo','ldc2lmi','ldc2lpl','ldc2lvs','ldc2lvc','ldc2lhi','ldc2lls','ldc2lge','ldc2llt','ldc2lgt','ldc2lle',
+ 'stceq','stcne','stccs','stchs','stccc','stclo','stcmi','stcpl','stcvs','stcvc','stchi','stcls','stcge','stclt','stcgt','stcle',
+ 'stcleq','stclne','stclcs','stclhs','stclcc','stcllo','stclmi','stclpl','stclvs','stclvc','stclhi','stclls','stclge','stcllt','stclgt','stclle',
+ 'stc2eq','stc2ne','stc2cs','stc2hs','stc2cc','stc2lo','stc2mi','stc2pl','stc2vs','stc2vc','stc2hi','stc2ls','stc2ge','stc2lt','stc2gt','stc2le',
+ 'stc2leq','stc2lne','stc2lcs','stc2lhs','stc2lcc','stc2llo','stc2lmi','stc2lpl','stc2lvs','stc2lvc','stc2lhi','stc2lls','stc2lge','stc2llt','stc2lgt','stc2lle',
+ 'mcreq','mcrne','mcrcs','mcrhs','mcrcc','mcrlo','mcrmi','mcrpl','mcrvs','mcrvc','mcrhi','mcrls','mcrge','mcrlt','mcrgt','mcrle',
+ 'mcr2eq','mcr2ne','mcr2cs','mcr2hs','mcr2cc','mcr2lo','mcr2mi','mcr2pl','mcr2vs','mcr2vc','mcr2hi','mcr2ls','mcr2ge','mcr2lt','mcr2gt','mcr2le',
+ 'mcrreq','mcrrne','mcrrcs','mcrrhs','mcrrcc','mcrrlo','mcrrmi','mcrrpl','mcrrvs','mcrrvc','mcrrhi','mcrrls','mcrrge','mcrrlt','mcrrgt','mcrrle',
+ 'mcrr2eq','mcrr2ne','mcrr2cs','mcrr2hs','mcrr2cc','mcrr2lo','mcrr2mi','mcrr2pl','mcrr2vs','mcrr2vc','mcrr2hi','mcrr2ls','mcrr2ge','mcrr2lt','mcrr2gt','mcrr2le',
+ 'mrceq','mrcne','mrccs','mrchs','mrccc','mrclo','mrcmi','mrcpl','mrcvs','mrcvc','mrchi','mrcls','mrcge','mrclt','mrcgt','mrcle',
+ 'mrc2eq','mrc2ne','mrc2cs','mrc2hs','mrc2cc','mrc2lo','mrc2mi','mrc2pl','mrc2vs','mrc2vc','mrc2hi','mrc2ls','mrc2ge','mrc2lt','mrc2gt','mrc2le',
+ 'mrrceq','mrrcne','mrrccs','mrrchs','mrrccc','mrrclo','mrrcmi','mrrcpl','mrrcvs','mrrcvc','mrrchi','mrrcls','mrrcge','mrrclt','mrrcgt','mrrcle',
+ 'mrrc2eq','mrrc2ne','mrrc2cs','mrrc2hs','mrrc2cc','mrrc2lo','mrrc2mi','mrrc2pl','mrrc2vs','mrrc2vc','mrrc2hi','mrrc2ls','mrrc2ge','mrrc2lt','mrrc2gt','mrrc2le'
+ ),
+ /* Unconditional System Instructions */
+ 15 => array(
+ /* System: Unconditional Debug and State-Change Instructions */
+ 'bkpt',
+ 'dbg','dbgal',
+ 'setend',
+ 'svc','svcal',
+ 'sev.w','seval.w',
+ 'sev','seval',
+ 'wfe.w','wfeal.w',
+ 'wfe','wfeal',
+ 'wfi.w','wfial.w',
+ 'wfi','wfial',
+ /* System: Unconditional ThumbEE Instructions */
+ 'enterx',
+ 'leavex',
+ 'chka.n','chkaal.n',
+ 'chka','chkaal',
+ 'hb.n','hbal.n',
+ 'hb','hbal',
+ 'hbl.n','hblal.n',
+ 'hbl','hblal',
+ 'hblp.n','hblpal.n',
+ 'hblp','hblpal',
+ 'hbp.n','hbpal.n',
+ 'hbp','hbpal',
+ /* System: Unconditional Privileged Instructions */
+ 'cpsie.n',
+ 'cpsie.w',
+ 'cpsie',
+ 'cpsid.n',
+ 'cpsid.w',
+ 'cpsid',
+ 'smc','smcal',
+ 'rfeda','rfedaal',
+ 'rfedb','rfedbal',
+ 'rfeia','rfeiaal',
+ 'rfeib','rfeibal',
+ 'srsda','srsdaal',
+ 'srsdb','srsdbal',
+ 'srsia','srsiaal',
+ 'srsib','srsibal'
+ ),
+ /* Conditional System Instructions */
+ 16 => array(
+ /* System: Conditional Debug and State-Change Instructions */
+ 'dbgeq','dbgne','dbgcs','dbghs','dbgcc','dbglo','dbgmi','dbgpl','dbgvs','dbgvc','dbghi','dbgls','dbgge','dbglt','dbggt','dbgle',
+ 'svceq','svcne','svccs','svchs','svccc','svclo','svcmi','svcpl','svcvs','svcvc','svchi','svcls','svcge','svclt','svcgt','svcle',
+ 'seveq.w','sevne.w','sevcs.w','sevhs.w','sevcc.w','sevlo.w','sevmi.w','sevpl.w','sevvs.w','sevvc.w','sevhi.w','sevls.w','sevge.w','sevlt.w','sevgt.w','sevle.w',
+ 'seveq','sevne','sevcs','sevhs','sevcc','sevlo','sevmi','sevpl','sevvs','sevvc','sevhi','sevls','sevge','sevlt','sevgt','sevle',
+ 'wfeeq.w','wfene.w','wfecs.w','wfehs.w','wfecc.w','wfelo.w','wfemi.w','wfepl.w','wfevs.w','wfevc.w','wfehi.w','wfels.w','wfege.w','wfelt.w','wfegt.w','wfele.w',
+ 'wfeeq','wfene','wfecs','wfehs','wfecc','wfelo','wfemi','wfepl','wfevs','wfevc','wfehi','wfels','wfege','wfelt','wfegt','wfele',
+ 'wfieq.w','wfine.w','wfics.w','wfihs.w','wficc.w','wfilo.w','wfimi.w','wfipl.w','wfivs.w','wfivc.w','wfihi.w','wfils.w','wfige.w','wfilt.w','wfigt.w','wfile.w',
+ 'wfieq','wfine','wfics','wfihs','wficc','wfilo','wfimi','wfipl','wfivs','wfivc','wfihi','wfils','wfige','wfilt','wfigt','wfile',
+ /* System: Conditional ThumbEE Instructions */
+ 'chkaeq.n','chkane.n','chkacs.n','chkahs.n','chkacc.n','chkalo.n','chkami.n','chkapl.n','chkavs.n','chkavc.n','chkahi.n','chkals.n','chkage.n','chkalt.n','chkagt.n','chkale.n',
+ 'chkaeq','chkane','chkacs','chkahs','chkacc','chkalo','chkami','chkapl','chkavs','chkavc','chkahi','chkals','chkage','chkalt','chkagt','chkale',
+ 'hbeq.n','hbne.n','hbcs.n','hbhs.n','hbcc.n','hblo.n','hbmi.n','hbpl.n','hbvs.n','hbvc.n','hbhi.n','hbls.n','hbge.n','hblt.n','hbgt.n','hble.n',
+ 'hbeq','hbne','hbcs','hbhs','hbcc','hblo','hbmi','hbpl','hbvs','hbvc','hbhi','hbls','hbge','hblt','hbgt','hble',
+ 'hbleq.n','hblne.n','hblcs.n','hblhs.n','hblcc.n','hbllo.n','hblmi.n','hblpl.n','hblvs.n','hblvc.n','hblhi.n','hblls.n','hblge.n','hbllt.n','hblgt.n','hblle.n',
+ 'hbleq','hblne','hblcs','hblhs','hblcc','hbllo','hblmi','hblpl','hblvs','hblvc','hblhi','hblls','hblge','hbllt','hblgt','hblle',
+ 'hblpeq.n','hblpne.n','hblpcs.n','hblphs.n','hblpcc.n','hblplo.n','hblpmi.n','hblppl.n','hblpvs.n','hblpvc.n','hblphi.n','hblpls.n','hblpge.n','hblplt.n','hblpgt.n','hblple.n',
+ 'hblpeq','hblpne','hblpcs','hblphs','hblpcc','hblplo','hblpmi','hblppl','hblpvs','hblpvc','hblphi','hblpls','hblpge','hblplt','hblpgt','hblple',
+ 'hbpeq.n','hbpne.n','hbpcs.n','hbphs.n','hbpcc.n','hbplo.n','hbpmi.n','hbppl.n','hbpvs.n','hbpvc.n','hbphi.n','hbpls.n','hbpge.n','hbplt.n','hbpgt.n','hbple.n',
+ 'hbpeq','hbpne','hbpcs','hbphs','hbpcc','hbplo','hbpmi','hbppl','hbpvs','hbpvc','hbphi','hbpls','hbpge','hbplt','hbpgt','hbple',
+ /* System: Conditional Privileged Instructions */
+ 'smceq','smcne','smccs','smchs','smccc','smclo','smcmi','smcpl','smcvs','smcvc','smchi','smcls','smcge','smclt','smcgt','smcle',
+ 'rfedaeq','rfedane','rfedacs','rfedahs','rfedacc','rfedalo','rfedami','rfedapl','rfedavs','rfedavc','rfedahi','rfedals','rfedage','rfedalt','rfedagt','rfedale',
+ 'rfedbeq','rfedbne','rfedbcs','rfedbhs','rfedbcc','rfedblo','rfedbmi','rfedbpl','rfedbvs','rfedbvc','rfedbhi','rfedbls','rfedbge','rfedblt','rfedbgt','rfedble',
+ 'rfeiaeq','rfeiane','rfeiacs','rfeiahs','rfeiacc','rfeialo','rfeiami','rfeiapl','rfeiavs','rfeiavc','rfeiahi','rfeials','rfeiage','rfeialt','rfeiagt','rfeiale',
+ 'rfeibeq','rfeibne','rfeibcs','rfeibhs','rfeibcc','rfeiblo','rfeibmi','rfeibpl','rfeibvs','rfeibvc','rfeibhi','rfeibls','rfeibge','rfeiblt','rfeibgt','rfeible',
+ 'srsdaeq','srsdane','srsdacs','srsdahs','srsdacc','srsdalo','srsdami','srsdapl','srsdavs','srsdavc','srsdahi','srsdals','srsdage','srsdalt','srsdagt','srsdale',
+ 'srsdbeq','srsdbne','srsdbcs','srsdbhs','srsdbcc','srsdblo','srsdbmi','srsdbpl','srsdbvs','srsdbvc','srsdbhi','srsdbls','srsdbge','srsdblt','srsdbgt','srsdble',
+ 'srsiaeq','srsiane','srsiacs','srsiahs','srsiacc','srsialo','srsiami','srsiapl','srsiavs','srsiavc','srsiahi','srsials','srsiage','srsialt','srsiagt','srsiale',
+ 'srsibeq','srsibne','srsibcs','srsibhs','srsibcc','srsiblo','srsibmi','srsibpl','srsibvs','srsibvc','srsibhi','srsibls','srsibge','srsiblt','srsibgt','srsible'
+ ),
+ /* Unconditional WMMX/WMMX2 instructions */
+ 17 => array(
+ /* Unconditional WMMX/WMMX2 SIMD Instructions */
+ 'tandcb','tandcbal',
+ 'tandch','tandchal',
+ 'tandcw','tandcwal',
+ 'tbcstb','tbcstbal',
+ 'tbcsth','tbcsthal',
+ 'tbcstw','tbcstwal',
+ 'textrcb','textrcbal',
+ 'textrch','textrchal',
+ 'textrcw','textrcwal',
+ 'textrmsb','textrmsbal',
+ 'textrmsh','textrmshal',
+ 'textrmsw','textrmswal',
+ 'textrmub','textrmubal',
+ 'textrmuh','textrmuhal',
+ 'textrmuw','textrmuwal',
+ 'tinsrb','tinsrbal',
+ 'tinsrh','tinsrhal',
+ 'tinsrw','tinsrwal',
+ 'tmcr','tmcral',
+ 'tmcrr','tmcrral',
+ 'tmia','tmiaal',
+ 'tmiaph','tmiaphal',
+ 'tmiabb','tmiabbal',
+ 'tmiabt','tmiabtal',
+ 'tmiatb','tmiatbal',
+ 'tmiatt','tmiattal',
+ 'tmovmskb','tmovmskbal',
+ 'tmovmskh','tmovmskhal',
+ 'tmovmskw','tmovmskwal',
+ 'tmrc','tmrcal',
+ 'tmrrc','tmrrcal',
+ 'torcb','torcbal',
+ 'torch','torchal',
+ 'torcw','torcwal',
+ 'torvscb','torvscbal',
+ 'torvsch','torvschal',
+ 'torvscw','torvscwal',
+ 'wabsb','wabsbal',
+ 'wabsh','wabshal',
+ 'wabsw','wabswal',
+ 'wabsdiffb','wabsdiffbal',
+ 'wabsdiffh','wabsdiffhal',
+ 'wabsdiffw','wabsdiffwal',
+ 'waccb','waccbal',
+ 'wacch','wacchal',
+ 'waccw','waccwal',
+ 'waddb','waddbal',
+ 'waddh','waddhal',
+ 'waddw','waddwal',
+ 'waddbc','waddbcal',
+ 'waddhc','waddhcal',
+ 'waddwc','waddwcal',
+ 'waddbss','waddbssal',
+ 'waddhss','waddhssal',
+ 'waddwss','waddwssal',
+ 'waddbus','waddbusal',
+ 'waddhus','waddhusal',
+ 'waddwus','waddwusal',
+ 'waddsubhx','waddsubhxal',
+ 'waligni','walignial',
+ 'walignr0','walignr0al',
+ 'walignr1','walignr1al',
+ 'walignr2','walignr2al',
+ 'walignr3','walignr3al',
+ 'wand','wandal',
+ 'wandn','wandnal',
+ 'wavg2b','wavg2bal',
+ 'wavg2h','wavg2hal',
+ 'wavg2br','wavg2bral',
+ 'wavg2hr','wavg2hral',
+ 'wavg4','wavg4al',
+ 'wavg4r','wavg4ral',
+ 'wcmpeqb','wcmpeqbal',
+ 'wcmpeqh','wcmpeqhal',
+ 'wcmpeqw','wcmpeqwal',
+ 'wcmpgtsb','wcmpgtsbal',
+ 'wcmpgtsh','wcmpgtshal',
+ 'wcmpgtsw','wcmpgtswal',
+ 'wcmpgtub','wcmpgtubal',
+ 'wcmpgtuh','wcmpgtuhal',
+ 'wcmpgtuw','wcmpgtuwal',
+ 'wldrb','wldrbal',
+ 'wldrh','wldrhal',
+ 'wldrw','wldrwal',
+ 'wldrd','wldrdal',
+ 'wmacs','wmacsal',
+ 'wmacu','wmacual',
+ 'wmacsz','wmacszal',
+ 'wmacuz','wmacuzal',
+ 'wmadds','wmaddsal',
+ 'wmaddu','wmaddual',
+ 'wmaddsx','wmaddsxal',
+ 'wmaddux','wmadduxal',
+ 'wmaddsn','wmaddsnal',
+ 'wmaddun','wmaddunal',
+ 'wmaxsb','wmaxsbal',
+ 'wmaxsh','wmaxshal',
+ 'wmaxsw','wmaxswal',
+ 'wmaxub','wmaxubal',
+ 'wmaxuh','wmaxuhal',
+ 'wmaxuw','wmaxuwal',
+ 'wmerge','wmergeal',
+ 'wmiabb','wmiabbal',
+ 'wmiabt','wmiabtal',
+ 'wmiatb','wmiatbal',
+ 'wmiatt','wmiattal',
+ 'wmiabbn','wmiabbnal',
+ 'wmiabtn','wmiabtnal',
+ 'wmiatbn','wmiatbnal',
+ 'wmiattn','wmiattnal',
+ 'wmiawbb','wmiawbbal',
+ 'wmiawbt','wmiawbtal',
+ 'wmiawtb','wmiawtbal',
+ 'wmiawtt','wmiawttal',
+ 'wmiawbbn','wmiawbbnal',
+ 'wmiawbtn','wmiawbtnal',
+ 'wmiawtbn','wmiawtbnal',
+ 'wmiawttn','wmiawttnal',
+ 'wminsb','wminsbal',
+ 'wminsh','wminshal',
+ 'wminsw','wminswal',
+ 'wminub','wminubal',
+ 'wminuh','wminuhal',
+ 'wminuw','wminuwal',
+ 'wmov','wmoval',
+ 'wmulsm','wmulsmal',
+ 'wmulsl','wmulslal',
+ 'wmulum','wmulumal',
+ 'wmulul','wmululal',
+ 'wmulsmr','wmulsmral',
+ 'wmulslr','wmulslral',
+ 'wmulumr','wmulumral',
+ 'wmululr','wmululral',
+ 'wmulwum','wmulwumal',
+ 'wmulwsm','wmulwsmal',
+ 'wmulwl','wmulwlal',
+ 'wmulwumr','wmulwumral',
+ 'wmulwsmr','wmulwsmral',
+ 'wor','woral',
+ 'wpackhss','wpackhssal',
+ 'wpackwss','wpackwssal',
+ 'wpackdss','wpackdssal',
+ 'wpackhus','wpackhusal',
+ 'wpackwus','wpackwusal',
+ 'wpackdus','wpackdusal',
+ 'wqmiabb','wqmiabbal',
+ 'wqmiabt','wqmiabtal',
+ 'wqmiatb','wqmiatbal',
+ 'wqmiatt','wqmiattal',
+ 'wqmiabbn','wqmiabbnal',
+ 'wqmiabtn','wqmiabtnal',
+ 'wqmiatbn','wqmiatbnal',
+ 'wqmiattn','wqmiattnal',
+ 'wqmulm','wqmulmal',
+ 'wqmulmr','wqmulmral',
+ 'wqmulwm','wqmulwmal',
+ 'wqmulwmr','wqmulwmral',
+ 'wrorh','wrorhal',
+ 'wrorw','wrorwal',
+ 'wrord','wrordal',
+ 'wrorhg','wrorhgal',
+ 'wrorwg','wrorwgal',
+ 'wrordg','wrordgal',
+ 'wsadb','wsadbal',
+ 'wsadh','wsadhal',
+ 'wsadbz','wsadbzal',
+ 'wsadhz','wsadhzal',
+ 'wshufh','wshufhal',
+ 'wsllh','wsllhal',
+ 'wsllw','wsllwal',
+ 'wslld','wslldal',
+ 'wsllhg','wsllhgal',
+ 'wsllwg','wsllwgal',
+ 'wslldg','wslldgal',
+ 'wsrah','wsrahal',
+ 'wsraw','wsrawal',
+ 'wsrad','wsradal',
+ 'wsrahg','wsrahgal',
+ 'wsrawg','wsrawgal',
+ 'wsradg','wsradgal',
+ 'wsrlh','wsrlhal',
+ 'wsrlw','wsrlwal',
+ 'wsrld','wsrldal',
+ 'wsrlhg','wsrlhgal',
+ 'wsrlwg','wsrlwgal',
+ 'wsrldg','wsrldgal',
+ 'wstrb','wstrbal',
+ 'wstrh','wstrhal',
+ 'wstrw','wstrwal',
+ 'wstrd','wstrdal',
+ 'wsubb','wsubbal',
+ 'wsubh','wsubhal',
+ 'wsubw','wsubwal',
+ 'wsubbss','wsubbssal',
+ 'wsubhss','wsubhssal',
+ 'wsubwss','wsubwssal',
+ 'wsubbus','wsubbusal',
+ 'wsubhus','wsubhusal',
+ 'wsubwus','wsubwusal',
+ 'wsubaddhx','wsubaddhxal',
+ 'wunpckehsb','wunpckehsbal',
+ 'wunpckehsh','wunpckehshal',
+ 'wunpckehsw','wunpckehswal',
+ 'wunpckehub','wunpckehubal',
+ 'wunpckehuh','wunpckehuhal',
+ 'wunpckehuw','wunpckehuwal',
+ 'wunpckihb','wunpckihbal',
+ 'wunpckihh','wunpckihhal',
+ 'wunpckihw','wunpckihwal',
+ 'wunpckelsb','wunpckelsbal',
+ 'wunpckelsh','wunpckelshal',
+ 'wunpckelsw','wunpckelswal',
+ 'wunpckelub','wunpckelubal',
+ 'wunpckeluh','wunpckeluhal',
+ 'wunpckeluw','wunpckeluwal',
+ 'wunpckilb','wunpckilbal',
+ 'wunpckilh','wunpckilhal',
+ 'wunpckilw','wunpckilwal',
+ 'wxor','wxoral',
+ 'wzero','wzeroal'
+ ),
+ /* Conditional WMMX/WMMX2 SIMD Instructions */
+ 18 => array(
+ /* Conditional WMMX/WMMX2 SIMD Instructions */
+ 'tandcbeq','tandcbne','tandcbcs','tandcbhs','tandcbcc','tandcblo','tandcbmi','tandcbpl','tandcbvs','tandcbvc','tandcbhi','tandcbls','tandcbge','tandcblt','tandcbgt','tandcble',
+ 'tandcheq','tandchne','tandchcs','tandchhs','tandchcc','tandchlo','tandchmi','tandchpl','tandchvs','tandchvc','tandchhi','tandchls','tandchge','tandchlt','tandchgt','tandchle',
+ 'tandcweq','tandcwne','tandcwcs','tandcwhs','tandcwcc','tandcwlo','tandcwmi','tandcwpl','tandcwvs','tandcwvc','tandcwhi','tandcwls','tandcwge','tandcwlt','tandcwgt','tandcwle',
+ 'tbcstbeq','tbcstbne','tbcstbcs','tbcstbhs','tbcstbcc','tbcstblo','tbcstbmi','tbcstbpl','tbcstbvs','tbcstbvc','tbcstbhi','tbcstbls','tbcstbge','tbcstblt','tbcstbgt','tbcstble',
+ 'tbcstheq','tbcsthne','tbcsthcs','tbcsthhs','tbcsthcc','tbcsthlo','tbcsthmi','tbcsthpl','tbcsthvs','tbcsthvc','tbcsthhi','tbcsthls','tbcsthge','tbcsthlt','tbcsthgt','tbcsthle',
+ 'tbcstweq','tbcstwne','tbcstwcs','tbcstwhs','tbcstwcc','tbcstwlo','tbcstwmi','tbcstwpl','tbcstwvs','tbcstwvc','tbcstwhi','tbcstwls','tbcstwge','tbcstwlt','tbcstwgt','tbcstwle',
+ 'textrcbeq','textrcbne','textrcbcs','textrcbhs','textrcbcc','textrcblo','textrcbmi','textrcbpl','textrcbvs','textrcbvc','textrcbhi','textrcbls','textrcbge','textrcblt','textrcbgt','textrcble',
+ 'textrcheq','textrchne','textrchcs','textrchhs','textrchcc','textrchlo','textrchmi','textrchpl','textrchvs','textrchvc','textrchhi','textrchls','textrchge','textrchlt','textrchgt','textrchle',
+ 'textrcweq','textrcwne','textrcwcs','textrcwhs','textrcwcc','textrcwlo','textrcwmi','textrcwpl','textrcwvs','textrcwvc','textrcwhi','textrcwls','textrcwge','textrcwlt','textrcwgt','textrcwle',
+ 'textrmsbeq','textrmsbne','textrmsbcs','textrmsbhs','textrmsbcc','textrmsblo','textrmsbmi','textrmsbpl','textrmsbvs','textrmsbvc','textrmsbhi','textrmsbls','textrmsbge','textrmsblt','textrmsbgt','textrmsble',
+ 'textrmsheq','textrmshne','textrmshcs','textrmshhs','textrmshcc','textrmshlo','textrmshmi','textrmshpl','textrmshvs','textrmshvc','textrmshhi','textrmshls','textrmshge','textrmshlt','textrmshgt','textrmshle',
+ 'textrmsweq','textrmswne','textrmswcs','textrmswhs','textrmswcc','textrmswlo','textrmswmi','textrmswpl','textrmswvs','textrmswvc','textrmswhi','textrmswls','textrmswge','textrmswlt','textrmswgt','textrmswle',
+ 'textrmubeq','textrmubne','textrmubcs','textrmubhs','textrmubcc','textrmublo','textrmubmi','textrmubpl','textrmubvs','textrmubvc','textrmubhi','textrmubls','textrmubge','textrmublt','textrmubgt','textrmuble',
+ 'textrmuheq','textrmuhne','textrmuhcs','textrmuhhs','textrmuhcc','textrmuhlo','textrmuhmi','textrmuhpl','textrmuhvs','textrmuhvc','textrmuhhi','textrmuhls','textrmuhge','textrmuhlt','textrmuhgt','textrmuhle',
+ 'textrmuweq','textrmuwne','textrmuwcs','textrmuwhs','textrmuwcc','textrmuwlo','textrmuwmi','textrmuwpl','textrmuwvs','textrmuwvc','textrmuwhi','textrmuwls','textrmuwge','textrmuwlt','textrmuwgt','textrmuwle',
+ 'tinsrbeq','tinsrbne','tinsrbcs','tinsrbhs','tinsrbcc','tinsrblo','tinsrbmi','tinsrbpl','tinsrbvs','tinsrbvc','tinsrbhi','tinsrbls','tinsrbge','tinsrblt','tinsrbgt','tinsrble',
+ 'tinsrheq','tinsrhne','tinsrhcs','tinsrhhs','tinsrhcc','tinsrhlo','tinsrhmi','tinsrhpl','tinsrhvs','tinsrhvc','tinsrhhi','tinsrhls','tinsrhge','tinsrhlt','tinsrhgt','tinsrhle',
+ 'tinsrweq','tinsrwne','tinsrwcs','tinsrwhs','tinsrwcc','tinsrwlo','tinsrwmi','tinsrwpl','tinsrwvs','tinsrwvc','tinsrwhi','tinsrwls','tinsrwge','tinsrwlt','tinsrwgt','tinsrwle',
+ 'tmcreq','tmcrne','tmcrcs','tmcrhs','tmcrcc','tmcrlo','tmcrmi','tmcrpl','tmcrvs','tmcrvc','tmcrhi','tmcrls','tmcrge','tmcrlt','tmcrgt','tmcrle',
+ 'tmcrreq','tmcrrne','tmcrrcs','tmcrrhs','tmcrrcc','tmcrrlo','tmcrrmi','tmcrrpl','tmcrrvs','tmcrrvc','tmcrrhi','tmcrrls','tmcrrge','tmcrrlt','tmcrrgt','tmcrrle',
+ 'tmiaeq','tmiane','tmiacs','tmiahs','tmiacc','tmialo','tmiami','tmiapl','tmiavs','tmiavc','tmiahi','tmials','tmiage','tmialt','tmiagt','tmiale',
+ 'tmiapheq','tmiaphne','tmiaphcs','tmiaphhs','tmiaphcc','tmiaphlo','tmiaphmi','tmiaphpl','tmiaphvs','tmiaphvc','tmiaphhi','tmiaphls','tmiaphge','tmiaphlt','tmiaphgt','tmiaphle',
+ 'tmiabbeq','tmiabbne','tmiabbcs','tmiabbhs','tmiabbcc','tmiabblo','tmiabbmi','tmiabbpl','tmiabbvs','tmiabbvc','tmiabbhi','tmiabbls','tmiabbge','tmiabblt','tmiabbgt','tmiabble',
+ 'tmiabteq','tmiabtne','tmiabtcs','tmiabths','tmiabtcc','tmiabtlo','tmiabtmi','tmiabtpl','tmiabtvs','tmiabtvc','tmiabthi','tmiabtls','tmiabtge','tmiabtlt','tmiabtgt','tmiabtle',
+ 'tmiatbeq','tmiatbne','tmiatbcs','tmiatbhs','tmiatbcc','tmiatblo','tmiatbmi','tmiatbpl','tmiatbvs','tmiatbvc','tmiatbhi','tmiatbls','tmiatbge','tmiatblt','tmiatbgt','tmiatble',
+ 'tmiatteq','tmiattne','tmiattcs','tmiatths','tmiattcc','tmiattlo','tmiattmi','tmiattpl','tmiattvs','tmiattvc','tmiatthi','tmiattls','tmiattge','tmiattlt','tmiattgt','tmiattle',
+ 'tmovmskbeq','tmovmskbne','tmovmskbcs','tmovmskbhs','tmovmskbcc','tmovmskblo','tmovmskbmi','tmovmskbpl','tmovmskbvs','tmovmskbvc','tmovmskbhi','tmovmskbls','tmovmskbge','tmovmskblt','tmovmskbgt','tmovmskble',
+ 'tmovmskheq','tmovmskhne','tmovmskhcs','tmovmskhhs','tmovmskhcc','tmovmskhlo','tmovmskhmi','tmovmskhpl','tmovmskhvs','tmovmskhvc','tmovmskhhi','tmovmskhls','tmovmskhge','tmovmskhlt','tmovmskhgt','tmovmskhle',
+ 'tmovmskweq','tmovmskwne','tmovmskwcs','tmovmskwhs','tmovmskwcc','tmovmskwlo','tmovmskwmi','tmovmskwpl','tmovmskwvs','tmovmskwvc','tmovmskwhi','tmovmskwls','tmovmskwge','tmovmskwlt','tmovmskwgt','tmovmskwle',
+ 'tmrceq','tmrcne','tmrccs','tmrchs','tmrccc','tmrclo','tmrcmi','tmrcpl','tmrcvs','tmrcvc','tmrchi','tmrcls','tmrcge','tmrclt','tmrcgt','tmrcle',
+ 'tmrrceq','tmrrcne','tmrrccs','tmrrchs','tmrrccc','tmrrclo','tmrrcmi','tmrrcpl','tmrrcvs','tmrrcvc','tmrrchi','tmrrcls','tmrrcge','tmrrclt','tmrrcgt','tmrrcle',
+ 'torcbeq','torcbne','torcbcs','torcbhs','torcbcc','torcblo','torcbmi','torcbpl','torcbvs','torcbvc','torcbhi','torcbls','torcbge','torcblt','torcbgt','torcble',
+ 'torcheq','torchne','torchcs','torchhs','torchcc','torchlo','torchmi','torchpl','torchvs','torchvc','torchhi','torchls','torchge','torchlt','torchgt','torchle',
+ 'torcweq','torcwne','torcwcs','torcwhs','torcwcc','torcwlo','torcwmi','torcwpl','torcwvs','torcwvc','torcwhi','torcwls','torcwge','torcwlt','torcwgt','torcwle',
+ 'torvscbeq','torvscbne','torvscbcs','torvscbhs','torvscbcc','torvscblo','torvscbmi','torvscbpl','torvscbvs','torvscbvc','torvscbhi','torvscbls','torvscbge','torvscblt','torvscbgt','torvscble',
+ 'torvscheq','torvschne','torvschcs','torvschhs','torvschcc','torvschlo','torvschmi','torvschpl','torvschvs','torvschvc','torvschhi','torvschls','torvschge','torvschlt','torvschgt','torvschle',
+ 'torvscweq','torvscwne','torvscwcs','torvscwhs','torvscwcc','torvscwlo','torvscwmi','torvscwpl','torvscwvs','torvscwvc','torvscwhi','torvscwls','torvscwge','torvscwlt','torvscwgt','torvscwle',
+ 'wabsbeq','wabsbne','wabsbcs','wabsbhs','wabsbcc','wabsblo','wabsbmi','wabsbpl','wabsbvs','wabsbvc','wabsbhi','wabsbls','wabsbge','wabsblt','wabsbgt','wabsble',
+ 'wabsheq','wabshne','wabshcs','wabshhs','wabshcc','wabshlo','wabshmi','wabshpl','wabshvs','wabshvc','wabshhi','wabshls','wabshge','wabshlt','wabshgt','wabshle',
+ 'wabsweq','wabswne','wabswcs','wabswhs','wabswcc','wabswlo','wabswmi','wabswpl','wabswvs','wabswvc','wabswhi','wabswls','wabswge','wabswlt','wabswgt','wabswle',
+ 'wabsdiffbeq','wabsdiffbne','wabsdiffbcs','wabsdiffbhs','wabsdiffbcc','wabsdiffblo','wabsdiffbmi','wabsdiffbpl','wabsdiffbvs','wabsdiffbvc','wabsdiffbhi','wabsdiffbls','wabsdiffbge','wabsdiffblt','wabsdiffbgt','wabsdiffble',
+ 'wabsdiffheq','wabsdiffhne','wabsdiffhcs','wabsdiffhhs','wabsdiffhcc','wabsdiffhlo','wabsdiffhmi','wabsdiffhpl','wabsdiffhvs','wabsdiffhvc','wabsdiffhhi','wabsdiffhls','wabsdiffhge','wabsdiffhlt','wabsdiffhgt','wabsdiffhle',
+ 'wabsdiffweq','wabsdiffwne','wabsdiffwcs','wabsdiffwhs','wabsdiffwcc','wabsdiffwlo','wabsdiffwmi','wabsdiffwpl','wabsdiffwvs','wabsdiffwvc','wabsdiffwhi','wabsdiffwls','wabsdiffwge','wabsdiffwlt','wabsdiffwgt','wabsdiffwle',
+ 'waccbeq','waccbne','waccbcs','waccbhs','waccbcc','waccblo','waccbmi','waccbpl','waccbvs','waccbvc','waccbhi','waccbls','waccbge','waccblt','waccbgt','waccble',
+ 'waccheq','wacchne','wacchcs','wacchhs','wacchcc','wacchlo','wacchmi','wacchpl','wacchvs','wacchvc','wacchhi','wacchls','wacchge','wacchlt','wacchgt','wacchle',
+ 'waccweq','waccwne','waccwcs','waccwhs','waccwcc','waccwlo','waccwmi','waccwpl','waccwvs','waccwvc','waccwhi','waccwls','waccwge','waccwlt','waccwgt','waccwle',
+ 'waddbeq','waddbne','waddbcs','waddbhs','waddbcc','waddblo','waddbmi','waddbpl','waddbvs','waddbvc','waddbhi','waddbls','waddbge','waddblt','waddbgt','waddble',
+ 'waddheq','waddhne','waddhcs','waddhhs','waddhcc','waddhlo','waddhmi','waddhpl','waddhvs','waddhvc','waddhhi','waddhls','waddhge','waddhlt','waddhgt','waddhle',
+ 'waddweq','waddwne','waddwcs','waddwhs','waddwcc','waddwlo','waddwmi','waddwpl','waddwvs','waddwvc','waddwhi','waddwls','waddwge','waddwlt','waddwgt','waddwle',
+ 'waddbceq','waddbcne','waddbccs','waddbchs','waddbccc','waddbclo','waddbcmi','waddbcpl','waddbcvs','waddbcvc','waddbchi','waddbcls','waddbcge','waddbclt','waddbcgt','waddbcle',
+ 'waddhceq','waddhcne','waddhccs','waddhchs','waddhccc','waddhclo','waddhcmi','waddhcpl','waddhcvs','waddhcvc','waddhchi','waddhcls','waddhcge','waddhclt','waddhcgt','waddhcle',
+ 'waddwceq','waddwcne','waddwccs','waddwchs','waddwccc','waddwclo','waddwcmi','waddwcpl','waddwcvs','waddwcvc','waddwchi','waddwcls','waddwcge','waddwclt','waddwcgt','waddwcle',
+ 'waddbsseq','waddbssne','waddbsscs','waddbsshs','waddbsscc','waddbsslo','waddbssmi','waddbsspl','waddbssvs','waddbssvc','waddbsshi','waddbssls','waddbssge','waddbsslt','waddbssgt','waddbssle',
+ 'waddhsseq','waddhssne','waddhsscs','waddhsshs','waddhsscc','waddhsslo','waddhssmi','waddhsspl','waddhssvs','waddhssvc','waddhsshi','waddhssls','waddhssge','waddhsslt','waddhssgt','waddhssle',
+ 'waddwsseq','waddwssne','waddwsscs','waddwsshs','waddwsscc','waddwsslo','waddwssmi','waddwsspl','waddwssvs','waddwssvc','waddwsshi','waddwssls','waddwssge','waddwsslt','waddwssgt','waddwssle',
+ 'waddbuseq','waddbusne','waddbuscs','waddbushs','waddbuscc','waddbuslo','waddbusmi','waddbuspl','waddbusvs','waddbusvc','waddbushi','waddbusls','waddbusge','waddbuslt','waddbusgt','waddbusle',
+ 'waddhuseq','waddhusne','waddhuscs','waddhushs','waddhuscc','waddhuslo','waddhusmi','waddhuspl','waddhusvs','waddhusvc','waddhushi','waddhusls','waddhusge','waddhuslt','waddhusgt','waddhusle',
+ 'waddwuseq','waddwusne','waddwuscs','waddwushs','waddwuscc','waddwuslo','waddwusmi','waddwuspl','waddwusvs','waddwusvc','waddwushi','waddwusls','waddwusge','waddwuslt','waddwusgt','waddwusle',
+ 'waddsubhxeq','waddsubhxne','waddsubhxcs','waddsubhxhs','waddsubhxcc','waddsubhxlo','waddsubhxmi','waddsubhxpl','waddsubhxvs','waddsubhxvc','waddsubhxhi','waddsubhxls','waddsubhxge','waddsubhxlt','waddsubhxgt','waddsubhxle',
+ 'walignieq','walignine','walignics','walignihs','walignicc','walignilo','walignimi','walignipl','walignivs','walignivc','walignihi','walignils','walignige','walignilt','walignigt','walignile',
+ 'walignr0eq','walignr0ne','walignr0cs','walignr0hs','walignr0cc','walignr0lo','walignr0mi','walignr0pl','walignr0vs','walignr0vc','walignr0hi','walignr0ls','walignr0ge','walignr0lt','walignr0gt','walignr0le',
+ 'walignr1eq','walignr1ne','walignr1cs','walignr1hs','walignr1cc','walignr1lo','walignr1mi','walignr1pl','walignr1vs','walignr1vc','walignr1hi','walignr1ls','walignr1ge','walignr1lt','walignr1gt','walignr1le',
+ 'walignr2eq','walignr2ne','walignr2cs','walignr2hs','walignr2cc','walignr2lo','walignr2mi','walignr2pl','walignr2vs','walignr2vc','walignr2hi','walignr2ls','walignr2ge','walignr2lt','walignr2gt','walignr2le',
+ 'walignr3eq','walignr3ne','walignr3cs','walignr3hs','walignr3cc','walignr3lo','walignr3mi','walignr3pl','walignr3vs','walignr3vc','walignr3hi','walignr3ls','walignr3ge','walignr3lt','walignr3gt','walignr3le',
+ 'wandeq','wandne','wandcs','wandhs','wandcc','wandlo','wandmi','wandpl','wandvs','wandvc','wandhi','wandls','wandge','wandlt','wandgt','wandle',
+ 'wandneq','wandnne','wandncs','wandnhs','wandncc','wandnlo','wandnmi','wandnpl','wandnvs','wandnvc','wandnhi','wandnls','wandnge','wandnlt','wandngt','wandnle',
+ 'wavg2beq','wavg2bne','wavg2bcs','wavg2bhs','wavg2bcc','wavg2blo','wavg2bmi','wavg2bpl','wavg2bvs','wavg2bvc','wavg2bhi','wavg2bls','wavg2bge','wavg2blt','wavg2bgt','wavg2ble',
+ 'wavg2heq','wavg2hne','wavg2hcs','wavg2hhs','wavg2hcc','wavg2hlo','wavg2hmi','wavg2hpl','wavg2hvs','wavg2hvc','wavg2hhi','wavg2hls','wavg2hge','wavg2hlt','wavg2hgt','wavg2hle',
+ 'wavg2breq','wavg2brne','wavg2brcs','wavg2brhs','wavg2brcc','wavg2brlo','wavg2brmi','wavg2brpl','wavg2brvs','wavg2brvc','wavg2brhi','wavg2brls','wavg2brge','wavg2brlt','wavg2brgt','wavg2brle',
+ 'wavg2hreq','wavg2hrne','wavg2hrcs','wavg2hrhs','wavg2hrcc','wavg2hrlo','wavg2hrmi','wavg2hrpl','wavg2hrvs','wavg2hrvc','wavg2hrhi','wavg2hrls','wavg2hrge','wavg2hrlt','wavg2hrgt','wavg2hrle',
+ 'wavg4eq','wavg4ne','wavg4cs','wavg4hs','wavg4cc','wavg4lo','wavg4mi','wavg4pl','wavg4vs','wavg4vc','wavg4hi','wavg4ls','wavg4ge','wavg4lt','wavg4gt','wavg4le',
+ 'wavg4req','wavg4rne','wavg4rcs','wavg4rhs','wavg4rcc','wavg4rlo','wavg4rmi','wavg4rpl','wavg4rvs','wavg4rvc','wavg4rhi','wavg4rls','wavg4rge','wavg4rlt','wavg4rgt','wavg4rle',
+ 'wcmpeqbeq','wcmpeqbne','wcmpeqbcs','wcmpeqbhs','wcmpeqbcc','wcmpeqblo','wcmpeqbmi','wcmpeqbpl','wcmpeqbvs','wcmpeqbvc','wcmpeqbhi','wcmpeqbls','wcmpeqbge','wcmpeqblt','wcmpeqbgt','wcmpeqble',
+ 'wcmpeqheq','wcmpeqhne','wcmpeqhcs','wcmpeqhhs','wcmpeqhcc','wcmpeqhlo','wcmpeqhmi','wcmpeqhpl','wcmpeqhvs','wcmpeqhvc','wcmpeqhhi','wcmpeqhls','wcmpeqhge','wcmpeqhlt','wcmpeqhgt','wcmpeqhle',
+ 'wcmpeqweq','wcmpeqwne','wcmpeqwcs','wcmpeqwhs','wcmpeqwcc','wcmpeqwlo','wcmpeqwmi','wcmpeqwpl','wcmpeqwvs','wcmpeqwvc','wcmpeqwhi','wcmpeqwls','wcmpeqwge','wcmpeqwlt','wcmpeqwgt','wcmpeqwle',
+ 'wcmpgtsbeq','wcmpgtsbne','wcmpgtsbcs','wcmpgtsbhs','wcmpgtsbcc','wcmpgtsblo','wcmpgtsbmi','wcmpgtsbpl','wcmpgtsbvs','wcmpgtsbvc','wcmpgtsbhi','wcmpgtsbls','wcmpgtsbge','wcmpgtsblt','wcmpgtsbgt','wcmpgtsble',
+ 'wcmpgtsheq','wcmpgtshne','wcmpgtshcs','wcmpgtshhs','wcmpgtshcc','wcmpgtshlo','wcmpgtshmi','wcmpgtshpl','wcmpgtshvs','wcmpgtshvc','wcmpgtshhi','wcmpgtshls','wcmpgtshge','wcmpgtshlt','wcmpgtshgt','wcmpgtshle',
+ 'wcmpgtsweq','wcmpgtswne','wcmpgtswcs','wcmpgtswhs','wcmpgtswcc','wcmpgtswlo','wcmpgtswmi','wcmpgtswpl','wcmpgtswvs','wcmpgtswvc','wcmpgtswhi','wcmpgtswls','wcmpgtswge','wcmpgtswlt','wcmpgtswgt','wcmpgtswle',
+ 'wcmpgtubeq','wcmpgtubne','wcmpgtubcs','wcmpgtubhs','wcmpgtubcc','wcmpgtublo','wcmpgtubmi','wcmpgtubpl','wcmpgtubvs','wcmpgtubvc','wcmpgtubhi','wcmpgtubls','wcmpgtubge','wcmpgtublt','wcmpgtubgt','wcmpgtuble',
+ 'wcmpgtuheq','wcmpgtuhne','wcmpgtuhcs','wcmpgtuhhs','wcmpgtuhcc','wcmpgtuhlo','wcmpgtuhmi','wcmpgtuhpl','wcmpgtuhvs','wcmpgtuhvc','wcmpgtuhhi','wcmpgtuhls','wcmpgtuhge','wcmpgtuhlt','wcmpgtuhgt','wcmpgtuhle',
+ 'wcmpgtuweq','wcmpgtuwne','wcmpgtuwcs','wcmpgtuwhs','wcmpgtuwcc','wcmpgtuwlo','wcmpgtuwmi','wcmpgtuwpl','wcmpgtuwvs','wcmpgtuwvc','wcmpgtuwhi','wcmpgtuwls','wcmpgtuwge','wcmpgtuwlt','wcmpgtuwgt','wcmpgtuwle',
+ 'wldrbeq','wldrbne','wldrbcs','wldrbhs','wldrbcc','wldrblo','wldrbmi','wldrbpl','wldrbvs','wldrbvc','wldrbhi','wldrbls','wldrbge','wldrblt','wldrbgt','wldrble',
+ 'wldrheq','wldrhne','wldrhcs','wldrhhs','wldrhcc','wldrhlo','wldrhmi','wldrhpl','wldrhvs','wldrhvc','wldrhhi','wldrhls','wldrhge','wldrhlt','wldrhgt','wldrhle',
+ 'wldrweq','wldrwne','wldrwcs','wldrwhs','wldrwcc','wldrwlo','wldrwmi','wldrwpl','wldrwvs','wldrwvc','wldrwhi','wldrwls','wldrwge','wldrwlt','wldrwgt','wldrwle',
+ 'wldrdeq','wldrdne','wldrdcs','wldrdhs','wldrdcc','wldrdlo','wldrdmi','wldrdpl','wldrdvs','wldrdvc','wldrdhi','wldrdls','wldrdge','wldrdlt','wldrdgt','wldrdle',
+ 'wmacseq','wmacsne','wmacscs','wmacshs','wmacscc','wmacslo','wmacsmi','wmacspl','wmacsvs','wmacsvc','wmacshi','wmacsls','wmacsge','wmacslt','wmacsgt','wmacsle',
+ 'wmacueq','wmacune','wmacucs','wmacuhs','wmacucc','wmaculo','wmacumi','wmacupl','wmacuvs','wmacuvc','wmacuhi','wmaculs','wmacuge','wmacult','wmacugt','wmacule',
+ 'wmacszeq','wmacszne','wmacszcs','wmacszhs','wmacszcc','wmacszlo','wmacszmi','wmacszpl','wmacszvs','wmacszvc','wmacszhi','wmacszls','wmacszge','wmacszlt','wmacszgt','wmacszle',
+ 'wmacuzeq','wmacuzne','wmacuzcs','wmacuzhs','wmacuzcc','wmacuzlo','wmacuzmi','wmacuzpl','wmacuzvs','wmacuzvc','wmacuzhi','wmacuzls','wmacuzge','wmacuzlt','wmacuzgt','wmacuzle',
+ 'wmaddseq','wmaddsne','wmaddscs','wmaddshs','wmaddscc','wmaddslo','wmaddsmi','wmaddspl','wmaddsvs','wmaddsvc','wmaddshi','wmaddsls','wmaddsge','wmaddslt','wmaddsgt','wmaddsle',
+ 'wmaddueq','wmaddune','wmadducs','wmadduhs','wmadducc','wmaddulo','wmaddumi','wmaddupl','wmadduvs','wmadduvc','wmadduhi','wmadduls','wmadduge','wmaddult','wmaddugt','wmaddule',
+ 'wmaddsxeq','wmaddsxne','wmaddsxcs','wmaddsxhs','wmaddsxcc','wmaddsxlo','wmaddsxmi','wmaddsxpl','wmaddsxvs','wmaddsxvc','wmaddsxhi','wmaddsxls','wmaddsxge','wmaddsxlt','wmaddsxgt','wmaddsxle',
+ 'wmadduxeq','wmadduxne','wmadduxcs','wmadduxhs','wmadduxcc','wmadduxlo','wmadduxmi','wmadduxpl','wmadduxvs','wmadduxvc','wmadduxhi','wmadduxls','wmadduxge','wmadduxlt','wmadduxgt','wmadduxle',
+ 'wmaddsneq','wmaddsnne','wmaddsncs','wmaddsnhs','wmaddsncc','wmaddsnlo','wmaddsnmi','wmaddsnpl','wmaddsnvs','wmaddsnvc','wmaddsnhi','wmaddsnls','wmaddsnge','wmaddsnlt','wmaddsngt','wmaddsnle',
+ 'wmadduneq','wmaddunne','wmadduncs','wmaddunhs','wmadduncc','wmaddunlo','wmaddunmi','wmaddunpl','wmaddunvs','wmaddunvc','wmaddunhi','wmaddunls','wmaddunge','wmaddunlt','wmaddungt','wmaddunle',
+ 'wmaxsbeq','wmaxsbne','wmaxsbcs','wmaxsbhs','wmaxsbcc','wmaxsblo','wmaxsbmi','wmaxsbpl','wmaxsbvs','wmaxsbvc','wmaxsbhi','wmaxsbls','wmaxsbge','wmaxsblt','wmaxsbgt','wmaxsble',
+ 'wmaxsheq','wmaxshne','wmaxshcs','wmaxshhs','wmaxshcc','wmaxshlo','wmaxshmi','wmaxshpl','wmaxshvs','wmaxshvc','wmaxshhi','wmaxshls','wmaxshge','wmaxshlt','wmaxshgt','wmaxshle',
+ 'wmaxsweq','wmaxswne','wmaxswcs','wmaxswhs','wmaxswcc','wmaxswlo','wmaxswmi','wmaxswpl','wmaxswvs','wmaxswvc','wmaxswhi','wmaxswls','wmaxswge','wmaxswlt','wmaxswgt','wmaxswle',
+ 'wmaxubeq','wmaxubne','wmaxubcs','wmaxubhs','wmaxubcc','wmaxublo','wmaxubmi','wmaxubpl','wmaxubvs','wmaxubvc','wmaxubhi','wmaxubls','wmaxubge','wmaxublt','wmaxubgt','wmaxuble',
+ 'wmaxuheq','wmaxuhne','wmaxuhcs','wmaxuhhs','wmaxuhcc','wmaxuhlo','wmaxuhmi','wmaxuhpl','wmaxuhvs','wmaxuhvc','wmaxuhhi','wmaxuhls','wmaxuhge','wmaxuhlt','wmaxuhgt','wmaxuhle',
+ 'wmaxuweq','wmaxuwne','wmaxuwcs','wmaxuwhs','wmaxuwcc','wmaxuwlo','wmaxuwmi','wmaxuwpl','wmaxuwvs','wmaxuwvc','wmaxuwhi','wmaxuwls','wmaxuwge','wmaxuwlt','wmaxuwgt','wmaxuwle',
+ 'wmergeeq','wmergene','wmergecs','wmergehs','wmergecc','wmergelo','wmergemi','wmergepl','wmergevs','wmergevc','wmergehi','wmergels','wmergege','wmergelt','wmergegt','wmergele',
+ 'wmiabbeq','wmiabbne','wmiabbcs','wmiabbhs','wmiabbcc','wmiabblo','wmiabbmi','wmiabbpl','wmiabbvs','wmiabbvc','wmiabbhi','wmiabbls','wmiabbge','wmiabblt','wmiabbgt','wmiabble',
+ 'wmiabteq','wmiabtne','wmiabtcs','wmiabths','wmiabtcc','wmiabtlo','wmiabtmi','wmiabtpl','wmiabtvs','wmiabtvc','wmiabthi','wmiabtls','wmiabtge','wmiabtlt','wmiabtgt','wmiabtle',
+ 'wmiatbeq','wmiatbne','wmiatbcs','wmiatbhs','wmiatbcc','wmiatblo','wmiatbmi','wmiatbpl','wmiatbvs','wmiatbvc','wmiatbhi','wmiatbls','wmiatbge','wmiatblt','wmiatbgt','wmiatble',
+ 'wmiatteq','wmiattne','wmiattcs','wmiatths','wmiattcc','wmiattlo','wmiattmi','wmiattpl','wmiattvs','wmiattvc','wmiatthi','wmiattls','wmiattge','wmiattlt','wmiattgt','wmiattle',
+ 'wmiabbneq','wmiabbnne','wmiabbncs','wmiabbnhs','wmiabbncc','wmiabbnlo','wmiabbnmi','wmiabbnpl','wmiabbnvs','wmiabbnvc','wmiabbnhi','wmiabbnls','wmiabbnge','wmiabbnlt','wmiabbngt','wmiabbnle',
+ 'wmiabtneq','wmiabtnne','wmiabtncs','wmiabtnhs','wmiabtncc','wmiabtnlo','wmiabtnmi','wmiabtnpl','wmiabtnvs','wmiabtnvc','wmiabtnhi','wmiabtnls','wmiabtnge','wmiabtnlt','wmiabtngt','wmiabtnle',
+ 'wmiatbneq','wmiatbnne','wmiatbncs','wmiatbnhs','wmiatbncc','wmiatbnlo','wmiatbnmi','wmiatbnpl','wmiatbnvs','wmiatbnvc','wmiatbnhi','wmiatbnls','wmiatbnge','wmiatbnlt','wmiatbngt','wmiatbnle',
+ 'wmiattneq','wmiattnne','wmiattncs','wmiattnhs','wmiattncc','wmiattnlo','wmiattnmi','wmiattnpl','wmiattnvs','wmiattnvc','wmiattnhi','wmiattnls','wmiattnge','wmiattnlt','wmiattngt','wmiattnle',
+ 'wmiawbbeq','wmiawbbne','wmiawbbcs','wmiawbbhs','wmiawbbcc','wmiawbblo','wmiawbbmi','wmiawbbpl','wmiawbbvs','wmiawbbvc','wmiawbbhi','wmiawbbls','wmiawbbge','wmiawbblt','wmiawbbgt','wmiawbble',
+ 'wmiawbteq','wmiawbtne','wmiawbtcs','wmiawbths','wmiawbtcc','wmiawbtlo','wmiawbtmi','wmiawbtpl','wmiawbtvs','wmiawbtvc','wmiawbthi','wmiawbtls','wmiawbtge','wmiawbtlt','wmiawbtgt','wmiawbtle',
+ 'wmiawtbeq','wmiawtbne','wmiawtbcs','wmiawtbhs','wmiawtbcc','wmiawtblo','wmiawtbmi','wmiawtbpl','wmiawtbvs','wmiawtbvc','wmiawtbhi','wmiawtbls','wmiawtbge','wmiawtblt','wmiawtbgt','wmiawtble',
+ 'wmiawtteq','wmiawttne','wmiawttcs','wmiawtths','wmiawttcc','wmiawttlo','wmiawttmi','wmiawttpl','wmiawttvs','wmiawttvc','wmiawtthi','wmiawttls','wmiawttge','wmiawttlt','wmiawttgt','wmiawttle',
+ 'wmiawbbneq','wmiawbbnne','wmiawbbncs','wmiawbbnhs','wmiawbbncc','wmiawbbnlo','wmiawbbnmi','wmiawbbnpl','wmiawbbnvs','wmiawbbnvc','wmiawbbnhi','wmiawbbnls','wmiawbbnge','wmiawbbnlt','wmiawbbngt','wmiawbbnle',
+ 'wmiawbtneq','wmiawbtnne','wmiawbtncs','wmiawbtnhs','wmiawbtncc','wmiawbtnlo','wmiawbtnmi','wmiawbtnpl','wmiawbtnvs','wmiawbtnvc','wmiawbtnhi','wmiawbtnls','wmiawbtnge','wmiawbtnlt','wmiawbtngt','wmiawbtnle',
+ 'wmiawtbneq','wmiawtbnne','wmiawtbncs','wmiawtbnhs','wmiawtbncc','wmiawtbnlo','wmiawtbnmi','wmiawtbnpl','wmiawtbnvs','wmiawtbnvc','wmiawtbnhi','wmiawtbnls','wmiawtbnge','wmiawtbnlt','wmiawtbngt','wmiawtbnle',
+ 'wmiawttneq','wmiawttnne','wmiawttncs','wmiawttnhs','wmiawttncc','wmiawttnlo','wmiawttnmi','wmiawttnpl','wmiawttnvs','wmiawttnvc','wmiawttnhi','wmiawttnls','wmiawttnge','wmiawttnlt','wmiawttngt','wmiawttnle',
+ 'wminsbeq','wminsbne','wminsbcs','wminsbhs','wminsbcc','wminsblo','wminsbmi','wminsbpl','wminsbvs','wminsbvc','wminsbhi','wminsbls','wminsbge','wminsblt','wminsbgt','wminsble',
+ 'wminsheq','wminshne','wminshcs','wminshhs','wminshcc','wminshlo','wminshmi','wminshpl','wminshvs','wminshvc','wminshhi','wminshls','wminshge','wminshlt','wminshgt','wminshle',
+ 'wminsweq','wminswne','wminswcs','wminswhs','wminswcc','wminswlo','wminswmi','wminswpl','wminswvs','wminswvc','wminswhi','wminswls','wminswge','wminswlt','wminswgt','wminswle',
+ 'wminubeq','wminubne','wminubcs','wminubhs','wminubcc','wminublo','wminubmi','wminubpl','wminubvs','wminubvc','wminubhi','wminubls','wminubge','wminublt','wminubgt','wminuble',
+ 'wminuheq','wminuhne','wminuhcs','wminuhhs','wminuhcc','wminuhlo','wminuhmi','wminuhpl','wminuhvs','wminuhvc','wminuhhi','wminuhls','wminuhge','wminuhlt','wminuhgt','wminuhle',
+ 'wminuweq','wminuwne','wminuwcs','wminuwhs','wminuwcc','wminuwlo','wminuwmi','wminuwpl','wminuwvs','wminuwvc','wminuwhi','wminuwls','wminuwge','wminuwlt','wminuwgt','wminuwle',
+ 'wmoveq','wmovne','wmovcs','wmovhs','wmovcc','wmovlo','wmovmi','wmovpl','wmovvs','wmovvc','wmovhi','wmovls','wmovge','wmovlt','wmovgt','wmovle',
+ 'wmulsmeq','wmulsmne','wmulsmcs','wmulsmhs','wmulsmcc','wmulsmlo','wmulsmmi','wmulsmpl','wmulsmvs','wmulsmvc','wmulsmhi','wmulsmls','wmulsmge','wmulsmlt','wmulsmgt','wmulsmle',
+ 'wmulsleq','wmulslne','wmulslcs','wmulslhs','wmulslcc','wmulsllo','wmulslmi','wmulslpl','wmulslvs','wmulslvc','wmulslhi','wmulslls','wmulslge','wmulsllt','wmulslgt','wmulslle',
+ 'wmulumeq','wmulumne','wmulumcs','wmulumhs','wmulumcc','wmulumlo','wmulummi','wmulumpl','wmulumvs','wmulumvc','wmulumhi','wmulumls','wmulumge','wmulumlt','wmulumgt','wmulumle',
+ 'wmululeq','wmululne','wmululcs','wmululhs','wmululcc','wmulullo','wmululmi','wmululpl','wmululvs','wmululvc','wmululhi','wmululls','wmululge','wmulullt','wmululgt','wmululle',
+ 'wmulsmreq','wmulsmrne','wmulsmrcs','wmulsmrhs','wmulsmrcc','wmulsmrlo','wmulsmrmi','wmulsmrpl','wmulsmrvs','wmulsmrvc','wmulsmrhi','wmulsmrls','wmulsmrge','wmulsmrlt','wmulsmrgt','wmulsmrle',
+ 'wmulslreq','wmulslrne','wmulslrcs','wmulslrhs','wmulslrcc','wmulslrlo','wmulslrmi','wmulslrpl','wmulslrvs','wmulslrvc','wmulslrhi','wmulslrls','wmulslrge','wmulslrlt','wmulslrgt','wmulslrle',
+ 'wmulumreq','wmulumrne','wmulumrcs','wmulumrhs','wmulumrcc','wmulumrlo','wmulumrmi','wmulumrpl','wmulumrvs','wmulumrvc','wmulumrhi','wmulumrls','wmulumrge','wmulumrlt','wmulumrgt','wmulumrle',
+ 'wmululreq','wmululrne','wmululrcs','wmululrhs','wmululrcc','wmululrlo','wmululrmi','wmululrpl','wmululrvs','wmululrvc','wmululrhi','wmululrls','wmululrge','wmululrlt','wmululrgt','wmululrle',
+ 'wmulwumeq','wmulwumne','wmulwumcs','wmulwumhs','wmulwumcc','wmulwumlo','wmulwummi','wmulwumpl','wmulwumvs','wmulwumvc','wmulwumhi','wmulwumls','wmulwumge','wmulwumlt','wmulwumgt','wmulwumle',
+ 'wmulwsmeq','wmulwsmne','wmulwsmcs','wmulwsmhs','wmulwsmcc','wmulwsmlo','wmulwsmmi','wmulwsmpl','wmulwsmvs','wmulwsmvc','wmulwsmhi','wmulwsmls','wmulwsmge','wmulwsmlt','wmulwsmgt','wmulwsmle',
+ 'wmulwleq','wmulwlne','wmulwlcs','wmulwlhs','wmulwlcc','wmulwllo','wmulwlmi','wmulwlpl','wmulwlvs','wmulwlvc','wmulwlhi','wmulwlls','wmulwlge','wmulwllt','wmulwlgt','wmulwlle',
+ 'wmulwumreq','wmulwumrne','wmulwumrcs','wmulwumrhs','wmulwumrcc','wmulwumrlo','wmulwumrmi','wmulwumrpl','wmulwumrvs','wmulwumrvc','wmulwumrhi','wmulwumrls','wmulwumrge','wmulwumrlt','wmulwumrgt','wmulwumrle',
+ 'wmulwsmreq','wmulwsmrne','wmulwsmrcs','wmulwsmrhs','wmulwsmrcc','wmulwsmrlo','wmulwsmrmi','wmulwsmrpl','wmulwsmrvs','wmulwsmrvc','wmulwsmrhi','wmulwsmrls','wmulwsmrge','wmulwsmrlt','wmulwsmrgt','wmulwsmrle',
+ 'woreq','worne','worcs','worhs','worcc','worlo','wormi','worpl','worvs','worvc','worhi','worls','worge','worlt','worgt','worle',
+ 'wpackhsseq','wpackhssne','wpackhsscs','wpackhsshs','wpackhsscc','wpackhsslo','wpackhssmi','wpackhsspl','wpackhssvs','wpackhssvc','wpackhsshi','wpackhssls','wpackhssge','wpackhsslt','wpackhssgt','wpackhssle',
+ 'wpackwsseq','wpackwssne','wpackwsscs','wpackwsshs','wpackwsscc','wpackwsslo','wpackwssmi','wpackwsspl','wpackwssvs','wpackwssvc','wpackwsshi','wpackwssls','wpackwssge','wpackwsslt','wpackwssgt','wpackwssle',
+ 'wpackdsseq','wpackdssne','wpackdsscs','wpackdsshs','wpackdsscc','wpackdsslo','wpackdssmi','wpackdsspl','wpackdssvs','wpackdssvc','wpackdsshi','wpackdssls','wpackdssge','wpackdsslt','wpackdssgt','wpackdssle',
+ 'wpackhuseq','wpackhusne','wpackhuscs','wpackhushs','wpackhuscc','wpackhuslo','wpackhusmi','wpackhuspl','wpackhusvs','wpackhusvc','wpackhushi','wpackhusls','wpackhusge','wpackhuslt','wpackhusgt','wpackhusle',
+ 'wpackwuseq','wpackwusne','wpackwuscs','wpackwushs','wpackwuscc','wpackwuslo','wpackwusmi','wpackwuspl','wpackwusvs','wpackwusvc','wpackwushi','wpackwusls','wpackwusge','wpackwuslt','wpackwusgt','wpackwusle',
+ 'wpackduseq','wpackdusne','wpackduscs','wpackdushs','wpackduscc','wpackduslo','wpackdusmi','wpackduspl','wpackdusvs','wpackdusvc','wpackdushi','wpackdusls','wpackdusge','wpackduslt','wpackdusgt','wpackdusle',
+ 'wqmiabbeq','wqmiabbne','wqmiabbcs','wqmiabbhs','wqmiabbcc','wqmiabblo','wqmiabbmi','wqmiabbpl','wqmiabbvs','wqmiabbvc','wqmiabbhi','wqmiabbls','wqmiabbge','wqmiabblt','wqmiabbgt','wqmiabble',
+ 'wqmiabteq','wqmiabtne','wqmiabtcs','wqmiabths','wqmiabtcc','wqmiabtlo','wqmiabtmi','wqmiabtpl','wqmiabtvs','wqmiabtvc','wqmiabthi','wqmiabtls','wqmiabtge','wqmiabtlt','wqmiabtgt','wqmiabtle',
+ 'wqmiatbeq','wqmiatbne','wqmiatbcs','wqmiatbhs','wqmiatbcc','wqmiatblo','wqmiatbmi','wqmiatbpl','wqmiatbvs','wqmiatbvc','wqmiatbhi','wqmiatbls','wqmiatbge','wqmiatblt','wqmiatbgt','wqmiatble',
+ 'wqmiatteq','wqmiattne','wqmiattcs','wqmiatths','wqmiattcc','wqmiattlo','wqmiattmi','wqmiattpl','wqmiattvs','wqmiattvc','wqmiatthi','wqmiattls','wqmiattge','wqmiattlt','wqmiattgt','wqmiattle',
+ 'wqmiabbneq','wqmiabbnne','wqmiabbncs','wqmiabbnhs','wqmiabbncc','wqmiabbnlo','wqmiabbnmi','wqmiabbnpl','wqmiabbnvs','wqmiabbnvc','wqmiabbnhi','wqmiabbnls','wqmiabbnge','wqmiabbnlt','wqmiabbngt','wqmiabbnle',
+ 'wqmiabtneq','wqmiabtnne','wqmiabtncs','wqmiabtnhs','wqmiabtncc','wqmiabtnlo','wqmiabtnmi','wqmiabtnpl','wqmiabtnvs','wqmiabtnvc','wqmiabtnhi','wqmiabtnls','wqmiabtnge','wqmiabtnlt','wqmiabtngt','wqmiabtnle',
+ 'wqmiatbneq','wqmiatbnne','wqmiatbncs','wqmiatbnhs','wqmiatbncc','wqmiatbnlo','wqmiatbnmi','wqmiatbnpl','wqmiatbnvs','wqmiatbnvc','wqmiatbnhi','wqmiatbnls','wqmiatbnge','wqmiatbnlt','wqmiatbngt','wqmiatbnle',
+ 'wqmiattneq','wqmiattnne','wqmiattncs','wqmiattnhs','wqmiattncc','wqmiattnlo','wqmiattnmi','wqmiattnpl','wqmiattnvs','wqmiattnvc','wqmiattnhi','wqmiattnls','wqmiattnge','wqmiattnlt','wqmiattngt','wqmiattnle',
+ 'wqmulmeq','wqmulmne','wqmulmcs','wqmulmhs','wqmulmcc','wqmulmlo','wqmulmmi','wqmulmpl','wqmulmvs','wqmulmvc','wqmulmhi','wqmulmls','wqmulmge','wqmulmlt','wqmulmgt','wqmulmle',
+ 'wqmulmreq','wqmulmrne','wqmulmrcs','wqmulmrhs','wqmulmrcc','wqmulmrlo','wqmulmrmi','wqmulmrpl','wqmulmrvs','wqmulmrvc','wqmulmrhi','wqmulmrls','wqmulmrge','wqmulmrlt','wqmulmrgt','wqmulmrle',
+ 'wqmulwmeq','wqmulwmne','wqmulwmcs','wqmulwmhs','wqmulwmcc','wqmulwmlo','wqmulwmmi','wqmulwmpl','wqmulwmvs','wqmulwmvc','wqmulwmhi','wqmulwmls','wqmulwmge','wqmulwmlt','wqmulwmgt','wqmulwmle',
+ 'wqmulwmreq','wqmulwmrne','wqmulwmrcs','wqmulwmrhs','wqmulwmrcc','wqmulwmrlo','wqmulwmrmi','wqmulwmrpl','wqmulwmrvs','wqmulwmrvc','wqmulwmrhi','wqmulwmrls','wqmulwmrge','wqmulwmrlt','wqmulwmrgt','wqmulwmrle',
+ 'wrorheq','wrorhne','wrorhcs','wrorhhs','wrorhcc','wrorhlo','wrorhmi','wrorhpl','wrorhvs','wrorhvc','wrorhhi','wrorhls','wrorhge','wrorhlt','wrorhgt','wrorhle',
+ 'wrorweq','wrorwne','wrorwcs','wrorwhs','wrorwcc','wrorwlo','wrorwmi','wrorwpl','wrorwvs','wrorwvc','wrorwhi','wrorwls','wrorwge','wrorwlt','wrorwgt','wrorwle',
+ 'wrordeq','wrordne','wrordcs','wrordhs','wrordcc','wrordlo','wrordmi','wrordpl','wrordvs','wrordvc','wrordhi','wrordls','wrordge','wrordlt','wrordgt','wrordle',
+ 'wrorhgeq','wrorhgne','wrorhgcs','wrorhghs','wrorhgcc','wrorhglo','wrorhgmi','wrorhgpl','wrorhgvs','wrorhgvc','wrorhghi','wrorhgls','wrorhgge','wrorhglt','wrorhggt','wrorhgle',
+ 'wrorwgeq','wrorwgne','wrorwgcs','wrorwghs','wrorwgcc','wrorwglo','wrorwgmi','wrorwgpl','wrorwgvs','wrorwgvc','wrorwghi','wrorwgls','wrorwgge','wrorwglt','wrorwggt','wrorwgle',
+ 'wrordgeq','wrordgne','wrordgcs','wrordghs','wrordgcc','wrordglo','wrordgmi','wrordgpl','wrordgvs','wrordgvc','wrordghi','wrordgls','wrordgge','wrordglt','wrordggt','wrordgle',
+ 'wsadbeq','wsadbne','wsadbcs','wsadbhs','wsadbcc','wsadblo','wsadbmi','wsadbpl','wsadbvs','wsadbvc','wsadbhi','wsadbls','wsadbge','wsadblt','wsadbgt','wsadble',
+ 'wsadheq','wsadhne','wsadhcs','wsadhhs','wsadhcc','wsadhlo','wsadhmi','wsadhpl','wsadhvs','wsadhvc','wsadhhi','wsadhls','wsadhge','wsadhlt','wsadhgt','wsadhle',
+ 'wsadbzeq','wsadbzne','wsadbzcs','wsadbzhs','wsadbzcc','wsadbzlo','wsadbzmi','wsadbzpl','wsadbzvs','wsadbzvc','wsadbzhi','wsadbzls','wsadbzge','wsadbzlt','wsadbzgt','wsadbzle',
+ 'wsadhzeq','wsadhzne','wsadhzcs','wsadhzhs','wsadhzcc','wsadhzlo','wsadhzmi','wsadhzpl','wsadhzvs','wsadhzvc','wsadhzhi','wsadhzls','wsadhzge','wsadhzlt','wsadhzgt','wsadhzle',
+ 'wshufheq','wshufhne','wshufhcs','wshufhhs','wshufhcc','wshufhlo','wshufhmi','wshufhpl','wshufhvs','wshufhvc','wshufhhi','wshufhls','wshufhge','wshufhlt','wshufhgt','wshufhle',
+ 'wsllheq','wsllhne','wsllhcs','wsllhhs','wsllhcc','wsllhlo','wsllhmi','wsllhpl','wsllhvs','wsllhvc','wsllhhi','wsllhls','wsllhge','wsllhlt','wsllhgt','wsllhle',
+ 'wsllweq','wsllwne','wsllwcs','wsllwhs','wsllwcc','wsllwlo','wsllwmi','wsllwpl','wsllwvs','wsllwvc','wsllwhi','wsllwls','wsllwge','wsllwlt','wsllwgt','wsllwle',
+ 'wslldeq','wslldne','wslldcs','wslldhs','wslldcc','wslldlo','wslldmi','wslldpl','wslldvs','wslldvc','wslldhi','wslldls','wslldge','wslldlt','wslldgt','wslldle',
+ 'wsllhgeq','wsllhgne','wsllhgcs','wsllhghs','wsllhgcc','wsllhglo','wsllhgmi','wsllhgpl','wsllhgvs','wsllhgvc','wsllhghi','wsllhgls','wsllhgge','wsllhglt','wsllhggt','wsllhgle',
+ 'wsllwgeq','wsllwgne','wsllwgcs','wsllwghs','wsllwgcc','wsllwglo','wsllwgmi','wsllwgpl','wsllwgvs','wsllwgvc','wsllwghi','wsllwgls','wsllwgge','wsllwglt','wsllwggt','wsllwgle',
+ 'wslldgeq','wslldgne','wslldgcs','wslldghs','wslldgcc','wslldglo','wslldgmi','wslldgpl','wslldgvs','wslldgvc','wslldghi','wslldgls','wslldgge','wslldglt','wslldggt','wslldgle',
+ 'wsraheq','wsrahne','wsrahcs','wsrahhs','wsrahcc','wsrahlo','wsrahmi','wsrahpl','wsrahvs','wsrahvc','wsrahhi','wsrahls','wsrahge','wsrahlt','wsrahgt','wsrahle',
+ 'wsraweq','wsrawne','wsrawcs','wsrawhs','wsrawcc','wsrawlo','wsrawmi','wsrawpl','wsrawvs','wsrawvc','wsrawhi','wsrawls','wsrawge','wsrawlt','wsrawgt','wsrawle',
+ 'wsradeq','wsradne','wsradcs','wsradhs','wsradcc','wsradlo','wsradmi','wsradpl','wsradvs','wsradvc','wsradhi','wsradls','wsradge','wsradlt','wsradgt','wsradle',
+ 'wsrahgeq','wsrahgne','wsrahgcs','wsrahghs','wsrahgcc','wsrahglo','wsrahgmi','wsrahgpl','wsrahgvs','wsrahgvc','wsrahghi','wsrahgls','wsrahgge','wsrahglt','wsrahggt','wsrahgle',
+ 'wsrawgeq','wsrawgne','wsrawgcs','wsrawghs','wsrawgcc','wsrawglo','wsrawgmi','wsrawgpl','wsrawgvs','wsrawgvc','wsrawghi','wsrawgls','wsrawgge','wsrawglt','wsrawggt','wsrawgle',
+ 'wsradgeq','wsradgne','wsradgcs','wsradghs','wsradgcc','wsradglo','wsradgmi','wsradgpl','wsradgvs','wsradgvc','wsradghi','wsradgls','wsradgge','wsradglt','wsradggt','wsradgle',
+ 'wsrlheq','wsrlhne','wsrlhcs','wsrlhhs','wsrlhcc','wsrlhlo','wsrlhmi','wsrlhpl','wsrlhvs','wsrlhvc','wsrlhhi','wsrlhls','wsrlhge','wsrlhlt','wsrlhgt','wsrlhle',
+ 'wsrlweq','wsrlwne','wsrlwcs','wsrlwhs','wsrlwcc','wsrlwlo','wsrlwmi','wsrlwpl','wsrlwvs','wsrlwvc','wsrlwhi','wsrlwls','wsrlwge','wsrlwlt','wsrlwgt','wsrlwle',
+ 'wsrldeq','wsrldne','wsrldcs','wsrldhs','wsrldcc','wsrldlo','wsrldmi','wsrldpl','wsrldvs','wsrldvc','wsrldhi','wsrldls','wsrldge','wsrldlt','wsrldgt','wsrldle',
+ 'wsrlhgeq','wsrlhgne','wsrlhgcs','wsrlhghs','wsrlhgcc','wsrlhglo','wsrlhgmi','wsrlhgpl','wsrlhgvs','wsrlhgvc','wsrlhghi','wsrlhgls','wsrlhgge','wsrlhglt','wsrlhggt','wsrlhgle',
+ 'wsrlwgeq','wsrlwgne','wsrlwgcs','wsrlwghs','wsrlwgcc','wsrlwglo','wsrlwgmi','wsrlwgpl','wsrlwgvs','wsrlwgvc','wsrlwghi','wsrlwgls','wsrlwgge','wsrlwglt','wsrlwggt','wsrlwgle',
+ 'wsrldgeq','wsrldgne','wsrldgcs','wsrldghs','wsrldgcc','wsrldglo','wsrldgmi','wsrldgpl','wsrldgvs','wsrldgvc','wsrldghi','wsrldgls','wsrldgge','wsrldglt','wsrldggt','wsrldgle',
+ 'wstrbeq','wstrbne','wstrbcs','wstrbhs','wstrbcc','wstrblo','wstrbmi','wstrbpl','wstrbvs','wstrbvc','wstrbhi','wstrbls','wstrbge','wstrblt','wstrbgt','wstrble',
+ 'wstrheq','wstrhne','wstrhcs','wstrhhs','wstrhcc','wstrhlo','wstrhmi','wstrhpl','wstrhvs','wstrhvc','wstrhhi','wstrhls','wstrhge','wstrhlt','wstrhgt','wstrhle',
+ 'wstrweq','wstrwne','wstrwcs','wstrwhs','wstrwcc','wstrwlo','wstrwmi','wstrwpl','wstrwvs','wstrwvc','wstrwhi','wstrwls','wstrwge','wstrwlt','wstrwgt','wstrwle',
+ 'wstrdeq','wstrdne','wstrdcs','wstrdhs','wstrdcc','wstrdlo','wstrdmi','wstrdpl','wstrdvs','wstrdvc','wstrdhi','wstrdls','wstrdge','wstrdlt','wstrdgt','wstrdle',
+ 'wsubbeq','wsubbne','wsubbcs','wsubbhs','wsubbcc','wsubblo','wsubbmi','wsubbpl','wsubbvs','wsubbvc','wsubbhi','wsubbls','wsubbge','wsubblt','wsubbgt','wsubble',
+ 'wsubheq','wsubhne','wsubhcs','wsubhhs','wsubhcc','wsubhlo','wsubhmi','wsubhpl','wsubhvs','wsubhvc','wsubhhi','wsubhls','wsubhge','wsubhlt','wsubhgt','wsubhle',
+ 'wsubweq','wsubwne','wsubwcs','wsubwhs','wsubwcc','wsubwlo','wsubwmi','wsubwpl','wsubwvs','wsubwvc','wsubwhi','wsubwls','wsubwge','wsubwlt','wsubwgt','wsubwle',
+ 'wsubbsseq','wsubbssne','wsubbsscs','wsubbsshs','wsubbsscc','wsubbsslo','wsubbssmi','wsubbsspl','wsubbssvs','wsubbssvc','wsubbsshi','wsubbssls','wsubbssge','wsubbsslt','wsubbssgt','wsubbssle',
+ 'wsubhsseq','wsubhssne','wsubhsscs','wsubhsshs','wsubhsscc','wsubhsslo','wsubhssmi','wsubhsspl','wsubhssvs','wsubhssvc','wsubhsshi','wsubhssls','wsubhssge','wsubhsslt','wsubhssgt','wsubhssle',
+ 'wsubwsseq','wsubwssne','wsubwsscs','wsubwsshs','wsubwsscc','wsubwsslo','wsubwssmi','wsubwsspl','wsubwssvs','wsubwssvc','wsubwsshi','wsubwssls','wsubwssge','wsubwsslt','wsubwssgt','wsubwssle',
+ 'wsubbuseq','wsubbusne','wsubbuscs','wsubbushs','wsubbuscc','wsubbuslo','wsubbusmi','wsubbuspl','wsubbusvs','wsubbusvc','wsubbushi','wsubbusls','wsubbusge','wsubbuslt','wsubbusgt','wsubbusle',
+ 'wsubhuseq','wsubhusne','wsubhuscs','wsubhushs','wsubhuscc','wsubhuslo','wsubhusmi','wsubhuspl','wsubhusvs','wsubhusvc','wsubhushi','wsubhusls','wsubhusge','wsubhuslt','wsubhusgt','wsubhusle',
+ 'wsubwuseq','wsubwusne','wsubwuscs','wsubwushs','wsubwuscc','wsubwuslo','wsubwusmi','wsubwuspl','wsubwusvs','wsubwusvc','wsubwushi','wsubwusls','wsubwusge','wsubwuslt','wsubwusgt','wsubwusle',
+ 'wsubaddhxeq','wsubaddhxne','wsubaddhxcs','wsubaddhxhs','wsubaddhxcc','wsubaddhxlo','wsubaddhxmi','wsubaddhxpl','wsubaddhxvs','wsubaddhxvc','wsubaddhxhi','wsubaddhxls','wsubaddhxge','wsubaddhxlt','wsubaddhxgt','wsubaddhxle',
+ 'wunpckehsbeq','wunpckehsbne','wunpckehsbcs','wunpckehsbhs','wunpckehsbcc','wunpckehsblo','wunpckehsbmi','wunpckehsbpl','wunpckehsbvs','wunpckehsbvc','wunpckehsbhi','wunpckehsbls','wunpckehsbge','wunpckehsblt','wunpckehsbgt','wunpckehsble',
+ 'wunpckehsheq','wunpckehshne','wunpckehshcs','wunpckehshhs','wunpckehshcc','wunpckehshlo','wunpckehshmi','wunpckehshpl','wunpckehshvs','wunpckehshvc','wunpckehshhi','wunpckehshls','wunpckehshge','wunpckehshlt','wunpckehshgt','wunpckehshle',
+ 'wunpckehsweq','wunpckehswne','wunpckehswcs','wunpckehswhs','wunpckehswcc','wunpckehswlo','wunpckehswmi','wunpckehswpl','wunpckehswvs','wunpckehswvc','wunpckehswhi','wunpckehswls','wunpckehswge','wunpckehswlt','wunpckehswgt','wunpckehswle',
+ 'wunpckehubeq','wunpckehubne','wunpckehubcs','wunpckehubhs','wunpckehubcc','wunpckehublo','wunpckehubmi','wunpckehubpl','wunpckehubvs','wunpckehubvc','wunpckehubhi','wunpckehubls','wunpckehubge','wunpckehublt','wunpckehubgt','wunpckehuble',
+ 'wunpckehuheq','wunpckehuhne','wunpckehuhcs','wunpckehuhhs','wunpckehuhcc','wunpckehuhlo','wunpckehuhmi','wunpckehuhpl','wunpckehuhvs','wunpckehuhvc','wunpckehuhhi','wunpckehuhls','wunpckehuhge','wunpckehuhlt','wunpckehuhgt','wunpckehuhle',
+ 'wunpckehuweq','wunpckehuwne','wunpckehuwcs','wunpckehuwhs','wunpckehuwcc','wunpckehuwlo','wunpckehuwmi','wunpckehuwpl','wunpckehuwvs','wunpckehuwvc','wunpckehuwhi','wunpckehuwls','wunpckehuwge','wunpckehuwlt','wunpckehuwgt','wunpckehuwle',
+ 'wunpckihbeq','wunpckihbne','wunpckihbcs','wunpckihbhs','wunpckihbcc','wunpckihblo','wunpckihbmi','wunpckihbpl','wunpckihbvs','wunpckihbvc','wunpckihbhi','wunpckihbls','wunpckihbge','wunpckihblt','wunpckihbgt','wunpckihble',
+ 'wunpckihheq','wunpckihhne','wunpckihhcs','wunpckihhhs','wunpckihhcc','wunpckihhlo','wunpckihhmi','wunpckihhpl','wunpckihhvs','wunpckihhvc','wunpckihhhi','wunpckihhls','wunpckihhge','wunpckihhlt','wunpckihhgt','wunpckihhle',
+ 'wunpckihweq','wunpckihwne','wunpckihwcs','wunpckihwhs','wunpckihwcc','wunpckihwlo','wunpckihwmi','wunpckihwpl','wunpckihwvs','wunpckihwvc','wunpckihwhi','wunpckihwls','wunpckihwge','wunpckihwlt','wunpckihwgt','wunpckihwle',
+ 'wunpckelsbeq','wunpckelsbne','wunpckelsbcs','wunpckelsbhs','wunpckelsbcc','wunpckelsblo','wunpckelsbmi','wunpckelsbpl','wunpckelsbvs','wunpckelsbvc','wunpckelsbhi','wunpckelsbls','wunpckelsbge','wunpckelsblt','wunpckelsbgt','wunpckelsble',
+ 'wunpckelsheq','wunpckelshne','wunpckelshcs','wunpckelshhs','wunpckelshcc','wunpckelshlo','wunpckelshmi','wunpckelshpl','wunpckelshvs','wunpckelshvc','wunpckelshhi','wunpckelshls','wunpckelshge','wunpckelshlt','wunpckelshgt','wunpckelshle',
+ 'wunpckelsweq','wunpckelswne','wunpckelswcs','wunpckelswhs','wunpckelswcc','wunpckelswlo','wunpckelswmi','wunpckelswpl','wunpckelswvs','wunpckelswvc','wunpckelswhi','wunpckelswls','wunpckelswge','wunpckelswlt','wunpckelswgt','wunpckelswle',
+ 'wunpckelubeq','wunpckelubne','wunpckelubcs','wunpckelubhs','wunpckelubcc','wunpckelublo','wunpckelubmi','wunpckelubpl','wunpckelubvs','wunpckelubvc','wunpckelubhi','wunpckelubls','wunpckelubge','wunpckelublt','wunpckelubgt','wunpckeluble',
+ 'wunpckeluheq','wunpckeluhne','wunpckeluhcs','wunpckeluhhs','wunpckeluhcc','wunpckeluhlo','wunpckeluhmi','wunpckeluhpl','wunpckeluhvs','wunpckeluhvc','wunpckeluhhi','wunpckeluhls','wunpckeluhge','wunpckeluhlt','wunpckeluhgt','wunpckeluhle',
+ 'wunpckeluweq','wunpckeluwne','wunpckeluwcs','wunpckeluwhs','wunpckeluwcc','wunpckeluwlo','wunpckeluwmi','wunpckeluwpl','wunpckeluwvs','wunpckeluwvc','wunpckeluwhi','wunpckeluwls','wunpckeluwge','wunpckeluwlt','wunpckeluwgt','wunpckeluwle',
+ 'wunpckilbeq','wunpckilbne','wunpckilbcs','wunpckilbhs','wunpckilbcc','wunpckilblo','wunpckilbmi','wunpckilbpl','wunpckilbvs','wunpckilbvc','wunpckilbhi','wunpckilbls','wunpckilbge','wunpckilblt','wunpckilbgt','wunpckilble',
+ 'wunpckilheq','wunpckilhne','wunpckilhcs','wunpckilhhs','wunpckilhcc','wunpckilhlo','wunpckilhmi','wunpckilhpl','wunpckilhvs','wunpckilhvc','wunpckilhhi','wunpckilhls','wunpckilhge','wunpckilhlt','wunpckilhgt','wunpckilhle',
+ 'wunpckilweq','wunpckilwne','wunpckilwcs','wunpckilwhs','wunpckilwcc','wunpckilwlo','wunpckilwmi','wunpckilwpl','wunpckilwvs','wunpckilwvc','wunpckilwhi','wunpckilwls','wunpckilwge','wunpckilwlt','wunpckilwgt','wunpckilwle',
+ 'wxoreq','wxorne','wxorcs','wxorhs','wxorcc','wxorlo','wxormi','wxorpl','wxorvs','wxorvc','wxorhi','wxorls','wxorge','wxorlt','wxorgt','wxorle',
+ 'wzeroeq','wzerone','wzerocs','wzerohs','wzerocc','wzerolo','wzeromi','wzeropl','wzerovs','wzerovc','wzerohi','wzerols','wzeroge','wzerolt','wzerogt','wzerole'
+ ),
+ /* Unconditional VFPv3 & NEON SIMD Memory Access Instructions */
+ 19 => array(
+ /* Unconditional VFPv3 & NEON SIMD Memory Access: Loads */
+ 'vld.8','vldal.8',
+ 'vld.16','vldal.16',
+ 'vld.32','vldal.32',
+ 'vld.64','vldal.64',
+
+ 'vld1.8','vld1al.8',
+ 'vld1.16','vld1al.16',
+ 'vld1.32','vld1al.32',
+
+ 'vld2.8','vld2al.8',
+ 'vld2.16','vld2al.16',
+ 'vld2.32','vld2al.32',
+
+ 'vld3.8','vld3al.8',
+ 'vld3.16','vld3al.16',
+ 'vld3.32','vld3al.32',
+
+ 'vld4.8','vld4al.8',
+ 'vld4.16','vld4al.16',
+ 'vld4.32','vld4al.32',
+
+ 'vldm','vldmal',
+ 'vldm.32','vldmal.32',
+ 'vldm.64','vldmal.64',
+
+ 'vldmia','vldmiaal',
+ 'vldmia.32','vldmiaal.32',
+ 'vldmia.64','vldmiaal.64',
+
+ 'vldmdb','vldmdbal',
+ 'vldmdb.32','vldmdbal.32',
+ 'vldmdb.64','vldmdbal.64',
+
+ 'vldr','vldral',
+ 'vldr.32','vldral.32',
+ 'vldr.64','vldral.64',
+
+ 'vpop','vpopal',
+ 'vpop.32','vpopal.32',
+ 'vpop.64','vpopal.64',
+
+ /* Unconditional VFPv3 & NEON SIMD Memory Access: Stores */
+ 'vst1.8','vst1al.8',
+ 'vst1.16','vst1al.16',
+ 'vst1.32','vst1al.32',
+ 'vst1.64','vst1al.64',
+
+ 'vst2.8','vst2al.8',
+ 'vst2.16','vst2al.16',
+ 'vst2.32','vst2al.32',
+
+ 'vst3.8','vst3al.8',
+ 'vst3.16','vst3al.16',
+ 'vst3.32','vst3al.32',
+
+ 'vst4.8','vst4al.8',
+ 'vst4.16','vst4al.16',
+ 'vst4.32','vst4al.32',
+
+ 'vstm','vstmal',
+ 'vstm.32','vstmal.32',
+ 'vstm.64','vstmal.64',
+
+ 'vstmia','vstmiaal',
+ 'vstmia.32','vstmiaal.32',
+ 'vstmia.64','vstmiaal.64',
+
+ 'vstmdb','vstmdbal',
+ 'vstmdb.32','vstmdbal.32',
+ 'vstmdb.64','vstmdbal.64',
+
+ 'vstr','vstral',
+ 'vstr.32','vstral.32',
+ 'vstr.64','vstral.64',
+
+ 'vpush','vpushal',
+ 'vpush.32','vpushal.32',
+ 'vpush.64','vpushal.64'
+ ),
+ /* Unconditional NEON SIMD Logical Instructions */
+ 20 => array(
+ 'vand','vandal',
+ 'vand.i8','vandal.i8',
+ 'vand.i16','vandal.i16',
+ 'vand.i32','vandal.i32',
+ 'vand.i64','vandal.i64',
+ 'vand.s8','vandal.s8',
+ 'vand.s16','vandal.s16',
+ 'vand.s32','vandal.s32',
+ 'vand.s64','vandal.s64',
+ 'vand.u8','vandal.u8',
+ 'vand.u16','vandal.u16',
+ 'vand.u32','vandal.u32',
+ 'vand.u64','vandal.u64',
+ 'vand.f32','vandal.f32',
+ 'vand.f64','vandal.f64',
+
+ 'vbic','vbical',
+ 'vbic.i8','vbical.i8',
+ 'vbic.i16','vbical.i16',
+ 'vbic.i32','vbical.i32',
+ 'vbic.i64','vbical.i64',
+ 'vbic.s8','vbical.s8',
+ 'vbic.s16','vbical.s16',
+ 'vbic.s32','vbical.s32',
+ 'vbic.s64','vbical.s64',
+ 'vbic.u8','vbical.u8',
+ 'vbic.u16','vbical.u16',
+ 'vbic.u32','vbical.u32',
+ 'vbic.u64','vbical.u64',
+ 'vbic.f32','vbical.f32',
+ 'vbic.f64','vbical.f64',
+
+ 'vbif','vbifal',
+ 'vbif.i8','vbifal.i8',
+ 'vbif.i16','vbifal.i16',
+ 'vbif.i32','vbifal.i32',
+ 'vbif.i64','vbifal.i64',
+ 'vbif.s8','vbifal.s8',
+ 'vbif.s16','vbifal.s16',
+ 'vbif.s32','vbifal.s32',
+ 'vbif.s64','vbifal.s64',
+ 'vbif.u8','vbifal.u8',
+ 'vbif.u16','vbifal.u16',
+ 'vbif.u32','vbifal.u32',
+ 'vbif.u64','vbifal.u64',
+ 'vbif.f32','vbifal.f32',
+ 'vbif.f64','vbifal.f64',
+
+ 'vbit','vbital',
+ 'vbit.i8','vbital.i8',
+ 'vbit.i16','vbital.i16',
+ 'vbit.i32','vbital.i32',
+ 'vbit.i64','vbital.i64',
+ 'vbit.s8','vbital.s8',
+ 'vbit.s16','vbital.s16',
+ 'vbit.s32','vbital.s32',
+ 'vbit.s64','vbital.s64',
+ 'vbit.u8','vbital.u8',
+ 'vbit.u16','vbital.u16',
+ 'vbit.u32','vbital.u32',
+ 'vbit.u64','vbital.u64',
+ 'vbit.f32','vbital.f32',
+ 'vbit.f64','vbital.f64',
+
+ 'vbsl','vbslal',
+ 'vbsl.i8','vbslal.i8',
+ 'vbsl.i16','vbslal.i16',
+ 'vbsl.i32','vbslal.i32',
+ 'vbsl.i64','vbslal.i64',
+ 'vbsl.s8','vbslal.s8',
+ 'vbsl.s16','vbslal.s16',
+ 'vbsl.s32','vbslal.s32',
+ 'vbsl.s64','vbslal.s64',
+ 'vbsl.u8','vbslal.u8',
+ 'vbsl.u16','vbslal.u16',
+ 'vbsl.u32','vbslal.u32',
+ 'vbsl.u64','vbslal.u64',
+ 'vbsl.f32','vbslal.f32',
+ 'vbsl.f64','vbslal.f64',
+
+ 'veor','veoral',
+ 'veor.i8','veoral.i8',
+ 'veor.i16','veoral.i16',
+ 'veor.i32','veoral.i32',
+ 'veor.i64','veoral.i64',
+ 'veor.s8','veoral.s8',
+ 'veor.s16','veoral.s16',
+ 'veor.s32','veoral.s32',
+ 'veor.s64','veoral.s64',
+ 'veor.u8','veoral.u8',
+ 'veor.u16','veoral.u16',
+ 'veor.u32','veoral.u32',
+ 'veor.u64','veoral.u64',
+ 'veor.f32','veoral.f32',
+ 'veor.f64','veoral.f64',
+
+ 'vmov','vmoval',
+ 'vmov.8','vmoval.8',
+ 'vmov.16','vmoval.16',
+ 'vmov.32','vmoval.32',
+ 'vmov.i8','vmoval.i8',
+ 'vmov.i16','vmoval.i16',
+ 'vmov.i32','vmoval.i32',
+ 'vmov.i64','vmoval.i64',
+ 'vmov.f32','vmoval.f32',
+ 'vmov.f64','vmoval.f64',
+
+ 'vmvn','vmvnal',
+ 'vmvn.s8','vmvnal.s8',
+ 'vmvn.s16','vmvnal.s16',
+ 'vmvn.s32','vmvnal.s32',
+ 'vmvn.s64','vmvnal.s64',
+ 'vmvn.u8','vmvnal.u8',
+ 'vmvn.u16','vmvnal.u16',
+ 'vmvn.u32','vmvnal.u32',
+ 'vmvn.u64','vmvnal.u64',
+ 'vmvn.i8','vmvnal.i8',
+ 'vmvn.i16','vmvnal.i16',
+ 'vmvn.i32','vmvnal.i32',
+ 'vmvn.i64','vmvnal.i64',
+ 'vmvn.f32','vmvnal.f32',
+ 'vmvn.f64','vmvnal.f64',
+
+ 'vorn','vornal',
+ 'vorn.s8','vornal.s8',
+ 'vorn.s16','vornal.s16',
+ 'vorn.s32','vornal.s32',
+ 'vorn.s64','vornal.s64',
+ 'vorn.u8','vornal.u8',
+ 'vorn.u16','vornal.u16',
+ 'vorn.u32','vornal.u32',
+ 'vorn.u64','vornal.u64',
+ 'vorn.i8','vornal.i8',
+ 'vorn.i16','vornal.i16',
+ 'vorn.i32','vornal.i32',
+ 'vorn.i64','vornal.i64',
+ 'vorn.f32','vornal.f32',
+ 'vorn.f64','vornal.f64',
+
+ 'vorr','vorral',
+ 'vorr.s8','vorral.s8',
+ 'vorr.s16','vorral.s16',
+ 'vorr.s32','vorral.s32',
+ 'vorr.s64','vorral.s64',
+ 'vorr.u8','vorral.u8',
+ 'vorr.u16','vorral.u16',
+ 'vorr.u32','vorral.u32',
+ 'vorr.u64','vorral.u64',
+ 'vorr.i8','vorral.i8',
+ 'vorr.i16','vorral.i16',
+ 'vorr.i32','vorral.i32',
+ 'vorr.i64','vorral.i64',
+ 'vorr.f32','vorral.f32',
+ 'vorr.f64','vorral.f64',
+
+ 'vswp','vswpal',
+ 'vswp.s8','vswpal.s8',
+ 'vswp.s16','vswpal.s16',
+ 'vswp.s32','vswpal.s32',
+ 'vswp.s64','vswpal.s64',
+ 'vswp.u8','vswpal.u8',
+ 'vswp.u16','vswpal.u16',
+ 'vswp.u32','vswpal.u32',
+ 'vswp.u64','vswpal.u64',
+ 'vswp.i8','vswpal.i8',
+ 'vswp.i16','vswpal.i16',
+ 'vswp.i32','vswpal.i32',
+ 'vswp.i64','vswpal.i64',
+ 'vswp.f32','vswpal.f32',
+ 'vswp.f64','vswpal.f64'
+ ),
+ /* Unconditional NEON SIMD ARM Registers Interop Instructions */
+ 21 => array(
+ 'vmrs','vmrsal',
+ 'vmsr','vmsral'
+ ),
+ /* Unconditional NEON SIMD Bit/Byte-Level Instructions */
+ 22 => array(
+ 'vcnt.8','vcntal.8',
+ 'vdup.8','vdupal.8',
+
+ 'vdup.16','vdupal.16',
+ 'vdup.32','vdupal.32',
+
+ 'vext.8','vextal.8',
+ 'vext.16','vextal.16',
+
+ 'vext.32','vextal.32',
+ 'vext.64','vextal.64',
+
+ 'vrev16.8','vrev16al.8',
+ 'vrev32.8','vrev32al.8',
+ 'vrev32.16','vrev32al.16',
+ 'vrev64.8','vrev64al.8',
+ 'vrev64.16','vrev64al.16',
+ 'vrev64.32','vrev64al.32',
+
+ 'vsli.8','vslial.8',
+ 'vsli.16','vslial.16',
+ 'vsli.32','vslial.32',
+ 'vsli.64','vslial.64',
+
+ 'vsri.8','vsrial.8',
+ 'vsri.16','vsrial.16',
+ 'vsri.32','vsrial.32',
+ 'vsri.64','vsrial.64',
+
+ 'vtbl.8','vtblal.8',
+
+ 'vtbx','vtbxal',
+
+ 'vtrn.8','vtrnal.8',
+ 'vtrn.16','vtrnal.16',
+ 'vtrn.32','vtrnal.32',
+
+ 'vtst.8','vtstal.8',
+ 'vtst.16','vtstal.16',
+ 'vtst.32','vtstal.32',
+
+ 'vuzp.8','vuzpal.8',
+ 'vuzp.16','vuzpal.16',
+ 'vuzp.32','vuzpal.32',
+
+ 'vzip.8','vzipal.8',
+ 'vzip.16','vzipal.16',
+ 'vzip.32','vzipal.32',
+
+ 'vmull.p8','vmullal.p8'
+ ),
+ /* Unconditional NEON SIMD Universal Integer Instructions */
+ 23 => array(
+ 'vadd.i8','vaddal.i8',
+ 'vadd.i16','vaddal.i16',
+ 'vadd.i32','vaddal.i32',
+ 'vadd.i64','vaddal.i64',
+
+ 'vsub.i8','vsubal.i8',
+ 'vsub.i16','vsubal.i16',
+ 'vsub.i32','vsubal.i32',
+ 'vsub.i64','vsubal.i64',
+
+ 'vaddhn.i16','vaddhnal.i16',
+ 'vaddhn.i32','vaddhnal.i32',
+ 'vaddhn.i64','vaddhnal.i64',
+
+ 'vsubhn.i16','vsubhnal.i16',
+ 'vsubhn.i32','vsubhnal.i32',
+ 'vsubhn.i64','vsubhnal.i64',
+
+ 'vraddhn.i16','vraddhnal.i16',
+ 'vraddhn.i32','vraddhnal.i32',
+ 'vraddhn.i64','vraddhnal.i64',
+
+ 'vrsubhn.i16','vrsubhnal.i16',
+ 'vrsubhn.i32','vrsubhnal.i32',
+ 'vrsubhn.i64','vrsubhnal.i64',
+
+ 'vpadd.i8','vpaddal.i8',
+ 'vpadd.i16','vpaddal.i16',
+ 'vpadd.i32','vpaddal.i32',
+
+ 'vceq.i8','vceqal.i8',
+ 'vceq.i16','vceqal.i16',
+ 'vceq.i32','vceqal.i32',
+
+ 'vclz.i8','vclzal.i8',
+ 'vclz.i16','vclzal.i16',
+ 'vclz.i32','vclzal.i32',
+
+ 'vmovn.i16','vmovnal.i16',
+ 'vmovn.i32','vmovnal.i32',
+ 'vmovn.i64','vmovnal.i64',
+
+ 'vmla.s8','vmlaal.s8',
+ 'vmla.s16','vmlaal.s16',
+ 'vmla.s32','vmlaal.s32',
+ 'vmla.u8','vmlaal.u8',
+ 'vmla.u16','vmlaal.u16',
+ 'vmla.u32','vmlaal.u32',
+ 'vmla.i8','vmlaal.i8',
+ 'vmla.i16','vmlaal.i16',
+ 'vmla.i32','vmlaal.i32',
+
+ 'vmls.s8','vmlsal.s8',
+ 'vmls.s16','vmlsal.s16',
+ 'vmls.s32','vmlsal.s32',
+ 'vmls.u8','vmlsal.u8',
+ 'vmls.u16','vmlsal.u16',
+ 'vmls.u32','vmlsal.u32',
+ 'vmls.i8','vmlsal.i8',
+ 'vmls.i16','vmlsal.i16',
+ 'vmls.i32','vmlsal.i32',
+
+ 'vmul.s8','vmulal.s8',
+ 'vmul.s16','vmulal.s16',
+ 'vmul.s32','vmulal.s32',
+ 'vmul.u8','vmulal.u8',
+ 'vmul.u16','vmulal.u16',
+ 'vmul.u32','vmulal.u32',
+ 'vmul.i8','vmulal.i8',
+ 'vmul.i16','vmulal.i16',
+ 'vmul.i32','vmulal.i32',
+ 'vmul.p8','vmulal.p8',
+
+ 'vrshrn.i16','vrshrnal.i16',
+ 'vrshrn.i32','vrshrnal.i32',
+ 'vrshrn.i64','vrshrnal.i64',
+
+ 'vshrn.i16','vshrnal.i16',
+ 'vshrn.i32','vshrnal.i32',
+ 'vshrn.i64','vshrnal.i64',
+
+ 'vshl.i8','vshlal.i8',
+ 'vshl.i16','vshlal.i16',
+ 'vshl.i32','vshlal.i32',
+ 'vshl.i64','vshlal.i64',
+
+ 'vshll.i8','vshllal.i8',
+ 'vshll.i16','vshllal.i16',
+ 'vshll.i32','vshllal.i32'
+ ),
+ /* Unconditional NEON SIMD Signed Integer Instructions */
+ 24 => array(
+ 'vaba.s8','vabaal.s8',
+ 'vaba.s16','vabaal.s16',
+ 'vaba.s32','vabaal.s32',
+
+ 'vabal.s8','vabalal.s8',
+ 'vabal.s16','vabalal.s16',
+ 'vabal.s32','vabalal.s32',
+
+ 'vabd.s8','vabdal.s8',
+ 'vabd.s16','vabdal.s16',
+ 'vabd.s32','vabdal.s32',
+
+ 'vabs.s8','vabsal.s8',
+ 'vabs.s16','vabsal.s16',
+ 'vabs.s32','vabsal.s32',
+
+ 'vaddl.s8','vaddlal.s8',
+ 'vaddl.s16','vaddlal.s16',
+ 'vaddl.s32','vaddlal.s32',
+
+ 'vcge.s8','vcgeal.s8',
+ 'vcge.s16','vcgeal.s16',
+ 'vcge.s32','vcgeal.s32',
+
+ 'vcle.s8','vcleal.s8',
+ 'vcle.s16','vcleal.s16',
+ 'vcle.s32','vcleal.s32',
+
+ 'vcgt.s8','vcgtal.s8',
+ 'vcgt.s16','vcgtal.s16',
+ 'vcgt.s32','vcgtal.s32',
+
+ 'vclt.s8','vcltal.s8',
+ 'vclt.s16','vcltal.s16',
+ 'vclt.s32','vcltal.s32',
+
+ 'vcls.s8','vclsal.s8',
+ 'vcls.s16','vclsal.s16',
+ 'vcls.s32','vclsal.s32',
+
+ 'vaddw.s8','vaddwal.s8',
+ 'vaddw.s16','vaddwal.s16',
+ 'vaddw.s32','vaddwal.s32',
+
+ 'vhadd.s8','vhaddal.s8',
+ 'vhadd.s16','vhaddal.s16',
+ 'vhadd.s32','vhaddal.s32',
+
+ 'vhsub.s8','vhsubal.s8',
+ 'vhsub.s16','vhsubal.s16',
+ 'vhsub.s32','vhsubal.s32',
+
+ 'vmax.s8','vmaxal.s8',
+ 'vmax.s16','vmaxal.s16',
+ 'vmax.s32','vmaxal.s32',
+
+ 'vmin.s8','vminal.s8',
+ 'vmin.s16','vminal.s16',
+ 'vmin.s32','vminal.s32',
+
+ 'vmlal.s8','vmlalal.s8',
+ 'vmlal.s16','vmlalal.s16',
+ 'vmlal.s32','vmlalal.s32',
+
+ 'vmlsl.s8','vmlslal.s8',
+ 'vmlsl.s16','vmlslal.s16',
+ 'vmlsl.s32','vmlslal.s32',
+
+ 'vneg.s8','vnegal.s8',
+ 'vneg.s16','vnegal.s16',
+ 'vneg.s32','vnegal.s32',
+
+ 'vpadal.s8','vpadalal.s8',
+ 'vpadal.s16','vpadalal.s16',
+ 'vpadal.s32','vpadalal.s32',
+
+ 'vmovl.s8','vmovlal.s8',
+ 'vmovl.s16','vmovlal.s16',
+ 'vmovl.s32','vmovlal.s32',
+
+ 'vmull.s8','vmullal.s8',
+ 'vmull.s16','vmullal.s16',
+ 'vmull.s32','vmullal.s32',
+
+ 'vpaddl.s8','vpaddlal.s8',
+ 'vpaddl.s16','vpaddlal.s16',
+ 'vpaddl.s32','vpaddlal.s32',
+
+ 'vpmax.s8','vpmaxal.s8',
+ 'vpmax.s16','vpmaxal.s16',
+ 'vpmax.s32','vpmaxal.s32',
+
+ 'vpmin.s8','vpminal.s8',
+ 'vpmin.s16','vpminal.s16',
+ 'vpmin.s32','vpminal.s32',
+
+ 'vqabs.s8','vqabsal.s8',
+ 'vqabs.s16','vqabsal.s16',
+ 'vqabs.s32','vqabsal.s32',
+
+ 'vqadd.s8','vqaddal.s8',
+ 'vqadd.s16','vqaddal.s16',
+ 'vqadd.s32','vqaddal.s32',
+ 'vqadd.s64','vqaddal.s64',
+
+ 'vqdmlal.s16','vqdmlalal.s16',
+ 'vqdmlal.s32','vqdmlalal.s32',
+
+ 'vqdmlsl.s16','vqdmlslal.s16',
+ 'vqdmlsl.s32','vqdmlslal.s32',
+
+ 'vqdmulh.s16','vqdmulhal.s16',
+ 'vqdmulh.s32','vqdmulhal.s32',
+
+ 'vqdmull.s16','vqdmullal.s16',
+ 'vqdmull.s32','vqdmullal.s32',
+
+ 'vqmovn.s16','vqmovnal.s16',
+ 'vqmovn.s32','vqmovnal.s32',
+ 'vqmovn.s64','vqmovnal.s64',
+
+ 'vqmovun.s16','vqmovunal.s16',
+ 'vqmovun.s32','vqmovunal.s32',
+ 'vqmovun.s64','vqmovunal.s64',
+
+ 'vqneg.s8','vqnegal.s8',
+ 'vqneg.s16','vqnegal.s16',
+ 'vqneg.s32','vqnegal.s32',
+
+ 'vqrdmulh.s16','vqrdmulhal.s16',
+ 'vqrdmulh.s32','vqrdmulhal.s32',
+
+ 'vqrshl.s8','vqrshlal.s8',
+ 'vqrshl.s16','vqrshlal.s16',
+ 'vqrshl.s32','vqrshlal.s32',
+ 'vqrshl.s64','vqrshlal.s64',
+
+ 'vqrshrn.s16','vqrshrnal.s16',
+ 'vqrshrn.s32','vqrshrnal.s32',
+ 'vqrshrn.s64','vqrshrnal.s64',
+
+ 'vqrshrun.s16','vqrshrunal.s16',
+ 'vqrshrun.s32','vqrshrunal.s32',
+ 'vqrshrun.s64','vqrshrunal.s64',
+
+ 'vqshl.s8','vqshlal.s8',
+ 'vqshl.s16','vqshlal.s16',
+ 'vqshl.s32','vqshlal.s32',
+ 'vqshl.s64','vqshlal.s64',
+
+ 'vqshlu.s8','vqshlual.s8',
+ 'vqshlu.s16','vqshlual.s16',
+ 'vqshlu.s32','vqshlual.s32',
+ 'vqshlu.s64','vqshlual.s64',
+
+ 'vqshrn.s16','vqshrnal.s16',
+ 'vqshrn.s32','vqshrnal.s32',
+ 'vqshrn.s64','vqshrnal.s64',
+
+ 'vqshrun.s16','vqshrunal.s16',
+ 'vqshrun.s32','vqshrunal.s32',
+ 'vqshrun.s64','vqshrunal.s64',
+
+ 'vqsub.s8','vqsubal.s8',
+ 'vqsub.s16','vqsubal.s16',
+ 'vqsub.s32','vqsubal.s32',
+ 'vqsub.s64','vqsubal.s64',
+
+ 'vrhadd.s8','vrhaddal.s8',
+ 'vrhadd.s16','vrhaddal.s16',
+ 'vrhadd.s32','vrhaddal.s32',
+
+ 'vrshl.s8','vrshlal.s8',
+ 'vrshl.s16','vrshlal.s16',
+ 'vrshl.s32','vrshlal.s32',
+ 'vrshl.s64','vrshlal.s64',
+
+ 'vrshr.s8','vrshral.s8',
+ 'vrshr.s16','vrshral.s16',
+ 'vrshr.s32','vrshral.s32',
+ 'vrshr.s64','vrshral.s64',
+
+ 'vrsra.s8','vrsraal.s8',
+ 'vrsra.s16','vrsraal.s16',
+ 'vrsra.s32','vrsraal.s32',
+ 'vrsra.s64','vrsraal.s64',
+
+ 'vshl.s8','vshlal.s8',
+ 'vshl.s16','vshlal.s16',
+ 'vshl.s32','vshlal.s32',
+ 'vshl.s64','vshlal.s64',
+
+ 'vshll.s8','vshllal.s8',
+ 'vshll.s16','vshllal.s16',
+ 'vshll.s32','vshllal.s32',
+
+ 'vshr.s8','vshral.s8',
+ 'vshr.s16','vshral.s16',
+ 'vshr.s32','vshral.s32',
+ 'vshr.s64','vshral.s64',
+
+ 'vsra.s8','vsraal.s8',
+ 'vsra.s16','vsraal.s16',
+ 'vsra.s32','vsraal.s32',
+ 'vsra.s64','vsraal.s64',
+
+ 'vsubl.s8','vsublal.s8',
+ 'vsubl.s16','vsublal.s16',
+ 'vsubl.s32','vsublal.s32',
+
+ 'vsubh.s8','vsubhal.s8',
+ 'vsubh.s16','vsubhal.s16',
+ 'vsubh.s32','vsubhal.s32'
+ ),
+ /* Unconditional NEON SIMD Unsigned Integer Instructions */
+ 25 => array(
+ 'vaba.u8','vabaal.u8',
+ 'vaba.u16','vabaal.u16',
+ 'vaba.u32','vabaal.u32',
+
+ 'vabal.u8','vabalal.u8',
+ 'vabal.u16','vabalal.u16',
+ 'vabal.u32','vabalal.u32',
+
+ 'vabd.u8','vabdal.u8',
+ 'vabd.u16','vabdal.u16',
+ 'vabd.u32','vabdal.u32',
+
+ 'vaddl.u8','vaddlal.u8',
+ 'vaddl.u16','vaddlal.u16',
+ 'vaddl.u32','vaddlal.u32',
+
+ 'vsubl.u8','vsublal.u8',
+ 'vsubl.u16','vsublal.u16',
+ 'vsubl.u32','vsublal.u32',
+
+ 'vaddw.u8','vaddwal.u8',
+ 'vaddw.u16','vaddwal.u16',
+ 'vaddw.u32','vaddwal.u32',
+
+ 'vsubh.u8','vsubhal.u8',
+ 'vsubh.u16','vsubhal.u16',
+ 'vsubh.u32','vsubhal.u32',
+
+ 'vhadd.u8','vhaddal.u8',
+ 'vhadd.u16','vhaddal.u16',
+ 'vhadd.u32','vhaddal.u32',
+
+ 'vhsub.u8','vhsubal.u8',
+ 'vhsub.u16','vhsubal.u16',
+ 'vhsub.u32','vhsubal.u32',
+
+ 'vpadal.u8','vpadalal.u8',
+ 'vpadal.u16','vpadalal.u16',
+ 'vpadal.u32','vpadalal.u32',
+
+ 'vpaddl.u8','vpaddlal.u8',
+ 'vpaddl.u16','vpaddlal.u16',
+ 'vpaddl.u32','vpaddlal.u32',
+
+ 'vcge.u8','vcgeal.u8',
+ 'vcge.u16','vcgeal.u16',
+ 'vcge.u32','vcgeal.u32',
+
+ 'vcle.u8','vcleal.u8',
+ 'vcle.u16','vcleal.u16',
+ 'vcle.u32','vcleal.u32',
+
+ 'vcgt.u8','vcgtal.u8',
+ 'vcgt.u16','vcgtal.u16',
+ 'vcgt.u32','vcgtal.u32',
+
+ 'vclt.u8','vcltal.u8',
+ 'vclt.u16','vcltal.u16',
+ 'vclt.u32','vcltal.u32',
+
+ 'vmax.u8','vmaxal.u8',
+ 'vmax.u16','vmaxal.u16',
+ 'vmax.u32','vmaxal.u32',
+
+ 'vmin.u8','vminal.u8',
+ 'vmin.u16','vminal.u16',
+ 'vmin.u32','vminal.u32',
+
+ 'vmlal.u8','vmlalal.u8',
+ 'vmlal.u16','vmlalal.u16',
+ 'vmlal.u32','vmlalal.u32',
+
+ 'vmlsl.u8','vmlslal.u8',
+ 'vmlsl.u16','vmlslal.u16',
+ 'vmlsl.u32','vmlslal.u32',
+
+ 'vmull.u8','vmullal.u8',
+ 'vmull.u16','vmullal.u16',
+ 'vmull.u32','vmullal.u32',
+
+ 'vmovl.u8','vmovlal.u8',
+ 'vmovl.u16','vmovlal.u16',
+ 'vmovl.u32','vmovlal.u32',
+
+ 'vshl.u8','vshlal.u8',
+ 'vshl.u16','vshlal.u16',
+ 'vshl.u32','vshlal.u32',
+ 'vshl.u64','vshlal.u64',
+
+ 'vshll.u8','vshllal.u8',
+ 'vshll.u16','vshllal.u16',
+ 'vshll.u32','vshllal.u32',
+
+ 'vshr.u8','vshral.u8',
+ 'vshr.u16','vshral.u16',
+ 'vshr.u32','vshral.u32',
+ 'vshr.u64','vshral.u64',
+
+ 'vsra.u8','vsraal.u8',
+ 'vsra.u16','vsraal.u16',
+ 'vsra.u32','vsraal.u32',
+ 'vsra.u64','vsraal.u64',
+
+ 'vpmax.u8','vpmaxal.u8',
+ 'vpmax.u16','vpmaxal.u16',
+ 'vpmax.u32','vpmaxal.u32',
+
+ 'vpmin.u8','vpminal.u8',
+ 'vpmin.u16','vpminal.u16',
+ 'vpmin.u32','vpminal.u32',
+
+ 'vqadd.u8','vqaddal.u8',
+ 'vqadd.u16','vqaddal.u16',
+ 'vqadd.u32','vqaddal.u32',
+ 'vqadd.u64','vqaddal.u64',
+
+ 'vqsub.u8','vqsubal.u8',
+ 'vqsub.u16','vqsubal.u16',
+ 'vqsub.u32','vqsubal.u32',
+ 'vqsub.u64','vqsubal.u64',
+
+ 'vqmovn.u16','vqmovnal.u16',
+ 'vqmovn.u32','vqmovnal.u32',
+ 'vqmovn.u64','vqmovnal.u64',
+
+ 'vqshl.u8','vqshlal.u8',
+ 'vqshl.u16','vqshlal.u16',
+ 'vqshl.u32','vqshlal.u32',
+ 'vqshl.u64','vqshlal.u64',
+
+ 'vqshrn.u16','vqshrnal.u16',
+ 'vqshrn.u32','vqshrnal.u32',
+ 'vqshrn.u64','vqshrnal.u64',
+
+ 'vqrshl.u8','vqrshlal.u8',
+ 'vqrshl.u16','vqrshlal.u16',
+ 'vqrshl.u32','vqrshlal.u32',
+ 'vqrshl.u64','vqrshlal.u64',
+
+ 'vqrshrn.u16','vqrshrnal.u16',
+ 'vqrshrn.u32','vqrshrnal.u32',
+ 'vqrshrn.u64','vqrshrnal.u64',
+
+ 'vrhadd.u8','vrhaddal.u8',
+ 'vrhadd.u16','vrhaddal.u16',
+ 'vrhadd.u32','vrhaddal.u32',
+
+ 'vrshl.u8','vrshlal.u8',
+ 'vrshl.u16','vrshlal.u16',
+ 'vrshl.u32','vrshlal.u32',
+ 'vrshl.u64','vrshlal.u64',
+
+ 'vrshr.u8','vrshral.u8',
+ 'vrshr.u16','vrshral.u16',
+ 'vrshr.u32','vrshral.u32',
+ 'vrshr.u64','vrshral.u64',
+
+ 'vrsra.u8','vrsraal.u8',
+ 'vrsra.u16','vrsraal.u16',
+ 'vrsra.u32','vrsraal.u32',
+ 'vrsra.u64','vrsraal.u64'
+ ),
+ /* Unconditional VFPv3 & NEON SIMD Floating-Point Instructions */
+ 26 => array(
+ 'vabd.f32','vabdal.f32',
+
+ 'vabs.f32','vabsal.f32',
+ 'vabs.f64','vabsal.f64',
+
+ 'vacge.f32','vacgeal.f32',
+ 'vacgt.f32','vacgtal.f32',
+ 'vacle.f32','vacleal.f32',
+ 'vaclt.f32','vacltal.f32',
+
+ 'vadd.f32','vaddal.f32',
+ 'vadd.f64','vaddal.f64',
+
+ 'vceq.f32','vceqal.f32',
+ 'vcge.f32','vcgeal.f32',
+ 'vcle.f32','vcleal.f32',
+ 'vcgt.f32','vcgtal.f32',
+ 'vclt.f32','vcltal.f32',
+
+ 'vcmp.f32','vcmpal.f32',
+ 'vcmp.f64','vcmpal.f64',
+
+ 'vcmpe.f32','vcmpeal.f32',
+ 'vcmpe.f64','vcmpeal.f64',
+
+ 'vcvt.s16.f32','vcvtal.s16.f32',
+ 'vcvt.s16.f64','vcvtal.s16.f64',
+ 'vcvt.s32.f32','vcvtal.s32.f32',
+ 'vcvt.s32.f64','vcvtal.s32.f64',
+ 'vcvt.u16.f32','vcvtal.u16.f32',
+ 'vcvt.u16.f64','vcvtal.u16.f64',
+ 'vcvt.u32.f32','vcvtal.u32.f32',
+ 'vcvt.u32.f64','vcvtal.u32.f64',
+ 'vcvt.f16.f32','vcvtal.f16.f32',
+ 'vcvt.f32.s32','vcvtal.f32.s32',
+ 'vcvt.f32.u32','vcvtal.f32.u32',
+ 'vcvt.f32.f16','vcvtal.f32.f16',
+ 'vcvt.f32.f64','vcvtal.f32.f64',
+ 'vcvt.f64.s32','vcvtal.f64.s32',
+ 'vcvt.f64.u32','vcvtal.f64.u32',
+ 'vcvt.f64.f32','vcvtal.f64.f32',
+
+ 'vcvtr.s32.f32','vcvtral.s32.f32',
+ 'vcvtr.s32.f64','vcvtral.s32.f64',
+ 'vcvtr.u32.f32','vcvtral.u32.f32',
+ 'vcvtr.u32.f64','vcvtral.u32.f64',
+
+ 'vcvtb.f16.f32','vcvtbal.f16.f32',
+ 'vcvtb.f32.f16','vcvtbal.f32.f16',
+
+ 'vcvtt.f16.f32','vcvttal.f16.f32',
+ 'vcvtt.f32.f16','vcvttal.f32.f16',
+
+ 'vdiv.f32','vdival.f32',
+ 'vdiv.f64','vdival.f64',
+
+ 'vmax.f32','vmaxal.f32',
+ 'vmin.f32','vminal.f32',
+
+ 'vmla.f32','vmlaal.f32',
+ 'vmla.f64','vmlaal.f64',
+
+ 'vmls.f32','vmlsal.f32',
+ 'vmls.f64','vmlsal.f64',
+
+ 'vmul.f32','vmulal.f32',
+ 'vmul.f64','vmulal.f64',
+
+ 'vneg.f32','vnegal.f32',
+ 'vneg.f64','vnegal.f64',
+
+ 'vnmla.f32','vnmlaal.f32',
+ 'vnmla.f64','vnmlaal.f64',
+
+ 'vnmls.f32','vnmlsal.f32',
+ 'vnmls.f64','vnmlsal.f64',
+
+ 'vnmul.f64','vnmulal.f64',
+ 'vnmul.f32','vnmulal.f32',
+
+ 'vpadd.f32','vpaddal.f32',
+
+ 'vpmax.f32','vpmaxal.f32',
+ 'vpmin.f32','vpminal.f32',
+
+ 'vrecpe.u32','vrecpeal.u32',
+ 'vrecpe.f32','vrecpeal.f32',
+ 'vrecps.f32','vrecpsal.f32',
+
+ 'vrsqrte.u32','vrsqrteal.u32',
+ 'vrsqrte.f32','vrsqrteal.f32',
+ 'vrsqrts.f32','vrsqrtsal.f32',
+
+ 'vsqrt.f32','vsqrtal.f32',
+ 'vsqrt.f64','vsqrtal.f64',
+
+ 'vsub.f32','vsubal.f32',
+ 'vsub.f64','vsubal.f64'
+ ),
+ /* Conditional VFPv3 & NEON SIMD Memory Access Instructions */
+ 27 => array(
+ /* Conditional VFPv3 & NEON SIMD Memory Access: Loads */
+ 'vldeq.8','vldne.8','vldcs.8','vldhs.8','vldcc.8','vldlo.8','vldmi.8','vldpl.8','vldvs.8','vldvc.8','vldhi.8','vldls.8','vldge.8','vldlt.8','vldgt.8','vldle.8',
+ 'vldeq.16','vldne.16','vldcs.16','vldhs.16','vldcc.16','vldlo.16','vldmi.16','vldpl.16','vldvs.16','vldvc.16','vldhi.16','vldls.16','vldge.16','vldlt.16','vldgt.16','vldle.16',
+ 'vldeq.32','vldne.32','vldcs.32','vldhs.32','vldcc.32','vldlo.32','vldmi.32','vldpl.32','vldvs.32','vldvc.32','vldhi.32','vldls.32','vldge.32','vldlt.32','vldgt.32','vldle.32',
+ 'vldeq.64','vldne.64','vldcs.64','vldhs.64','vldcc.64','vldlo.64','vldmi.64','vldpl.64','vldvs.64','vldvc.64','vldhi.64','vldls.64','vldge.64','vldlt.64','vldgt.64','vldle.64',
+
+ 'vld1eq.8','vld1ne.8','vld1cs.8','vld1hs.8','vld1cc.8','vld1lo.8','vld1mi.8','vld1pl.8','vld1vs.8','vld1vc.8','vld1hi.8','vld1ls.8','vld1ge.8','vld1lt.8','vld1gt.8','vld1le.8',
+ 'vld1eq.16','vld1ne.16','vld1cs.16','vld1hs.16','vld1cc.16','vld1lo.16','vld1mi.16','vld1pl.16','vld1vs.16','vld1vc.16','vld1hi.16','vld1ls.16','vld1ge.16','vld1lt.16','vld1gt.16','vld1le.16',
+ 'vld1eq.32','vld1ne.32','vld1cs.32','vld1hs.32','vld1cc.32','vld1lo.32','vld1mi.32','vld1pl.32','vld1vs.32','vld1vc.32','vld1hi.32','vld1ls.32','vld1ge.32','vld1lt.32','vld1gt.32','vld1le.32',
+
+ 'vld2eq.8','vld2ne.8','vld2cs.8','vld2hs.8','vld2cc.8','vld2lo.8','vld2mi.8','vld2pl.8','vld2vs.8','vld2vc.8','vld2hi.8','vld2ls.8','vld2ge.8','vld2lt.8','vld2gt.8','vld2le.8',
+ 'vld2eq.16','vld2ne.16','vld2cs.16','vld2hs.16','vld2cc.16','vld2lo.16','vld2mi.16','vld2pl.16','vld2vs.16','vld2vc.16','vld2hi.16','vld2ls.16','vld2ge.16','vld2lt.16','vld2gt.16','vld2le.16',
+ 'vld2eq.32','vld2ne.32','vld2cs.32','vld2hs.32','vld2cc.32','vld2lo.32','vld2mi.32','vld2pl.32','vld2vs.32','vld2vc.32','vld2hi.32','vld2ls.32','vld2ge.32','vld2lt.32','vld2gt.32','vld2le.32',
+
+ 'vld3eq.8','vld3ne.8','vld3cs.8','vld3hs.8','vld3cc.8','vld3lo.8','vld3mi.8','vld3pl.8','vld3vs.8','vld3vc.8','vld3hi.8','vld3ls.8','vld3ge.8','vld3lt.8','vld3gt.8','vld3le.8',
+ 'vld3eq.16','vld3ne.16','vld3cs.16','vld3hs.16','vld3cc.16','vld3lo.16','vld3mi.16','vld3pl.16','vld3vs.16','vld3vc.16','vld3hi.16','vld3ls.16','vld3ge.16','vld3lt.16','vld3gt.16','vld3le.16',
+ 'vld3eq.32','vld3ne.32','vld3cs.32','vld3hs.32','vld3cc.32','vld3lo.32','vld3mi.32','vld3pl.32','vld3vs.32','vld3vc.32','vld3hi.32','vld3ls.32','vld3ge.32','vld3lt.32','vld3gt.32','vld3le.32',
+
+ 'vld4eq.8','vld4ne.8','vld4cs.8','vld4hs.8','vld4cc.8','vld4lo.8','vld4mi.8','vld4pl.8','vld4vs.8','vld4vc.8','vld4hi.8','vld4ls.8','vld4ge.8','vld4lt.8','vld4gt.8','vld4le.8',
+ 'vld4eq.16','vld4ne.16','vld4cs.16','vld4hs.16','vld4cc.16','vld4lo.16','vld4mi.16','vld4pl.16','vld4vs.16','vld4vc.16','vld4hi.16','vld4ls.16','vld4ge.16','vld4lt.16','vld4gt.16','vld4le.16',
+ 'vld4eq.32','vld4ne.32','vld4cs.32','vld4hs.32','vld4cc.32','vld4lo.32','vld4mi.32','vld4pl.32','vld4vs.32','vld4vc.32','vld4hi.32','vld4ls.32','vld4ge.32','vld4lt.32','vld4gt.32','vld4le.32',
+
+ 'vldmeq','vldmne','vldmcs','vldmhs','vldmcc','vldmlo','vldmmi','vldmpl','vldmvs','vldmvc','vldmhi','vldmls','vldmge','vldmlt','vldmgt','vldmle',
+ 'vldmeq.32','vldmne.32','vldmcs.32','vldmhs.32','vldmcc.32','vldmlo.32','vldmmi.32','vldmpl.32','vldmvs.32','vldmvc.32','vldmhi.32','vldmls.32','vldmge.32','vldmlt.32','vldmgt.32','vldmle.32',
+ 'vldmeq.64','vldmne.64','vldmcs.64','vldmhs.64','vldmcc.64','vldmlo.64','vldmmi.64','vldmpl.64','vldmvs.64','vldmvc.64','vldmhi.64','vldmls.64','vldmge.64','vldmlt.64','vldmgt.64','vldmle.64',
+
+ 'vldmiaeq','vldmiane','vldmiacs','vldmiahs','vldmiacc','vldmialo','vldmiami','vldmiapl','vldmiavs','vldmiavc','vldmiahi','vldmials','vldmiage','vldmialt','vldmiagt','vldmiale',
+ 'vldmiaeq.32','vldmiane.32','vldmiacs.32','vldmiahs.32','vldmiacc.32','vldmialo.32','vldmiami.32','vldmiapl.32','vldmiavs.32','vldmiavc.32','vldmiahi.32','vldmials.32','vldmiage.32','vldmialt.32','vldmiagt.32','vldmiale.32',
+ 'vldmiaeq.64','vldmiane.64','vldmiacs.64','vldmiahs.64','vldmiacc.64','vldmialo.64','vldmiami.64','vldmiapl.64','vldmiavs.64','vldmiavc.64','vldmiahi.64','vldmials.64','vldmiage.64','vldmialt.64','vldmiagt.64','vldmiale.64',
+
+ 'vldmdbeq','vldmdbne','vldmdbcs','vldmdbhs','vldmdbcc','vldmdblo','vldmdbmi','vldmdbpl','vldmdbvs','vldmdbvc','vldmdbhi','vldmdbls','vldmdbge','vldmdblt','vldmdbgt','vldmdble',
+ 'vldmdbeq.32','vldmdbne.32','vldmdbcs.32','vldmdbhs.32','vldmdbcc.32','vldmdblo.32','vldmdbmi.32','vldmdbpl.32','vldmdbvs.32','vldmdbvc.32','vldmdbhi.32','vldmdbls.32','vldmdbge.32','vldmdblt.32','vldmdbgt.32','vldmdble.32',
+ 'vldmdbeq.64','vldmdbne.64','vldmdbcs.64','vldmdbhs.64','vldmdbcc.64','vldmdblo.64','vldmdbmi.64','vldmdbpl.64','vldmdbvs.64','vldmdbvc.64','vldmdbhi.64','vldmdbls.64','vldmdbge.64','vldmdblt.64','vldmdbgt.64','vldmdble.64',
+
+ 'vldreq','vldrne','vldrcs','vldrhs','vldrcc','vldrlo','vldrmi','vldrpl','vldrvs','vldrvc','vldrhi','vldrls','vldrge','vldrlt','vldrgt','vldrle',
+ 'vldreq.32','vldrne.32','vldrcs.32','vldrhs.32','vldrcc.32','vldrlo.32','vldrmi.32','vldrpl.32','vldrvs.32','vldrvc.32','vldrhi.32','vldrls.32','vldrge.32','vldrlt.32','vldrgt.32','vldrle.32',
+ 'vldreq.64','vldrne.64','vldrcs.64','vldrhs.64','vldrcc.64','vldrlo.64','vldrmi.64','vldrpl.64','vldrvs.64','vldrvc.64','vldrhi.64','vldrls.64','vldrge.64','vldrlt.64','vldrgt.64','vldrle.64',
+
+ 'vpopeq','vpopne','vpopcs','vpophs','vpopcc','vpoplo','vpopmi','vpoppl','vpopvs','vpopvc','vpophi','vpopls','vpopge','vpoplt','vpopgt','vpople',
+ 'vpopeq.32','vpopne.32','vpopcs.32','vpophs.32','vpopcc.32','vpoplo.32','vpopmi.32','vpoppl.32','vpopvs.32','vpopvc.32','vpophi.32','vpopls.32','vpopge.32','vpoplt.32','vpopgt.32','vpople.32',
+ 'vpopeq.64','vpopne.64','vpopcs.64','vpophs.64','vpopcc.64','vpoplo.64','vpopmi.64','vpoppl.64','vpopvs.64','vpopvc.64','vpophi.64','vpopls.64','vpopge.64','vpoplt.64','vpopgt.64','vpople.64',
+
+ /* Conditional VFPv3 & NEON SIMD Memory Access: Stores */
+ 'vst1eq.8','vst1ne.8','vst1cs.8','vst1hs.8','vst1cc.8','vst1lo.8','vst1mi.8','vst1pl.8','vst1vs.8','vst1vc.8','vst1hi.8','vst1ls.8','vst1ge.8','vst1lt.8','vst1gt.8','vst1le.8',
+ 'vst1eq.16','vst1ne.16','vst1cs.16','vst1hs.16','vst1cc.16','vst1lo.16','vst1mi.16','vst1pl.16','vst1vs.16','vst1vc.16','vst1hi.16','vst1ls.16','vst1ge.16','vst1lt.16','vst1gt.16','vst1le.16',
+ 'vst1eq.32','vst1ne.32','vst1cs.32','vst1hs.32','vst1cc.32','vst1lo.32','vst1mi.32','vst1pl.32','vst1vs.32','vst1vc.32','vst1hi.32','vst1ls.32','vst1ge.32','vst1lt.32','vst1gt.32','vst1le.32',
+ 'vst1eq.64','vst1ne.64','vst1cs.64','vst1hs.64','vst1cc.64','vst1lo.64','vst1mi.64','vst1pl.64','vst1vs.64','vst1vc.64','vst1hi.64','vst1ls.64','vst1ge.64','vst1lt.64','vst1gt.64','vst1le.64',
+
+ 'vst2eq.8','vst2ne.8','vst2cs.8','vst2hs.8','vst2cc.8','vst2lo.8','vst2mi.8','vst2pl.8','vst2vs.8','vst2vc.8','vst2hi.8','vst2ls.8','vst2ge.8','vst2lt.8','vst2gt.8','vst2le.8',
+ 'vst2eq.16','vst2ne.16','vst2cs.16','vst2hs.16','vst2cc.16','vst2lo.16','vst2mi.16','vst2pl.16','vst2vs.16','vst2vc.16','vst2hi.16','vst2ls.16','vst2ge.16','vst2lt.16','vst2gt.16','vst2le.16',
+ 'vst2eq.32','vst2ne.32','vst2cs.32','vst2hs.32','vst2cc.32','vst2lo.32','vst2mi.32','vst2pl.32','vst2vs.32','vst2vc.32','vst2hi.32','vst2ls.32','vst2ge.32','vst2lt.32','vst2gt.32','vst2le.32',
+
+ 'vst3eq.8','vst3ne.8','vst3cs.8','vst3hs.8','vst3cc.8','vst3lo.8','vst3mi.8','vst3pl.8','vst3vs.8','vst3vc.8','vst3hi.8','vst3ls.8','vst3ge.8','vst3lt.8','vst3gt.8','vst3le.8',
+ 'vst3eq.16','vst3ne.16','vst3cs.16','vst3hs.16','vst3cc.16','vst3lo.16','vst3mi.16','vst3pl.16','vst3vs.16','vst3vc.16','vst3hi.16','vst3ls.16','vst3ge.16','vst3lt.16','vst3gt.16','vst3le.16',
+ 'vst3eq.32','vst3ne.32','vst3cs.32','vst3hs.32','vst3cc.32','vst3lo.32','vst3mi.32','vst3pl.32','vst3vs.32','vst3vc.32','vst3hi.32','vst3ls.32','vst3ge.32','vst3lt.32','vst3gt.32','vst3le.32',
+
+ 'vst4eq.8','vst4ne.8','vst4cs.8','vst4hs.8','vst4cc.8','vst4lo.8','vst4mi.8','vst4pl.8','vst4vs.8','vst4vc.8','vst4hi.8','vst4ls.8','vst4ge.8','vst4lt.8','vst4gt.8','vst4le.8',
+ 'vst4eq.16','vst4ne.16','vst4cs.16','vst4hs.16','vst4cc.16','vst4lo.16','vst4mi.16','vst4pl.16','vst4vs.16','vst4vc.16','vst4hi.16','vst4ls.16','vst4ge.16','vst4lt.16','vst4gt.16','vst4le.16',
+ 'vst4eq.32','vst4ne.32','vst4cs.32','vst4hs.32','vst4cc.32','vst4lo.32','vst4mi.32','vst4pl.32','vst4vs.32','vst4vc.32','vst4hi.32','vst4ls.32','vst4ge.32','vst4lt.32','vst4gt.32','vst4le.32',
+
+ 'vstmeq','vstmne','vstmcs','vstmhs','vstmcc','vstmlo','vstmmi','vstmpl','vstmvs','vstmvc','vstmhi','vstmls','vstmge','vstmlt','vstmgt','vstmle',
+ 'vstmeq.32','vstmne.32','vstmcs.32','vstmhs.32','vstmcc.32','vstmlo.32','vstmmi.32','vstmpl.32','vstmvs.32','vstmvc.32','vstmhi.32','vstmls.32','vstmge.32','vstmlt.32','vstmgt.32','vstmle.32',
+ 'vstmeq.64','vstmne.64','vstmcs.64','vstmhs.64','vstmcc.64','vstmlo.64','vstmmi.64','vstmpl.64','vstmvs.64','vstmvc.64','vstmhi.64','vstmls.64','vstmge.64','vstmlt.64','vstmgt.64','vstmle.64',
+
+ 'vstmiaeq','vstmiane','vstmiacs','vstmiahs','vstmiacc','vstmialo','vstmiami','vstmiapl','vstmiavs','vstmiavc','vstmiahi','vstmials','vstmiage','vstmialt','vstmiagt','vstmiale',
+ 'vstmiaeq.32','vstmiane.32','vstmiacs.32','vstmiahs.32','vstmiacc.32','vstmialo.32','vstmiami.32','vstmiapl.32','vstmiavs.32','vstmiavc.32','vstmiahi.32','vstmials.32','vstmiage.32','vstmialt.32','vstmiagt.32','vstmiale.32',
+ 'vstmiaeq.64','vstmiane.64','vstmiacs.64','vstmiahs.64','vstmiacc.64','vstmialo.64','vstmiami.64','vstmiapl.64','vstmiavs.64','vstmiavc.64','vstmiahi.64','vstmials.64','vstmiage.64','vstmialt.64','vstmiagt.64','vstmiale.64',
+
+ 'vstmdbeq','vstmdbne','vstmdbcs','vstmdbhs','vstmdbcc','vstmdblo','vstmdbmi','vstmdbpl','vstmdbvs','vstmdbvc','vstmdbhi','vstmdbls','vstmdbge','vstmdblt','vstmdbgt','vstmdble',
+ 'vstmdbeq.32','vstmdbne.32','vstmdbcs.32','vstmdbhs.32','vstmdbcc.32','vstmdblo.32','vstmdbmi.32','vstmdbpl.32','vstmdbvs.32','vstmdbvc.32','vstmdbhi.32','vstmdbls.32','vstmdbge.32','vstmdblt.32','vstmdbgt.32','vstmdble.32',
+ 'vstmdbeq.64','vstmdbne.64','vstmdbcs.64','vstmdbhs.64','vstmdbcc.64','vstmdblo.64','vstmdbmi.64','vstmdbpl.64','vstmdbvs.64','vstmdbvc.64','vstmdbhi.64','vstmdbls.64','vstmdbge.64','vstmdblt.64','vstmdbgt.64','vstmdble.64',
+
+ 'vstreq','vstrne','vstrcs','vstrhs','vstrcc','vstrlo','vstrmi','vstrpl','vstrvs','vstrvc','vstrhi','vstrls','vstrge','vstrlt','vstrgt','vstrle',
+ 'vstreq.32','vstrne.32','vstrcs.32','vstrhs.32','vstrcc.32','vstrlo.32','vstrmi.32','vstrpl.32','vstrvs.32','vstrvc.32','vstrhi.32','vstrls.32','vstrge.32','vstrlt.32','vstrgt.32','vstrle.32',
+ 'vstreq.64','vstrne.64','vstrcs.64','vstrhs.64','vstrcc.64','vstrlo.64','vstrmi.64','vstrpl.64','vstrvs.64','vstrvc.64','vstrhi.64','vstrls.64','vstrge.64','vstrlt.64','vstrgt.64','vstrle.64',
+
+ 'vpusheq','vpushne','vpushcs','vpushhs','vpushcc','vpushlo','vpushmi','vpushpl','vpushvs','vpushvc','vpushhi','vpushls','vpushge','vpushlt','vpushgt','vpushle',
+ 'vpusheq.32','vpushne.32','vpushcs.32','vpushhs.32','vpushcc.32','vpushlo.32','vpushmi.32','vpushpl.32','vpushvs.32','vpushvc.32','vpushhi.32','vpushls.32','vpushge.32','vpushlt.32','vpushgt.32','vpushle.32',
+ 'vpusheq.64','vpushne.64','vpushcs.64','vpushhs.64','vpushcc.64','vpushlo.64','vpushmi.64','vpushpl.64','vpushvs.64','vpushvc.64','vpushhi.64','vpushls.64','vpushge.64','vpushlt.64','vpushgt.64','vpushle.64'
+ ),
+ /* Conditional NEON SIMD Logical Instructions */
+ 28 => array(
+ 'vandeq','vandne','vandcs','vandhs','vandcc','vandlo','vandmi','vandpl','vandvs','vandvc','vandhi','vandls','vandge','vandlt','vandgt','vandle',
+ 'vandeq.i8','vandne.i8','vandcs.i8','vandhs.i8','vandcc.i8','vandlo.i8','vandmi.i8','vandpl.i8','vandvs.i8','vandvc.i8','vandhi.i8','vandls.i8','vandge.i8','vandlt.i8','vandgt.i8','vandle.i8',
+ 'vandeq.i16','vandne.i16','vandcs.i16','vandhs.i16','vandcc.i16','vandlo.i16','vandmi.i16','vandpl.i16','vandvs.i16','vandvc.i16','vandhi.i16','vandls.i16','vandge.i16','vandlt.i16','vandgt.i16','vandle.i16',
+ 'vandeq.i32','vandne.i32','vandcs.i32','vandhs.i32','vandcc.i32','vandlo.i32','vandmi.i32','vandpl.i32','vandvs.i32','vandvc.i32','vandhi.i32','vandls.i32','vandge.i32','vandlt.i32','vandgt.i32','vandle.i32',
+ 'vandeq.i64','vandne.i64','vandcs.i64','vandhs.i64','vandcc.i64','vandlo.i64','vandmi.i64','vandpl.i64','vandvs.i64','vandvc.i64','vandhi.i64','vandls.i64','vandge.i64','vandlt.i64','vandgt.i64','vandle.i64',
+ 'vandeq.s8','vandne.s8','vandcs.s8','vandhs.s8','vandcc.s8','vandlo.s8','vandmi.s8','vandpl.s8','vandvs.s8','vandvc.s8','vandhi.s8','vandls.s8','vandge.s8','vandlt.s8','vandgt.s8','vandle.s8',
+ 'vandeq.s16','vandne.s16','vandcs.s16','vandhs.s16','vandcc.s16','vandlo.s16','vandmi.s16','vandpl.s16','vandvs.s16','vandvc.s16','vandhi.s16','vandls.s16','vandge.s16','vandlt.s16','vandgt.s16','vandle.s16',
+ 'vandeq.s32','vandne.s32','vandcs.s32','vandhs.s32','vandcc.s32','vandlo.s32','vandmi.s32','vandpl.s32','vandvs.s32','vandvc.s32','vandhi.s32','vandls.s32','vandge.s32','vandlt.s32','vandgt.s32','vandle.s32',
+ 'vandeq.s64','vandne.s64','vandcs.s64','vandhs.s64','vandcc.s64','vandlo.s64','vandmi.s64','vandpl.s64','vandvs.s64','vandvc.s64','vandhi.s64','vandls.s64','vandge.s64','vandlt.s64','vandgt.s64','vandle.s64',
+ 'vandeq.u8','vandne.u8','vandcs.u8','vandhs.u8','vandcc.u8','vandlo.u8','vandmi.u8','vandpl.u8','vandvs.u8','vandvc.u8','vandhi.u8','vandls.u8','vandge.u8','vandlt.u8','vandgt.u8','vandle.u8',
+ 'vandeq.u16','vandne.u16','vandcs.u16','vandhs.u16','vandcc.u16','vandlo.u16','vandmi.u16','vandpl.u16','vandvs.u16','vandvc.u16','vandhi.u16','vandls.u16','vandge.u16','vandlt.u16','vandgt.u16','vandle.u16',
+ 'vandeq.u32','vandne.u32','vandcs.u32','vandhs.u32','vandcc.u32','vandlo.u32','vandmi.u32','vandpl.u32','vandvs.u32','vandvc.u32','vandhi.u32','vandls.u32','vandge.u32','vandlt.u32','vandgt.u32','vandle.u32',
+ 'vandeq.u64','vandne.u64','vandcs.u64','vandhs.u64','vandcc.u64','vandlo.u64','vandmi.u64','vandpl.u64','vandvs.u64','vandvc.u64','vandhi.u64','vandls.u64','vandge.u64','vandlt.u64','vandgt.u64','vandle.u64',
+ 'vandeq.f32','vandne.f32','vandcs.f32','vandhs.f32','vandcc.f32','vandlo.f32','vandmi.f32','vandpl.f32','vandvs.f32','vandvc.f32','vandhi.f32','vandls.f32','vandge.f32','vandlt.f32','vandgt.f32','vandle.f32',
+ 'vandeq.f64','vandne.f64','vandcs.f64','vandhs.f64','vandcc.f64','vandlo.f64','vandmi.f64','vandpl.f64','vandvs.f64','vandvc.f64','vandhi.f64','vandls.f64','vandge.f64','vandlt.f64','vandgt.f64','vandle.f64',
+
+ 'vbiceq','vbicne','vbiccs','vbichs','vbiccc','vbiclo','vbicmi','vbicpl','vbicvs','vbicvc','vbichi','vbicls','vbicge','vbiclt','vbicgt','vbicle',
+ 'vbiceq.i8','vbicne.i8','vbiccs.i8','vbichs.i8','vbiccc.i8','vbiclo.i8','vbicmi.i8','vbicpl.i8','vbicvs.i8','vbicvc.i8','vbichi.i8','vbicls.i8','vbicge.i8','vbiclt.i8','vbicgt.i8','vbicle.i8',
+ 'vbiceq.i16','vbicne.i16','vbiccs.i16','vbichs.i16','vbiccc.i16','vbiclo.i16','vbicmi.i16','vbicpl.i16','vbicvs.i16','vbicvc.i16','vbichi.i16','vbicls.i16','vbicge.i16','vbiclt.i16','vbicgt.i16','vbicle.i16',
+ 'vbiceq.i32','vbicne.i32','vbiccs.i32','vbichs.i32','vbiccc.i32','vbiclo.i32','vbicmi.i32','vbicpl.i32','vbicvs.i32','vbicvc.i32','vbichi.i32','vbicls.i32','vbicge.i32','vbiclt.i32','vbicgt.i32','vbicle.i32',
+ 'vbiceq.i64','vbicne.i64','vbiccs.i64','vbichs.i64','vbiccc.i64','vbiclo.i64','vbicmi.i64','vbicpl.i64','vbicvs.i64','vbicvc.i64','vbichi.i64','vbicls.i64','vbicge.i64','vbiclt.i64','vbicgt.i64','vbicle.i64',
+ 'vbiceq.s8','vbicne.s8','vbiccs.s8','vbichs.s8','vbiccc.s8','vbiclo.s8','vbicmi.s8','vbicpl.s8','vbicvs.s8','vbicvc.s8','vbichi.s8','vbicls.s8','vbicge.s8','vbiclt.s8','vbicgt.s8','vbicle.s8',
+ 'vbiceq.s16','vbicne.s16','vbiccs.s16','vbichs.s16','vbiccc.s16','vbiclo.s16','vbicmi.s16','vbicpl.s16','vbicvs.s16','vbicvc.s16','vbichi.s16','vbicls.s16','vbicge.s16','vbiclt.s16','vbicgt.s16','vbicle.s16',
+ 'vbiceq.s32','vbicne.s32','vbiccs.s32','vbichs.s32','vbiccc.s32','vbiclo.s32','vbicmi.s32','vbicpl.s32','vbicvs.s32','vbicvc.s32','vbichi.s32','vbicls.s32','vbicge.s32','vbiclt.s32','vbicgt.s32','vbicle.s32',
+ 'vbiceq.s64','vbicne.s64','vbiccs.s64','vbichs.s64','vbiccc.s64','vbiclo.s64','vbicmi.s64','vbicpl.s64','vbicvs.s64','vbicvc.s64','vbichi.s64','vbicls.s64','vbicge.s64','vbiclt.s64','vbicgt.s64','vbicle.s64',
+ 'vbiceq.u8','vbicne.u8','vbiccs.u8','vbichs.u8','vbiccc.u8','vbiclo.u8','vbicmi.u8','vbicpl.u8','vbicvs.u8','vbicvc.u8','vbichi.u8','vbicls.u8','vbicge.u8','vbiclt.u8','vbicgt.u8','vbicle.u8',
+ 'vbiceq.u16','vbicne.u16','vbiccs.u16','vbichs.u16','vbiccc.u16','vbiclo.u16','vbicmi.u16','vbicpl.u16','vbicvs.u16','vbicvc.u16','vbichi.u16','vbicls.u16','vbicge.u16','vbiclt.u16','vbicgt.u16','vbicle.u16',
+ 'vbiceq.u32','vbicne.u32','vbiccs.u32','vbichs.u32','vbiccc.u32','vbiclo.u32','vbicmi.u32','vbicpl.u32','vbicvs.u32','vbicvc.u32','vbichi.u32','vbicls.u32','vbicge.u32','vbiclt.u32','vbicgt.u32','vbicle.u32',
+ 'vbiceq.u64','vbicne.u64','vbiccs.u64','vbichs.u64','vbiccc.u64','vbiclo.u64','vbicmi.u64','vbicpl.u64','vbicvs.u64','vbicvc.u64','vbichi.u64','vbicls.u64','vbicge.u64','vbiclt.u64','vbicgt.u64','vbicle.u64',
+ 'vbiceq.f32','vbicne.f32','vbiccs.f32','vbichs.f32','vbiccc.f32','vbiclo.f32','vbicmi.f32','vbicpl.f32','vbicvs.f32','vbicvc.f32','vbichi.f32','vbicls.f32','vbicge.f32','vbiclt.f32','vbicgt.f32','vbicle.f32',
+ 'vbiceq.f64','vbicne.f64','vbiccs.f64','vbichs.f64','vbiccc.f64','vbiclo.f64','vbicmi.f64','vbicpl.f64','vbicvs.f64','vbicvc.f64','vbichi.f64','vbicls.f64','vbicge.f64','vbiclt.f64','vbicgt.f64','vbicle.f64',
+
+ 'vbifeq','vbifne','vbifcs','vbifhs','vbifcc','vbiflo','vbifmi','vbifpl','vbifvs','vbifvc','vbifhi','vbifls','vbifge','vbiflt','vbifgt','vbifle',
+ 'vbifeq.i8','vbifne.i8','vbifcs.i8','vbifhs.i8','vbifcc.i8','vbiflo.i8','vbifmi.i8','vbifpl.i8','vbifvs.i8','vbifvc.i8','vbifhi.i8','vbifls.i8','vbifge.i8','vbiflt.i8','vbifgt.i8','vbifle.i8',
+ 'vbifeq.i16','vbifne.i16','vbifcs.i16','vbifhs.i16','vbifcc.i16','vbiflo.i16','vbifmi.i16','vbifpl.i16','vbifvs.i16','vbifvc.i16','vbifhi.i16','vbifls.i16','vbifge.i16','vbiflt.i16','vbifgt.i16','vbifle.i16',
+ 'vbifeq.i32','vbifne.i32','vbifcs.i32','vbifhs.i32','vbifcc.i32','vbiflo.i32','vbifmi.i32','vbifpl.i32','vbifvs.i32','vbifvc.i32','vbifhi.i32','vbifls.i32','vbifge.i32','vbiflt.i32','vbifgt.i32','vbifle.i32',
+ 'vbifeq.i64','vbifne.i64','vbifcs.i64','vbifhs.i64','vbifcc.i64','vbiflo.i64','vbifmi.i64','vbifpl.i64','vbifvs.i64','vbifvc.i64','vbifhi.i64','vbifls.i64','vbifge.i64','vbiflt.i64','vbifgt.i64','vbifle.i64',
+ 'vbifeq.s8','vbifne.s8','vbifcs.s8','vbifhs.s8','vbifcc.s8','vbiflo.s8','vbifmi.s8','vbifpl.s8','vbifvs.s8','vbifvc.s8','vbifhi.s8','vbifls.s8','vbifge.s8','vbiflt.s8','vbifgt.s8','vbifle.s8',
+ 'vbifeq.s16','vbifne.s16','vbifcs.s16','vbifhs.s16','vbifcc.s16','vbiflo.s16','vbifmi.s16','vbifpl.s16','vbifvs.s16','vbifvc.s16','vbifhi.s16','vbifls.s16','vbifge.s16','vbiflt.s16','vbifgt.s16','vbifle.s16',
+ 'vbifeq.s32','vbifne.s32','vbifcs.s32','vbifhs.s32','vbifcc.s32','vbiflo.s32','vbifmi.s32','vbifpl.s32','vbifvs.s32','vbifvc.s32','vbifhi.s32','vbifls.s32','vbifge.s32','vbiflt.s32','vbifgt.s32','vbifle.s32',
+ 'vbifeq.s64','vbifne.s64','vbifcs.s64','vbifhs.s64','vbifcc.s64','vbiflo.s64','vbifmi.s64','vbifpl.s64','vbifvs.s64','vbifvc.s64','vbifhi.s64','vbifls.s64','vbifge.s64','vbiflt.s64','vbifgt.s64','vbifle.s64',
+ 'vbifeq.u8','vbifne.u8','vbifcs.u8','vbifhs.u8','vbifcc.u8','vbiflo.u8','vbifmi.u8','vbifpl.u8','vbifvs.u8','vbifvc.u8','vbifhi.u8','vbifls.u8','vbifge.u8','vbiflt.u8','vbifgt.u8','vbifle.u8',
+ 'vbifeq.u16','vbifne.u16','vbifcs.u16','vbifhs.u16','vbifcc.u16','vbiflo.u16','vbifmi.u16','vbifpl.u16','vbifvs.u16','vbifvc.u16','vbifhi.u16','vbifls.u16','vbifge.u16','vbiflt.u16','vbifgt.u16','vbifle.u16',
+ 'vbifeq.u32','vbifne.u32','vbifcs.u32','vbifhs.u32','vbifcc.u32','vbiflo.u32','vbifmi.u32','vbifpl.u32','vbifvs.u32','vbifvc.u32','vbifhi.u32','vbifls.u32','vbifge.u32','vbiflt.u32','vbifgt.u32','vbifle.u32',
+ 'vbifeq.u64','vbifne.u64','vbifcs.u64','vbifhs.u64','vbifcc.u64','vbiflo.u64','vbifmi.u64','vbifpl.u64','vbifvs.u64','vbifvc.u64','vbifhi.u64','vbifls.u64','vbifge.u64','vbiflt.u64','vbifgt.u64','vbifle.u64',
+ 'vbifeq.f32','vbifne.f32','vbifcs.f32','vbifhs.f32','vbifcc.f32','vbiflo.f32','vbifmi.f32','vbifpl.f32','vbifvs.f32','vbifvc.f32','vbifhi.f32','vbifls.f32','vbifge.f32','vbiflt.f32','vbifgt.f32','vbifle.f32',
+ 'vbifeq.f64','vbifne.f64','vbifcs.f64','vbifhs.f64','vbifcc.f64','vbiflo.f64','vbifmi.f64','vbifpl.f64','vbifvs.f64','vbifvc.f64','vbifhi.f64','vbifls.f64','vbifge.f64','vbiflt.f64','vbifgt.f64','vbifle.f64',
+
+ 'vbiteq','vbitne','vbitcs','vbiths','vbitcc','vbitlo','vbitmi','vbitpl','vbitvs','vbitvc','vbithi','vbitls','vbitge','vbitlt','vbitgt','vbitle',
+ 'vbiteq.i8','vbitne.i8','vbitcs.i8','vbiths.i8','vbitcc.i8','vbitlo.i8','vbitmi.i8','vbitpl.i8','vbitvs.i8','vbitvc.i8','vbithi.i8','vbitls.i8','vbitge.i8','vbitlt.i8','vbitgt.i8','vbitle.i8',
+ 'vbiteq.i16','vbitne.i16','vbitcs.i16','vbiths.i16','vbitcc.i16','vbitlo.i16','vbitmi.i16','vbitpl.i16','vbitvs.i16','vbitvc.i16','vbithi.i16','vbitls.i16','vbitge.i16','vbitlt.i16','vbitgt.i16','vbitle.i16',
+ 'vbiteq.i32','vbitne.i32','vbitcs.i32','vbiths.i32','vbitcc.i32','vbitlo.i32','vbitmi.i32','vbitpl.i32','vbitvs.i32','vbitvc.i32','vbithi.i32','vbitls.i32','vbitge.i32','vbitlt.i32','vbitgt.i32','vbitle.i32',
+ 'vbiteq.i64','vbitne.i64','vbitcs.i64','vbiths.i64','vbitcc.i64','vbitlo.i64','vbitmi.i64','vbitpl.i64','vbitvs.i64','vbitvc.i64','vbithi.i64','vbitls.i64','vbitge.i64','vbitlt.i64','vbitgt.i64','vbitle.i64',
+ 'vbiteq.s8','vbitne.s8','vbitcs.s8','vbiths.s8','vbitcc.s8','vbitlo.s8','vbitmi.s8','vbitpl.s8','vbitvs.s8','vbitvc.s8','vbithi.s8','vbitls.s8','vbitge.s8','vbitlt.s8','vbitgt.s8','vbitle.s8',
+ 'vbiteq.s16','vbitne.s16','vbitcs.s16','vbiths.s16','vbitcc.s16','vbitlo.s16','vbitmi.s16','vbitpl.s16','vbitvs.s16','vbitvc.s16','vbithi.s16','vbitls.s16','vbitge.s16','vbitlt.s16','vbitgt.s16','vbitle.s16',
+ 'vbiteq.s32','vbitne.s32','vbitcs.s32','vbiths.s32','vbitcc.s32','vbitlo.s32','vbitmi.s32','vbitpl.s32','vbitvs.s32','vbitvc.s32','vbithi.s32','vbitls.s32','vbitge.s32','vbitlt.s32','vbitgt.s32','vbitle.s32',
+ 'vbiteq.s64','vbitne.s64','vbitcs.s64','vbiths.s64','vbitcc.s64','vbitlo.s64','vbitmi.s64','vbitpl.s64','vbitvs.s64','vbitvc.s64','vbithi.s64','vbitls.s64','vbitge.s64','vbitlt.s64','vbitgt.s64','vbitle.s64',
+ 'vbiteq.u8','vbitne.u8','vbitcs.u8','vbiths.u8','vbitcc.u8','vbitlo.u8','vbitmi.u8','vbitpl.u8','vbitvs.u8','vbitvc.u8','vbithi.u8','vbitls.u8','vbitge.u8','vbitlt.u8','vbitgt.u8','vbitle.u8',
+ 'vbiteq.u16','vbitne.u16','vbitcs.u16','vbiths.u16','vbitcc.u16','vbitlo.u16','vbitmi.u16','vbitpl.u16','vbitvs.u16','vbitvc.u16','vbithi.u16','vbitls.u16','vbitge.u16','vbitlt.u16','vbitgt.u16','vbitle.u16',
+ 'vbiteq.u32','vbitne.u32','vbitcs.u32','vbiths.u32','vbitcc.u32','vbitlo.u32','vbitmi.u32','vbitpl.u32','vbitvs.u32','vbitvc.u32','vbithi.u32','vbitls.u32','vbitge.u32','vbitlt.u32','vbitgt.u32','vbitle.u32',
+ 'vbiteq.u64','vbitne.u64','vbitcs.u64','vbiths.u64','vbitcc.u64','vbitlo.u64','vbitmi.u64','vbitpl.u64','vbitvs.u64','vbitvc.u64','vbithi.u64','vbitls.u64','vbitge.u64','vbitlt.u64','vbitgt.u64','vbitle.u64',
+ 'vbiteq.f32','vbitne.f32','vbitcs.f32','vbiths.f32','vbitcc.f32','vbitlo.f32','vbitmi.f32','vbitpl.f32','vbitvs.f32','vbitvc.f32','vbithi.f32','vbitls.f32','vbitge.f32','vbitlt.f32','vbitgt.f32','vbitle.f32',
+ 'vbiteq.f64','vbitne.f64','vbitcs.f64','vbiths.f64','vbitcc.f64','vbitlo.f64','vbitmi.f64','vbitpl.f64','vbitvs.f64','vbitvc.f64','vbithi.f64','vbitls.f64','vbitge.f64','vbitlt.f64','vbitgt.f64','vbitle.f64',
+
+ 'vbsleq','vbslne','vbslcs','vbslhs','vbslcc','vbsllo','vbslmi','vbslpl','vbslvs','vbslvc','vbslhi','vbslls','vbslge','vbsllt','vbslgt','vbslle',
+ 'vbsleq.i8','vbslne.i8','vbslcs.i8','vbslhs.i8','vbslcc.i8','vbsllo.i8','vbslmi.i8','vbslpl.i8','vbslvs.i8','vbslvc.i8','vbslhi.i8','vbslls.i8','vbslge.i8','vbsllt.i8','vbslgt.i8','vbslle.i8',
+ 'vbsleq.i16','vbslne.i16','vbslcs.i16','vbslhs.i16','vbslcc.i16','vbsllo.i16','vbslmi.i16','vbslpl.i16','vbslvs.i16','vbslvc.i16','vbslhi.i16','vbslls.i16','vbslge.i16','vbsllt.i16','vbslgt.i16','vbslle.i16',
+ 'vbsleq.i32','vbslne.i32','vbslcs.i32','vbslhs.i32','vbslcc.i32','vbsllo.i32','vbslmi.i32','vbslpl.i32','vbslvs.i32','vbslvc.i32','vbslhi.i32','vbslls.i32','vbslge.i32','vbsllt.i32','vbslgt.i32','vbslle.i32',
+ 'vbsleq.i64','vbslne.i64','vbslcs.i64','vbslhs.i64','vbslcc.i64','vbsllo.i64','vbslmi.i64','vbslpl.i64','vbslvs.i64','vbslvc.i64','vbslhi.i64','vbslls.i64','vbslge.i64','vbsllt.i64','vbslgt.i64','vbslle.i64',
+ 'vbsleq.s8','vbslne.s8','vbslcs.s8','vbslhs.s8','vbslcc.s8','vbsllo.s8','vbslmi.s8','vbslpl.s8','vbslvs.s8','vbslvc.s8','vbslhi.s8','vbslls.s8','vbslge.s8','vbsllt.s8','vbslgt.s8','vbslle.s8',
+ 'vbsleq.s16','vbslne.s16','vbslcs.s16','vbslhs.s16','vbslcc.s16','vbsllo.s16','vbslmi.s16','vbslpl.s16','vbslvs.s16','vbslvc.s16','vbslhi.s16','vbslls.s16','vbslge.s16','vbsllt.s16','vbslgt.s16','vbslle.s16',
+ 'vbsleq.s32','vbslne.s32','vbslcs.s32','vbslhs.s32','vbslcc.s32','vbsllo.s32','vbslmi.s32','vbslpl.s32','vbslvs.s32','vbslvc.s32','vbslhi.s32','vbslls.s32','vbslge.s32','vbsllt.s32','vbslgt.s32','vbslle.s32',
+ 'vbsleq.s64','vbslne.s64','vbslcs.s64','vbslhs.s64','vbslcc.s64','vbsllo.s64','vbslmi.s64','vbslpl.s64','vbslvs.s64','vbslvc.s64','vbslhi.s64','vbslls.s64','vbslge.s64','vbsllt.s64','vbslgt.s64','vbslle.s64',
+ 'vbsleq.u8','vbslne.u8','vbslcs.u8','vbslhs.u8','vbslcc.u8','vbsllo.u8','vbslmi.u8','vbslpl.u8','vbslvs.u8','vbslvc.u8','vbslhi.u8','vbslls.u8','vbslge.u8','vbsllt.u8','vbslgt.u8','vbslle.u8',
+ 'vbsleq.u16','vbslne.u16','vbslcs.u16','vbslhs.u16','vbslcc.u16','vbsllo.u16','vbslmi.u16','vbslpl.u16','vbslvs.u16','vbslvc.u16','vbslhi.u16','vbslls.u16','vbslge.u16','vbsllt.u16','vbslgt.u16','vbslle.u16',
+ 'vbsleq.u32','vbslne.u32','vbslcs.u32','vbslhs.u32','vbslcc.u32','vbsllo.u32','vbslmi.u32','vbslpl.u32','vbslvs.u32','vbslvc.u32','vbslhi.u32','vbslls.u32','vbslge.u32','vbsllt.u32','vbslgt.u32','vbslle.u32',
+ 'vbsleq.u64','vbslne.u64','vbslcs.u64','vbslhs.u64','vbslcc.u64','vbsllo.u64','vbslmi.u64','vbslpl.u64','vbslvs.u64','vbslvc.u64','vbslhi.u64','vbslls.u64','vbslge.u64','vbsllt.u64','vbslgt.u64','vbslle.u64',
+ 'vbsleq.f32','vbslne.f32','vbslcs.f32','vbslhs.f32','vbslcc.f32','vbsllo.f32','vbslmi.f32','vbslpl.f32','vbslvs.f32','vbslvc.f32','vbslhi.f32','vbslls.f32','vbslge.f32','vbsllt.f32','vbslgt.f32','vbslle.f32',
+ 'vbsleq.f64','vbslne.f64','vbslcs.f64','vbslhs.f64','vbslcc.f64','vbsllo.f64','vbslmi.f64','vbslpl.f64','vbslvs.f64','vbslvc.f64','vbslhi.f64','vbslls.f64','vbslge.f64','vbsllt.f64','vbslgt.f64','vbslle.f64',
+
+ 'veoreq','veorne','veorcs','veorhs','veorcc','veorlo','veormi','veorpl','veorvs','veorvc','veorhi','veorls','veorge','veorlt','veorgt','veorle',
+ 'veoreq.i8','veorne.i8','veorcs.i8','veorhs.i8','veorcc.i8','veorlo.i8','veormi.i8','veorpl.i8','veorvs.i8','veorvc.i8','veorhi.i8','veorls.i8','veorge.i8','veorlt.i8','veorgt.i8','veorle.i8',
+ 'veoreq.i16','veorne.i16','veorcs.i16','veorhs.i16','veorcc.i16','veorlo.i16','veormi.i16','veorpl.i16','veorvs.i16','veorvc.i16','veorhi.i16','veorls.i16','veorge.i16','veorlt.i16','veorgt.i16','veorle.i16',
+ 'veoreq.i32','veorne.i32','veorcs.i32','veorhs.i32','veorcc.i32','veorlo.i32','veormi.i32','veorpl.i32','veorvs.i32','veorvc.i32','veorhi.i32','veorls.i32','veorge.i32','veorlt.i32','veorgt.i32','veorle.i32',
+ 'veoreq.i64','veorne.i64','veorcs.i64','veorhs.i64','veorcc.i64','veorlo.i64','veormi.i64','veorpl.i64','veorvs.i64','veorvc.i64','veorhi.i64','veorls.i64','veorge.i64','veorlt.i64','veorgt.i64','veorle.i64',
+ 'veoreq.s8','veorne.s8','veorcs.s8','veorhs.s8','veorcc.s8','veorlo.s8','veormi.s8','veorpl.s8','veorvs.s8','veorvc.s8','veorhi.s8','veorls.s8','veorge.s8','veorlt.s8','veorgt.s8','veorle.s8',
+ 'veoreq.s16','veorne.s16','veorcs.s16','veorhs.s16','veorcc.s16','veorlo.s16','veormi.s16','veorpl.s16','veorvs.s16','veorvc.s16','veorhi.s16','veorls.s16','veorge.s16','veorlt.s16','veorgt.s16','veorle.s16',
+ 'veoreq.s32','veorne.s32','veorcs.s32','veorhs.s32','veorcc.s32','veorlo.s32','veormi.s32','veorpl.s32','veorvs.s32','veorvc.s32','veorhi.s32','veorls.s32','veorge.s32','veorlt.s32','veorgt.s32','veorle.s32',
+ 'veoreq.s64','veorne.s64','veorcs.s64','veorhs.s64','veorcc.s64','veorlo.s64','veormi.s64','veorpl.s64','veorvs.s64','veorvc.s64','veorhi.s64','veorls.s64','veorge.s64','veorlt.s64','veorgt.s64','veorle.s64',
+ 'veoreq.u8','veorne.u8','veorcs.u8','veorhs.u8','veorcc.u8','veorlo.u8','veormi.u8','veorpl.u8','veorvs.u8','veorvc.u8','veorhi.u8','veorls.u8','veorge.u8','veorlt.u8','veorgt.u8','veorle.u8',
+ 'veoreq.u16','veorne.u16','veorcs.u16','veorhs.u16','veorcc.u16','veorlo.u16','veormi.u16','veorpl.u16','veorvs.u16','veorvc.u16','veorhi.u16','veorls.u16','veorge.u16','veorlt.u16','veorgt.u16','veorle.u16',
+ 'veoreq.u32','veorne.u32','veorcs.u32','veorhs.u32','veorcc.u32','veorlo.u32','veormi.u32','veorpl.u32','veorvs.u32','veorvc.u32','veorhi.u32','veorls.u32','veorge.u32','veorlt.u32','veorgt.u32','veorle.u32',
+ 'veoreq.u64','veorne.u64','veorcs.u64','veorhs.u64','veorcc.u64','veorlo.u64','veormi.u64','veorpl.u64','veorvs.u64','veorvc.u64','veorhi.u64','veorls.u64','veorge.u64','veorlt.u64','veorgt.u64','veorle.u64',
+ 'veoreq.f32','veorne.f32','veorcs.f32','veorhs.f32','veorcc.f32','veorlo.f32','veormi.f32','veorpl.f32','veorvs.f32','veorvc.f32','veorhi.f32','veorls.f32','veorge.f32','veorlt.f32','veorgt.f32','veorle.f32',
+ 'veoreq.f64','veorne.f64','veorcs.f64','veorhs.f64','veorcc.f64','veorlo.f64','veormi.f64','veorpl.f64','veorvs.f64','veorvc.f64','veorhi.f64','veorls.f64','veorge.f64','veorlt.f64','veorgt.f64','veorle.f64',
+
+ 'vmoveq','vmovne','vmovcs','vmovhs','vmovcc','vmovlo','vmovmi','vmovpl','vmovvs','vmovvc','vmovhi','vmovls','vmovge','vmovlt','vmovgt','vmovle',
+ 'vmoveq.8','vmovne.8','vmovcs.8','vmovhs.8','vmovcc.8','vmovlo.8','vmovmi.8','vmovpl.8','vmovvs.8','vmovvc.8','vmovhi.8','vmovls.8','vmovge.8','vmovlt.8','vmovgt.8','vmovle.8',
+ 'vmoveq.16','vmovne.16','vmovcs.16','vmovhs.16','vmovcc.16','vmovlo.16','vmovmi.16','vmovpl.16','vmovvs.16','vmovvc.16','vmovhi.16','vmovls.16','vmovge.16','vmovlt.16','vmovgt.16','vmovle.16',
+ 'vmoveq.32','vmovne.32','vmovcs.32','vmovhs.32','vmovcc.32','vmovlo.32','vmovmi.32','vmovpl.32','vmovvs.32','vmovvc.32','vmovhi.32','vmovls.32','vmovge.32','vmovlt.32','vmovgt.32','vmovle.32',
+ 'vmoveq.i8','vmovne.i8','vmovcs.i8','vmovhs.i8','vmovcc.i8','vmovlo.i8','vmovmi.i8','vmovpl.i8','vmovvs.i8','vmovvc.i8','vmovhi.i8','vmovls.i8','vmovge.i8','vmovlt.i8','vmovgt.i8','vmovle.i8',
+ 'vmoveq.i16','vmovne.i16','vmovcs.i16','vmovhs.i16','vmovcc.i16','vmovlo.i16','vmovmi.i16','vmovpl.i16','vmovvs.i16','vmovvc.i16','vmovhi.i16','vmovls.i16','vmovge.i16','vmovlt.i16','vmovgt.i16','vmovle.i16',
+ 'vmoveq.i32','vmovne.i32','vmovcs.i32','vmovhs.i32','vmovcc.i32','vmovlo.i32','vmovmi.i32','vmovpl.i32','vmovvs.i32','vmovvc.i32','vmovhi.i32','vmovls.i32','vmovge.i32','vmovlt.i32','vmovgt.i32','vmovle.i32',
+ 'vmoveq.i64','vmovne.i64','vmovcs.i64','vmovhs.i64','vmovcc.i64','vmovlo.i64','vmovmi.i64','vmovpl.i64','vmovvs.i64','vmovvc.i64','vmovhi.i64','vmovls.i64','vmovge.i64','vmovlt.i64','vmovgt.i64','vmovle.i64',
+ 'vmoveq.f32','vmovne.f32','vmovcs.f32','vmovhs.f32','vmovcc.f32','vmovlo.f32','vmovmi.f32','vmovpl.f32','vmovvs.f32','vmovvc.f32','vmovhi.f32','vmovls.f32','vmovge.f32','vmovlt.f32','vmovgt.f32','vmovle.f32',
+ 'vmoveq.f64','vmovne.f64','vmovcs.f64','vmovhs.f64','vmovcc.f64','vmovlo.f64','vmovmi.f64','vmovpl.f64','vmovvs.f64','vmovvc.f64','vmovhi.f64','vmovls.f64','vmovge.f64','vmovlt.f64','vmovgt.f64','vmovle.f64',
+
+ 'vmvneq','vmvnne','vmvncs','vmvnhs','vmvncc','vmvnlo','vmvnmi','vmvnpl','vmvnvs','vmvnvc','vmvnhi','vmvnls','vmvnge','vmvnlt','vmvngt','vmvnle',
+ 'vmvneq.s8','vmvnne.s8','vmvncs.s8','vmvnhs.s8','vmvncc.s8','vmvnlo.s8','vmvnmi.s8','vmvnpl.s8','vmvnvs.s8','vmvnvc.s8','vmvnhi.s8','vmvnls.s8','vmvnge.s8','vmvnlt.s8','vmvngt.s8','vmvnle.s8',
+ 'vmvneq.s16','vmvnne.s16','vmvncs.s16','vmvnhs.s16','vmvncc.s16','vmvnlo.s16','vmvnmi.s16','vmvnpl.s16','vmvnvs.s16','vmvnvc.s16','vmvnhi.s16','vmvnls.s16','vmvnge.s16','vmvnlt.s16','vmvngt.s16','vmvnle.s16',
+ 'vmvneq.s32','vmvnne.s32','vmvncs.s32','vmvnhs.s32','vmvncc.s32','vmvnlo.s32','vmvnmi.s32','vmvnpl.s32','vmvnvs.s32','vmvnvc.s32','vmvnhi.s32','vmvnls.s32','vmvnge.s32','vmvnlt.s32','vmvngt.s32','vmvnle.s32',
+ 'vmvneq.s64','vmvnne.s64','vmvncs.s64','vmvnhs.s64','vmvncc.s64','vmvnlo.s64','vmvnmi.s64','vmvnpl.s64','vmvnvs.s64','vmvnvc.s64','vmvnhi.s64','vmvnls.s64','vmvnge.s64','vmvnlt.s64','vmvngt.s64','vmvnle.s64',
+ 'vmvneq.u8','vmvnne.u8','vmvncs.u8','vmvnhs.u8','vmvncc.u8','vmvnlo.u8','vmvnmi.u8','vmvnpl.u8','vmvnvs.u8','vmvnvc.u8','vmvnhi.u8','vmvnls.u8','vmvnge.u8','vmvnlt.u8','vmvngt.u8','vmvnle.u8',
+ 'vmvneq.u16','vmvnne.u16','vmvncs.u16','vmvnhs.u16','vmvncc.u16','vmvnlo.u16','vmvnmi.u16','vmvnpl.u16','vmvnvs.u16','vmvnvc.u16','vmvnhi.u16','vmvnls.u16','vmvnge.u16','vmvnlt.u16','vmvngt.u16','vmvnle.u16',
+ 'vmvneq.u32','vmvnne.u32','vmvncs.u32','vmvnhs.u32','vmvncc.u32','vmvnlo.u32','vmvnmi.u32','vmvnpl.u32','vmvnvs.u32','vmvnvc.u32','vmvnhi.u32','vmvnls.u32','vmvnge.u32','vmvnlt.u32','vmvngt.u32','vmvnle.u32',
+ 'vmvneq.u64','vmvnne.u64','vmvncs.u64','vmvnhs.u64','vmvncc.u64','vmvnlo.u64','vmvnmi.u64','vmvnpl.u64','vmvnvs.u64','vmvnvc.u64','vmvnhi.u64','vmvnls.u64','vmvnge.u64','vmvnlt.u64','vmvngt.u64','vmvnle.u64',
+ 'vmvneq.i8','vmvnne.i8','vmvncs.i8','vmvnhs.i8','vmvncc.i8','vmvnlo.i8','vmvnmi.i8','vmvnpl.i8','vmvnvs.i8','vmvnvc.i8','vmvnhi.i8','vmvnls.i8','vmvnge.i8','vmvnlt.i8','vmvngt.i8','vmvnle.i8',
+ 'vmvneq.i16','vmvnne.i16','vmvncs.i16','vmvnhs.i16','vmvncc.i16','vmvnlo.i16','vmvnmi.i16','vmvnpl.i16','vmvnvs.i16','vmvnvc.i16','vmvnhi.i16','vmvnls.i16','vmvnge.i16','vmvnlt.i16','vmvngt.i16','vmvnle.i16',
+ 'vmvneq.i32','vmvnne.i32','vmvncs.i32','vmvnhs.i32','vmvncc.i32','vmvnlo.i32','vmvnmi.i32','vmvnpl.i32','vmvnvs.i32','vmvnvc.i32','vmvnhi.i32','vmvnls.i32','vmvnge.i32','vmvnlt.i32','vmvngt.i32','vmvnle.i32',
+ 'vmvneq.i64','vmvnne.i64','vmvncs.i64','vmvnhs.i64','vmvncc.i64','vmvnlo.i64','vmvnmi.i64','vmvnpl.i64','vmvnvs.i64','vmvnvc.i64','vmvnhi.i64','vmvnls.i64','vmvnge.i64','vmvnlt.i64','vmvngt.i64','vmvnle.i64',
+ 'vmvneq.f32','vmvnne.f32','vmvncs.f32','vmvnhs.f32','vmvncc.f32','vmvnlo.f32','vmvnmi.f32','vmvnpl.f32','vmvnvs.f32','vmvnvc.f32','vmvnhi.f32','vmvnls.f32','vmvnge.f32','vmvnlt.f32','vmvngt.f32','vmvnle.f32',
+ 'vmvneq.f64','vmvnne.f64','vmvncs.f64','vmvnhs.f64','vmvncc.f64','vmvnlo.f64','vmvnmi.f64','vmvnpl.f64','vmvnvs.f64','vmvnvc.f64','vmvnhi.f64','vmvnls.f64','vmvnge.f64','vmvnlt.f64','vmvngt.f64','vmvnle.f64',
+
+ 'vorneq','vornne','vorncs','vornhs','vorncc','vornlo','vornmi','vornpl','vornvs','vornvc','vornhi','vornls','vornge','vornlt','vorngt','vornle',
+ 'vorneq.s8','vornne.s8','vorncs.s8','vornhs.s8','vorncc.s8','vornlo.s8','vornmi.s8','vornpl.s8','vornvs.s8','vornvc.s8','vornhi.s8','vornls.s8','vornge.s8','vornlt.s8','vorngt.s8','vornle.s8',
+ 'vorneq.s16','vornne.s16','vorncs.s16','vornhs.s16','vorncc.s16','vornlo.s16','vornmi.s16','vornpl.s16','vornvs.s16','vornvc.s16','vornhi.s16','vornls.s16','vornge.s16','vornlt.s16','vorngt.s16','vornle.s16',
+ 'vorneq.s32','vornne.s32','vorncs.s32','vornhs.s32','vorncc.s32','vornlo.s32','vornmi.s32','vornpl.s32','vornvs.s32','vornvc.s32','vornhi.s32','vornls.s32','vornge.s32','vornlt.s32','vorngt.s32','vornle.s32',
+ 'vorneq.s64','vornne.s64','vorncs.s64','vornhs.s64','vorncc.s64','vornlo.s64','vornmi.s64','vornpl.s64','vornvs.s64','vornvc.s64','vornhi.s64','vornls.s64','vornge.s64','vornlt.s64','vorngt.s64','vornle.s64',
+ 'vorneq.u8','vornne.u8','vorncs.u8','vornhs.u8','vorncc.u8','vornlo.u8','vornmi.u8','vornpl.u8','vornvs.u8','vornvc.u8','vornhi.u8','vornls.u8','vornge.u8','vornlt.u8','vorngt.u8','vornle.u8',
+ 'vorneq.u16','vornne.u16','vorncs.u16','vornhs.u16','vorncc.u16','vornlo.u16','vornmi.u16','vornpl.u16','vornvs.u16','vornvc.u16','vornhi.u16','vornls.u16','vornge.u16','vornlt.u16','vorngt.u16','vornle.u16',
+ 'vorneq.u32','vornne.u32','vorncs.u32','vornhs.u32','vorncc.u32','vornlo.u32','vornmi.u32','vornpl.u32','vornvs.u32','vornvc.u32','vornhi.u32','vornls.u32','vornge.u32','vornlt.u32','vorngt.u32','vornle.u32',
+ 'vorneq.u64','vornne.u64','vorncs.u64','vornhs.u64','vorncc.u64','vornlo.u64','vornmi.u64','vornpl.u64','vornvs.u64','vornvc.u64','vornhi.u64','vornls.u64','vornge.u64','vornlt.u64','vorngt.u64','vornle.u64',
+ 'vorneq.i8','vornne.i8','vorncs.i8','vornhs.i8','vorncc.i8','vornlo.i8','vornmi.i8','vornpl.i8','vornvs.i8','vornvc.i8','vornhi.i8','vornls.i8','vornge.i8','vornlt.i8','vorngt.i8','vornle.i8',
+ 'vorneq.i16','vornne.i16','vorncs.i16','vornhs.i16','vorncc.i16','vornlo.i16','vornmi.i16','vornpl.i16','vornvs.i16','vornvc.i16','vornhi.i16','vornls.i16','vornge.i16','vornlt.i16','vorngt.i16','vornle.i16',
+ 'vorneq.i32','vornne.i32','vorncs.i32','vornhs.i32','vorncc.i32','vornlo.i32','vornmi.i32','vornpl.i32','vornvs.i32','vornvc.i32','vornhi.i32','vornls.i32','vornge.i32','vornlt.i32','vorngt.i32','vornle.i32',
+ 'vorneq.i64','vornne.i64','vorncs.i64','vornhs.i64','vorncc.i64','vornlo.i64','vornmi.i64','vornpl.i64','vornvs.i64','vornvc.i64','vornhi.i64','vornls.i64','vornge.i64','vornlt.i64','vorngt.i64','vornle.i64',
+ 'vorneq.f32','vornne.f32','vorncs.f32','vornhs.f32','vorncc.f32','vornlo.f32','vornmi.f32','vornpl.f32','vornvs.f32','vornvc.f32','vornhi.f32','vornls.f32','vornge.f32','vornlt.f32','vorngt.f32','vornle.f32',
+ 'vorneq.f64','vornne.f64','vorncs.f64','vornhs.f64','vorncc.f64','vornlo.f64','vornmi.f64','vornpl.f64','vornvs.f64','vornvc.f64','vornhi.f64','vornls.f64','vornge.f64','vornlt.f64','vorngt.f64','vornle.f64',
+
+ 'vorreq','vorrne','vorrcs','vorrhs','vorrcc','vorrlo','vorrmi','vorrpl','vorrvs','vorrvc','vorrhi','vorrls','vorrge','vorrlt','vorrgt','vorrle',
+ 'vorreq.s8','vorrne.s8','vorrcs.s8','vorrhs.s8','vorrcc.s8','vorrlo.s8','vorrmi.s8','vorrpl.s8','vorrvs.s8','vorrvc.s8','vorrhi.s8','vorrls.s8','vorrge.s8','vorrlt.s8','vorrgt.s8','vorrle.s8',
+ 'vorreq.s16','vorrne.s16','vorrcs.s16','vorrhs.s16','vorrcc.s16','vorrlo.s16','vorrmi.s16','vorrpl.s16','vorrvs.s16','vorrvc.s16','vorrhi.s16','vorrls.s16','vorrge.s16','vorrlt.s16','vorrgt.s16','vorrle.s16',
+ 'vorreq.s32','vorrne.s32','vorrcs.s32','vorrhs.s32','vorrcc.s32','vorrlo.s32','vorrmi.s32','vorrpl.s32','vorrvs.s32','vorrvc.s32','vorrhi.s32','vorrls.s32','vorrge.s32','vorrlt.s32','vorrgt.s32','vorrle.s32',
+ 'vorreq.s64','vorrne.s64','vorrcs.s64','vorrhs.s64','vorrcc.s64','vorrlo.s64','vorrmi.s64','vorrpl.s64','vorrvs.s64','vorrvc.s64','vorrhi.s64','vorrls.s64','vorrge.s64','vorrlt.s64','vorrgt.s64','vorrle.s64',
+ 'vorreq.u8','vorrne.u8','vorrcs.u8','vorrhs.u8','vorrcc.u8','vorrlo.u8','vorrmi.u8','vorrpl.u8','vorrvs.u8','vorrvc.u8','vorrhi.u8','vorrls.u8','vorrge.u8','vorrlt.u8','vorrgt.u8','vorrle.u8',
+ 'vorreq.u16','vorrne.u16','vorrcs.u16','vorrhs.u16','vorrcc.u16','vorrlo.u16','vorrmi.u16','vorrpl.u16','vorrvs.u16','vorrvc.u16','vorrhi.u16','vorrls.u16','vorrge.u16','vorrlt.u16','vorrgt.u16','vorrle.u16',
+ 'vorreq.u32','vorrne.u32','vorrcs.u32','vorrhs.u32','vorrcc.u32','vorrlo.u32','vorrmi.u32','vorrpl.u32','vorrvs.u32','vorrvc.u32','vorrhi.u32','vorrls.u32','vorrge.u32','vorrlt.u32','vorrgt.u32','vorrle.u32',
+ 'vorreq.u64','vorrne.u64','vorrcs.u64','vorrhs.u64','vorrcc.u64','vorrlo.u64','vorrmi.u64','vorrpl.u64','vorrvs.u64','vorrvc.u64','vorrhi.u64','vorrls.u64','vorrge.u64','vorrlt.u64','vorrgt.u64','vorrle.u64',
+ 'vorreq.i8','vorrne.i8','vorrcs.i8','vorrhs.i8','vorrcc.i8','vorrlo.i8','vorrmi.i8','vorrpl.i8','vorrvs.i8','vorrvc.i8','vorrhi.i8','vorrls.i8','vorrge.i8','vorrlt.i8','vorrgt.i8','vorrle.i8',
+ 'vorreq.i16','vorrne.i16','vorrcs.i16','vorrhs.i16','vorrcc.i16','vorrlo.i16','vorrmi.i16','vorrpl.i16','vorrvs.i16','vorrvc.i16','vorrhi.i16','vorrls.i16','vorrge.i16','vorrlt.i16','vorrgt.i16','vorrle.i16',
+ 'vorreq.i32','vorrne.i32','vorrcs.i32','vorrhs.i32','vorrcc.i32','vorrlo.i32','vorrmi.i32','vorrpl.i32','vorrvs.i32','vorrvc.i32','vorrhi.i32','vorrls.i32','vorrge.i32','vorrlt.i32','vorrgt.i32','vorrle.i32',
+ 'vorreq.i64','vorrne.i64','vorrcs.i64','vorrhs.i64','vorrcc.i64','vorrlo.i64','vorrmi.i64','vorrpl.i64','vorrvs.i64','vorrvc.i64','vorrhi.i64','vorrls.i64','vorrge.i64','vorrlt.i64','vorrgt.i64','vorrle.i64',
+ 'vorreq.f32','vorrne.f32','vorrcs.f32','vorrhs.f32','vorrcc.f32','vorrlo.f32','vorrmi.f32','vorrpl.f32','vorrvs.f32','vorrvc.f32','vorrhi.f32','vorrls.f32','vorrge.f32','vorrlt.f32','vorrgt.f32','vorrle.f32',
+ 'vorreq.f64','vorrne.f64','vorrcs.f64','vorrhs.f64','vorrcc.f64','vorrlo.f64','vorrmi.f64','vorrpl.f64','vorrvs.f64','vorrvc.f64','vorrhi.f64','vorrls.f64','vorrge.f64','vorrlt.f64','vorrgt.f64','vorrle.f64',
+
+ 'vswpeq','vswpne','vswpcs','vswphs','vswpcc','vswplo','vswpmi','vswppl','vswpvs','vswpvc','vswphi','vswpls','vswpge','vswplt','vswpgt','vswple',
+ 'vswpeq.s8','vswpne.s8','vswpcs.s8','vswphs.s8','vswpcc.s8','vswplo.s8','vswpmi.s8','vswppl.s8','vswpvs.s8','vswpvc.s8','vswphi.s8','vswpls.s8','vswpge.s8','vswplt.s8','vswpgt.s8','vswple.s8',
+ 'vswpeq.s16','vswpne.s16','vswpcs.s16','vswphs.s16','vswpcc.s16','vswplo.s16','vswpmi.s16','vswppl.s16','vswpvs.s16','vswpvc.s16','vswphi.s16','vswpls.s16','vswpge.s16','vswplt.s16','vswpgt.s16','vswple.s16',
+ 'vswpeq.s32','vswpne.s32','vswpcs.s32','vswphs.s32','vswpcc.s32','vswplo.s32','vswpmi.s32','vswppl.s32','vswpvs.s32','vswpvc.s32','vswphi.s32','vswpls.s32','vswpge.s32','vswplt.s32','vswpgt.s32','vswple.s32',
+ 'vswpeq.s64','vswpne.s64','vswpcs.s64','vswphs.s64','vswpcc.s64','vswplo.s64','vswpmi.s64','vswppl.s64','vswpvs.s64','vswpvc.s64','vswphi.s64','vswpls.s64','vswpge.s64','vswplt.s64','vswpgt.s64','vswple.s64',
+ 'vswpeq.u8','vswpne.u8','vswpcs.u8','vswphs.u8','vswpcc.u8','vswplo.u8','vswpmi.u8','vswppl.u8','vswpvs.u8','vswpvc.u8','vswphi.u8','vswpls.u8','vswpge.u8','vswplt.u8','vswpgt.u8','vswple.u8',
+ 'vswpeq.u16','vswpne.u16','vswpcs.u16','vswphs.u16','vswpcc.u16','vswplo.u16','vswpmi.u16','vswppl.u16','vswpvs.u16','vswpvc.u16','vswphi.u16','vswpls.u16','vswpge.u16','vswplt.u16','vswpgt.u16','vswple.u16',
+ 'vswpeq.u32','vswpne.u32','vswpcs.u32','vswphs.u32','vswpcc.u32','vswplo.u32','vswpmi.u32','vswppl.u32','vswpvs.u32','vswpvc.u32','vswphi.u32','vswpls.u32','vswpge.u32','vswplt.u32','vswpgt.u32','vswple.u32',
+ 'vswpeq.u64','vswpne.u64','vswpcs.u64','vswphs.u64','vswpcc.u64','vswplo.u64','vswpmi.u64','vswppl.u64','vswpvs.u64','vswpvc.u64','vswphi.u64','vswpls.u64','vswpge.u64','vswplt.u64','vswpgt.u64','vswple.u64',
+ 'vswpeq.i8','vswpne.i8','vswpcs.i8','vswphs.i8','vswpcc.i8','vswplo.i8','vswpmi.i8','vswppl.i8','vswpvs.i8','vswpvc.i8','vswphi.i8','vswpls.i8','vswpge.i8','vswplt.i8','vswpgt.i8','vswple.i8',
+ 'vswpeq.i16','vswpne.i16','vswpcs.i16','vswphs.i16','vswpcc.i16','vswplo.i16','vswpmi.i16','vswppl.i16','vswpvs.i16','vswpvc.i16','vswphi.i16','vswpls.i16','vswpge.i16','vswplt.i16','vswpgt.i16','vswple.i16',
+ 'vswpeq.i32','vswpne.i32','vswpcs.i32','vswphs.i32','vswpcc.i32','vswplo.i32','vswpmi.i32','vswppl.i32','vswpvs.i32','vswpvc.i32','vswphi.i32','vswpls.i32','vswpge.i32','vswplt.i32','vswpgt.i32','vswple.i32',
+ 'vswpeq.i64','vswpne.i64','vswpcs.i64','vswphs.i64','vswpcc.i64','vswplo.i64','vswpmi.i64','vswppl.i64','vswpvs.i64','vswpvc.i64','vswphi.i64','vswpls.i64','vswpge.i64','vswplt.i64','vswpgt.i64','vswple.i64',
+ 'vswpeq.f32','vswpne.f32','vswpcs.f32','vswphs.f32','vswpcc.f32','vswplo.f32','vswpmi.f32','vswppl.f32','vswpvs.f32','vswpvc.f32','vswphi.f32','vswpls.f32','vswpge.f32','vswplt.f32','vswpgt.f32','vswple.f32',
+ 'vswpeq.f64','vswpne.f64','vswpcs.f64','vswphs.f64','vswpcc.f64','vswplo.f64','vswpmi.f64','vswppl.f64','vswpvs.f64','vswpvc.f64','vswphi.f64','vswpls.f64','vswpge.f64','vswplt.f64','vswpgt.f64','vswple.f64'
+ ),
+ /* Conditional NEON SIMD ARM Registers Interop Instructions */
+ 29 => array(
+ 'vmrseq','vmrsne','vmrscs','vmrshs','vmrscc','vmrslo','vmrsmi','vmrspl','vmrsvs','vmrsvc','vmrshi','vmrsls','vmrsge','vmrslt','vmrsgt','vmrsle',
+ 'vmsreq','vmsrne','vmsrcs','vmsrhs','vmsrcc','vmsrlo','vmsrmi','vmsrpl','vmsrvs','vmsrvc','vmsrhi','vmsrls','vmsrge','vmsrlt','vmsrgt','vmsrle'
+ ),
+ /* Conditional NEON SIMD Bit/Byte-Level Instructions */
+ 30 => array(
+ 'vcnteq.8','vcntne.8','vcntcs.8','vcnths.8','vcntcc.8','vcntlo.8','vcntmi.8','vcntpl.8','vcntvs.8','vcntvc.8','vcnthi.8','vcntls.8','vcntge.8','vcntlt.8','vcntgt.8','vcntle.8',
+ 'vdupeq.8','vdupne.8','vdupcs.8','vduphs.8','vdupcc.8','vduplo.8','vdupmi.8','vduppl.8','vdupvs.8','vdupvc.8','vduphi.8','vdupls.8','vdupge.8','vduplt.8','vdupgt.8','vduple.8',
+
+ 'vdupeq.16','vdupne.16','vdupcs.16','vduphs.16','vdupcc.16','vduplo.16','vdupmi.16','vduppl.16','vdupvs.16','vdupvc.16','vduphi.16','vdupls.16','vdupge.16','vduplt.16','vdupgt.16','vduple.16',
+ 'vdupeq.32','vdupne.32','vdupcs.32','vduphs.32','vdupcc.32','vduplo.32','vdupmi.32','vduppl.32','vdupvs.32','vdupvc.32','vduphi.32','vdupls.32','vdupge.32','vduplt.32','vdupgt.32','vduple.32',
+
+ 'vexteq.8','vextne.8','vextcs.8','vexths.8','vextcc.8','vextlo.8','vextmi.8','vextpl.8','vextvs.8','vextvc.8','vexthi.8','vextls.8','vextge.8','vextlt.8','vextgt.8','vextle.8',
+ 'vexteq.16','vextne.16','vextcs.16','vexths.16','vextcc.16','vextlo.16','vextmi.16','vextpl.16','vextvs.16','vextvc.16','vexthi.16','vextls.16','vextge.16','vextlt.16','vextgt.16','vextle.16',
+
+ 'vexteq.32','vextne.32','vextcs.32','vexths.32','vextcc.32','vextlo.32','vextmi.32','vextpl.32','vextvs.32','vextvc.32','vexthi.32','vextls.32','vextge.32','vextlt.32','vextgt.32','vextle.32',
+ 'vexteq.64','vextne.64','vextcs.64','vexths.64','vextcc.64','vextlo.64','vextmi.64','vextpl.64','vextvs.64','vextvc.64','vexthi.64','vextls.64','vextge.64','vextlt.64','vextgt.64','vextle.64',
+
+ 'vrev16eq.8','vrev16ne.8','vrev16cs.8','vrev16hs.8','vrev16cc.8','vrev16lo.8','vrev16mi.8','vrev16pl.8','vrev16vs.8','vrev16vc.8','vrev16hi.8','vrev16ls.8','vrev16ge.8','vrev16lt.8','vrev16gt.8','vrev16le.8',
+ 'vrev32eq.8','vrev32ne.8','vrev32cs.8','vrev32hs.8','vrev32cc.8','vrev32lo.8','vrev32mi.8','vrev32pl.8','vrev32vs.8','vrev32vc.8','vrev32hi.8','vrev32ls.8','vrev32ge.8','vrev32lt.8','vrev32gt.8','vrev32le.8',
+ 'vrev32eq.16','vrev32ne.16','vrev32cs.16','vrev32hs.16','vrev32cc.16','vrev32lo.16','vrev32mi.16','vrev32pl.16','vrev32vs.16','vrev32vc.16','vrev32hi.16','vrev32ls.16','vrev32ge.16','vrev32lt.16','vrev32gt.16','vrev32le.16',
+ 'vrev64eq.8','vrev64ne.8','vrev64cs.8','vrev64hs.8','vrev64cc.8','vrev64lo.8','vrev64mi.8','vrev64pl.8','vrev64vs.8','vrev64vc.8','vrev64hi.8','vrev64ls.8','vrev64ge.8','vrev64lt.8','vrev64gt.8','vrev64le.8',
+ 'vrev64eq.16','vrev64ne.16','vrev64cs.16','vrev64hs.16','vrev64cc.16','vrev64lo.16','vrev64mi.16','vrev64pl.16','vrev64vs.16','vrev64vc.16','vrev64hi.16','vrev64ls.16','vrev64ge.16','vrev64lt.16','vrev64gt.16','vrev64le.16',
+ 'vrev64eq.32','vrev64ne.32','vrev64cs.32','vrev64hs.32','vrev64cc.32','vrev64lo.32','vrev64mi.32','vrev64pl.32','vrev64vs.32','vrev64vc.32','vrev64hi.32','vrev64ls.32','vrev64ge.32','vrev64lt.32','vrev64gt.32','vrev64le.32',
+
+ 'vslieq.8','vsline.8','vslics.8','vslihs.8','vslicc.8','vslilo.8','vslimi.8','vslipl.8','vslivs.8','vslivc.8','vslihi.8','vslils.8','vslige.8','vslilt.8','vsligt.8','vslile.8',
+ 'vslieq.16','vsline.16','vslics.16','vslihs.16','vslicc.16','vslilo.16','vslimi.16','vslipl.16','vslivs.16','vslivc.16','vslihi.16','vslils.16','vslige.16','vslilt.16','vsligt.16','vslile.16',
+ 'vslieq.32','vsline.32','vslics.32','vslihs.32','vslicc.32','vslilo.32','vslimi.32','vslipl.32','vslivs.32','vslivc.32','vslihi.32','vslils.32','vslige.32','vslilt.32','vsligt.32','vslile.32',
+ 'vslieq.64','vsline.64','vslics.64','vslihs.64','vslicc.64','vslilo.64','vslimi.64','vslipl.64','vslivs.64','vslivc.64','vslihi.64','vslils.64','vslige.64','vslilt.64','vsligt.64','vslile.64',
+
+ 'vsrieq.8','vsrine.8','vsrics.8','vsrihs.8','vsricc.8','vsrilo.8','vsrimi.8','vsripl.8','vsrivs.8','vsrivc.8','vsrihi.8','vsrils.8','vsrige.8','vsrilt.8','vsrigt.8','vsrile.8',
+ 'vsrieq.16','vsrine.16','vsrics.16','vsrihs.16','vsricc.16','vsrilo.16','vsrimi.16','vsripl.16','vsrivs.16','vsrivc.16','vsrihi.16','vsrils.16','vsrige.16','vsrilt.16','vsrigt.16','vsrile.16',
+ 'vsrieq.32','vsrine.32','vsrics.32','vsrihs.32','vsricc.32','vsrilo.32','vsrimi.32','vsripl.32','vsrivs.32','vsrivc.32','vsrihi.32','vsrils.32','vsrige.32','vsrilt.32','vsrigt.32','vsrile.32',
+ 'vsrieq.64','vsrine.64','vsrics.64','vsrihs.64','vsricc.64','vsrilo.64','vsrimi.64','vsripl.64','vsrivs.64','vsrivc.64','vsrihi.64','vsrils.64','vsrige.64','vsrilt.64','vsrigt.64','vsrile.64',
+
+ 'vtbleq.8','vtblne.8','vtblcs.8','vtblhs.8','vtblcc.8','vtbllo.8','vtblmi.8','vtblpl.8','vtblvs.8','vtblvc.8','vtblhi.8','vtblls.8','vtblge.8','vtbllt.8','vtblgt.8','vtblle.8',
+
+ 'vtbxeq','vtbxne','vtbxcs','vtbxhs','vtbxcc','vtbxlo','vtbxmi','vtbxpl','vtbxvs','vtbxvc','vtbxhi','vtbxls','vtbxge','vtbxlt','vtbxgt','vtbxle',
+
+ 'vtrneq.8','vtrnne.8','vtrncs.8','vtrnhs.8','vtrncc.8','vtrnlo.8','vtrnmi.8','vtrnpl.8','vtrnvs.8','vtrnvc.8','vtrnhi.8','vtrnls.8','vtrnge.8','vtrnlt.8','vtrngt.8','vtrnle.8',
+ 'vtrneq.16','vtrnne.16','vtrncs.16','vtrnhs.16','vtrncc.16','vtrnlo.16','vtrnmi.16','vtrnpl.16','vtrnvs.16','vtrnvc.16','vtrnhi.16','vtrnls.16','vtrnge.16','vtrnlt.16','vtrngt.16','vtrnle.16',
+ 'vtrneq.32','vtrnne.32','vtrncs.32','vtrnhs.32','vtrncc.32','vtrnlo.32','vtrnmi.32','vtrnpl.32','vtrnvs.32','vtrnvc.32','vtrnhi.32','vtrnls.32','vtrnge.32','vtrnlt.32','vtrngt.32','vtrnle.32',
+
+ 'vtsteq.8','vtstne.8','vtstcs.8','vtsths.8','vtstcc.8','vtstlo.8','vtstmi.8','vtstpl.8','vtstvs.8','vtstvc.8','vtsthi.8','vtstls.8','vtstge.8','vtstlt.8','vtstgt.8','vtstle.8',
+ 'vtsteq.16','vtstne.16','vtstcs.16','vtsths.16','vtstcc.16','vtstlo.16','vtstmi.16','vtstpl.16','vtstvs.16','vtstvc.16','vtsthi.16','vtstls.16','vtstge.16','vtstlt.16','vtstgt.16','vtstle.16',
+ 'vtsteq.32','vtstne.32','vtstcs.32','vtsths.32','vtstcc.32','vtstlo.32','vtstmi.32','vtstpl.32','vtstvs.32','vtstvc.32','vtsthi.32','vtstls.32','vtstge.32','vtstlt.32','vtstgt.32','vtstle.32',
+
+ 'vuzpeq.8','vuzpne.8','vuzpcs.8','vuzphs.8','vuzpcc.8','vuzplo.8','vuzpmi.8','vuzppl.8','vuzpvs.8','vuzpvc.8','vuzphi.8','vuzpls.8','vuzpge.8','vuzplt.8','vuzpgt.8','vuzple.8',
+ 'vuzpeq.16','vuzpne.16','vuzpcs.16','vuzphs.16','vuzpcc.16','vuzplo.16','vuzpmi.16','vuzppl.16','vuzpvs.16','vuzpvc.16','vuzphi.16','vuzpls.16','vuzpge.16','vuzplt.16','vuzpgt.16','vuzple.16',
+ 'vuzpeq.32','vuzpne.32','vuzpcs.32','vuzphs.32','vuzpcc.32','vuzplo.32','vuzpmi.32','vuzppl.32','vuzpvs.32','vuzpvc.32','vuzphi.32','vuzpls.32','vuzpge.32','vuzplt.32','vuzpgt.32','vuzple.32',
+
+ 'vzipeq.8','vzipne.8','vzipcs.8','vziphs.8','vzipcc.8','vziplo.8','vzipmi.8','vzippl.8','vzipvs.8','vzipvc.8','vziphi.8','vzipls.8','vzipge.8','vziplt.8','vzipgt.8','vziple.8',
+ 'vzipeq.16','vzipne.16','vzipcs.16','vziphs.16','vzipcc.16','vziplo.16','vzipmi.16','vzippl.16','vzipvs.16','vzipvc.16','vziphi.16','vzipls.16','vzipge.16','vziplt.16','vzipgt.16','vziple.16',
+ 'vzipeq.32','vzipne.32','vzipcs.32','vziphs.32','vzipcc.32','vziplo.32','vzipmi.32','vzippl.32','vzipvs.32','vzipvc.32','vziphi.32','vzipls.32','vzipge.32','vziplt.32','vzipgt.32','vziple.32',
+
+ 'vmulleq.p8','vmullne.p8','vmullcs.p8','vmullhs.p8','vmullcc.p8','vmulllo.p8','vmullmi.p8','vmullpl.p8','vmullvs.p8','vmullvc.p8','vmullhi.p8','vmullls.p8','vmullge.p8','vmulllt.p8','vmullgt.p8','vmullle.p8'
+ ),
+ /* Conditional NEON SIMD Universal Integer Instructions */
+ 31 => array(
+ 'vaddeq.i8','vaddne.i8','vaddcs.i8','vaddhs.i8','vaddcc.i8','vaddlo.i8','vaddmi.i8','vaddpl.i8','vaddvs.i8','vaddvc.i8','vaddhi.i8','vaddls.i8','vaddge.i8','vaddlt.i8','vaddgt.i8','vaddle.i8',
+ 'vaddeq.i16','vaddne.i16','vaddcs.i16','vaddhs.i16','vaddcc.i16','vaddlo.i16','vaddmi.i16','vaddpl.i16','vaddvs.i16','vaddvc.i16','vaddhi.i16','vaddls.i16','vaddge.i16','vaddlt.i16','vaddgt.i16','vaddle.i16',
+ 'vaddeq.i32','vaddne.i32','vaddcs.i32','vaddhs.i32','vaddcc.i32','vaddlo.i32','vaddmi.i32','vaddpl.i32','vaddvs.i32','vaddvc.i32','vaddhi.i32','vaddls.i32','vaddge.i32','vaddlt.i32','vaddgt.i32','vaddle.i32',
+ 'vaddeq.i64','vaddne.i64','vaddcs.i64','vaddhs.i64','vaddcc.i64','vaddlo.i64','vaddmi.i64','vaddpl.i64','vaddvs.i64','vaddvc.i64','vaddhi.i64','vaddls.i64','vaddge.i64','vaddlt.i64','vaddgt.i64','vaddle.i64',
+
+ 'vsubeq.i8','vsubne.i8','vsubcs.i8','vsubhs.i8','vsubcc.i8','vsublo.i8','vsubmi.i8','vsubpl.i8','vsubvs.i8','vsubvc.i8','vsubhi.i8','vsubls.i8','vsubge.i8','vsublt.i8','vsubgt.i8','vsuble.i8',
+ 'vsubeq.i16','vsubne.i16','vsubcs.i16','vsubhs.i16','vsubcc.i16','vsublo.i16','vsubmi.i16','vsubpl.i16','vsubvs.i16','vsubvc.i16','vsubhi.i16','vsubls.i16','vsubge.i16','vsublt.i16','vsubgt.i16','vsuble.i16',
+ 'vsubeq.i32','vsubne.i32','vsubcs.i32','vsubhs.i32','vsubcc.i32','vsublo.i32','vsubmi.i32','vsubpl.i32','vsubvs.i32','vsubvc.i32','vsubhi.i32','vsubls.i32','vsubge.i32','vsublt.i32','vsubgt.i32','vsuble.i32',
+ 'vsubeq.i64','vsubne.i64','vsubcs.i64','vsubhs.i64','vsubcc.i64','vsublo.i64','vsubmi.i64','vsubpl.i64','vsubvs.i64','vsubvc.i64','vsubhi.i64','vsubls.i64','vsubge.i64','vsublt.i64','vsubgt.i64','vsuble.i64',
+
+ 'vaddhneq.i16','vaddhnne.i16','vaddhncs.i16','vaddhnhs.i16','vaddhncc.i16','vaddhnlo.i16','vaddhnmi.i16','vaddhnpl.i16','vaddhnvs.i16','vaddhnvc.i16','vaddhnhi.i16','vaddhnls.i16','vaddhnge.i16','vaddhnlt.i16','vaddhngt.i16','vaddhnle.i16',
+ 'vaddhneq.i32','vaddhnne.i32','vaddhncs.i32','vaddhnhs.i32','vaddhncc.i32','vaddhnlo.i32','vaddhnmi.i32','vaddhnpl.i32','vaddhnvs.i32','vaddhnvc.i32','vaddhnhi.i32','vaddhnls.i32','vaddhnge.i32','vaddhnlt.i32','vaddhngt.i32','vaddhnle.i32',
+ 'vaddhneq.i64','vaddhnne.i64','vaddhncs.i64','vaddhnhs.i64','vaddhncc.i64','vaddhnlo.i64','vaddhnmi.i64','vaddhnpl.i64','vaddhnvs.i64','vaddhnvc.i64','vaddhnhi.i64','vaddhnls.i64','vaddhnge.i64','vaddhnlt.i64','vaddhngt.i64','vaddhnle.i64',
+
+ 'vsubhneq.i16','vsubhnne.i16','vsubhncs.i16','vsubhnhs.i16','vsubhncc.i16','vsubhnlo.i16','vsubhnmi.i16','vsubhnpl.i16','vsubhnvs.i16','vsubhnvc.i16','vsubhnhi.i16','vsubhnls.i16','vsubhnge.i16','vsubhnlt.i16','vsubhngt.i16','vsubhnle.i16',
+ 'vsubhneq.i32','vsubhnne.i32','vsubhncs.i32','vsubhnhs.i32','vsubhncc.i32','vsubhnlo.i32','vsubhnmi.i32','vsubhnpl.i32','vsubhnvs.i32','vsubhnvc.i32','vsubhnhi.i32','vsubhnls.i32','vsubhnge.i32','vsubhnlt.i32','vsubhngt.i32','vsubhnle.i32',
+ 'vsubhneq.i64','vsubhnne.i64','vsubhncs.i64','vsubhnhs.i64','vsubhncc.i64','vsubhnlo.i64','vsubhnmi.i64','vsubhnpl.i64','vsubhnvs.i64','vsubhnvc.i64','vsubhnhi.i64','vsubhnls.i64','vsubhnge.i64','vsubhnlt.i64','vsubhngt.i64','vsubhnle.i64',
+
+ 'vraddhneq.i16','vraddhnne.i16','vraddhncs.i16','vraddhnhs.i16','vraddhncc.i16','vraddhnlo.i16','vraddhnmi.i16','vraddhnpl.i16','vraddhnvs.i16','vraddhnvc.i16','vraddhnhi.i16','vraddhnls.i16','vraddhnge.i16','vraddhnlt.i16','vraddhngt.i16','vraddhnle.i16',
+ 'vraddhneq.i32','vraddhnne.i32','vraddhncs.i32','vraddhnhs.i32','vraddhncc.i32','vraddhnlo.i32','vraddhnmi.i32','vraddhnpl.i32','vraddhnvs.i32','vraddhnvc.i32','vraddhnhi.i32','vraddhnls.i32','vraddhnge.i32','vraddhnlt.i32','vraddhngt.i32','vraddhnle.i32',
+ 'vraddhneq.i64','vraddhnne.i64','vraddhncs.i64','vraddhnhs.i64','vraddhncc.i64','vraddhnlo.i64','vraddhnmi.i64','vraddhnpl.i64','vraddhnvs.i64','vraddhnvc.i64','vraddhnhi.i64','vraddhnls.i64','vraddhnge.i64','vraddhnlt.i64','vraddhngt.i64','vraddhnle.i64',
+
+ 'vrsubhneq.i16','vrsubhnne.i16','vrsubhncs.i16','vrsubhnhs.i16','vrsubhncc.i16','vrsubhnlo.i16','vrsubhnmi.i16','vrsubhnpl.i16','vrsubhnvs.i16','vrsubhnvc.i16','vrsubhnhi.i16','vrsubhnls.i16','vrsubhnge.i16','vrsubhnlt.i16','vrsubhngt.i16','vrsubhnle.i16',
+ 'vrsubhneq.i32','vrsubhnne.i32','vrsubhncs.i32','vrsubhnhs.i32','vrsubhncc.i32','vrsubhnlo.i32','vrsubhnmi.i32','vrsubhnpl.i32','vrsubhnvs.i32','vrsubhnvc.i32','vrsubhnhi.i32','vrsubhnls.i32','vrsubhnge.i32','vrsubhnlt.i32','vrsubhngt.i32','vrsubhnle.i32',
+ 'vrsubhneq.i64','vrsubhnne.i64','vrsubhncs.i64','vrsubhnhs.i64','vrsubhncc.i64','vrsubhnlo.i64','vrsubhnmi.i64','vrsubhnpl.i64','vrsubhnvs.i64','vrsubhnvc.i64','vrsubhnhi.i64','vrsubhnls.i64','vrsubhnge.i64','vrsubhnlt.i64','vrsubhngt.i64','vrsubhnle.i64',
+
+ 'vpaddeq.i8','vpaddne.i8','vpaddcs.i8','vpaddhs.i8','vpaddcc.i8','vpaddlo.i8','vpaddmi.i8','vpaddpl.i8','vpaddvs.i8','vpaddvc.i8','vpaddhi.i8','vpaddls.i8','vpaddge.i8','vpaddlt.i8','vpaddgt.i8','vpaddle.i8',
+ 'vpaddeq.i16','vpaddne.i16','vpaddcs.i16','vpaddhs.i16','vpaddcc.i16','vpaddlo.i16','vpaddmi.i16','vpaddpl.i16','vpaddvs.i16','vpaddvc.i16','vpaddhi.i16','vpaddls.i16','vpaddge.i16','vpaddlt.i16','vpaddgt.i16','vpaddle.i16',
+ 'vpaddeq.i32','vpaddne.i32','vpaddcs.i32','vpaddhs.i32','vpaddcc.i32','vpaddlo.i32','vpaddmi.i32','vpaddpl.i32','vpaddvs.i32','vpaddvc.i32','vpaddhi.i32','vpaddls.i32','vpaddge.i32','vpaddlt.i32','vpaddgt.i32','vpaddle.i32',
+
+ 'vceqeq.i8','vceqne.i8','vceqcs.i8','vceqhs.i8','vceqcc.i8','vceqlo.i8','vceqmi.i8','vceqpl.i8','vceqvs.i8','vceqvc.i8','vceqhi.i8','vceqls.i8','vceqge.i8','vceqlt.i8','vceqgt.i8','vceqle.i8',
+ 'vceqeq.i16','vceqne.i16','vceqcs.i16','vceqhs.i16','vceqcc.i16','vceqlo.i16','vceqmi.i16','vceqpl.i16','vceqvs.i16','vceqvc.i16','vceqhi.i16','vceqls.i16','vceqge.i16','vceqlt.i16','vceqgt.i16','vceqle.i16',
+ 'vceqeq.i32','vceqne.i32','vceqcs.i32','vceqhs.i32','vceqcc.i32','vceqlo.i32','vceqmi.i32','vceqpl.i32','vceqvs.i32','vceqvc.i32','vceqhi.i32','vceqls.i32','vceqge.i32','vceqlt.i32','vceqgt.i32','vceqle.i32',
+
+ 'vclzeq.i8','vclzne.i8','vclzcs.i8','vclzhs.i8','vclzcc.i8','vclzlo.i8','vclzmi.i8','vclzpl.i8','vclzvs.i8','vclzvc.i8','vclzhi.i8','vclzls.i8','vclzge.i8','vclzlt.i8','vclzgt.i8','vclzle.i8',
+ 'vclzeq.i16','vclzne.i16','vclzcs.i16','vclzhs.i16','vclzcc.i16','vclzlo.i16','vclzmi.i16','vclzpl.i16','vclzvs.i16','vclzvc.i16','vclzhi.i16','vclzls.i16','vclzge.i16','vclzlt.i16','vclzgt.i16','vclzle.i16',
+ 'vclzeq.i32','vclzne.i32','vclzcs.i32','vclzhs.i32','vclzcc.i32','vclzlo.i32','vclzmi.i32','vclzpl.i32','vclzvs.i32','vclzvc.i32','vclzhi.i32','vclzls.i32','vclzge.i32','vclzlt.i32','vclzgt.i32','vclzle.i32',
+
+ 'vmovneq.i16','vmovnne.i16','vmovncs.i16','vmovnhs.i16','vmovncc.i16','vmovnlo.i16','vmovnmi.i16','vmovnpl.i16','vmovnvs.i16','vmovnvc.i16','vmovnhi.i16','vmovnls.i16','vmovnge.i16','vmovnlt.i16','vmovngt.i16','vmovnle.i16',
+ 'vmovneq.i32','vmovnne.i32','vmovncs.i32','vmovnhs.i32','vmovncc.i32','vmovnlo.i32','vmovnmi.i32','vmovnpl.i32','vmovnvs.i32','vmovnvc.i32','vmovnhi.i32','vmovnls.i32','vmovnge.i32','vmovnlt.i32','vmovngt.i32','vmovnle.i32',
+ 'vmovneq.i64','vmovnne.i64','vmovncs.i64','vmovnhs.i64','vmovncc.i64','vmovnlo.i64','vmovnmi.i64','vmovnpl.i64','vmovnvs.i64','vmovnvc.i64','vmovnhi.i64','vmovnls.i64','vmovnge.i64','vmovnlt.i64','vmovngt.i64','vmovnle.i64',
+
+ 'vmlaeq.s8','vmlane.s8','vmlacs.s8','vmlahs.s8','vmlacc.s8','vmlalo.s8','vmlami.s8','vmlapl.s8','vmlavs.s8','vmlavc.s8','vmlahi.s8','vmlals.s8','vmlage.s8','vmlalt.s8','vmlagt.s8','vmlale.s8',
+ 'vmlaeq.s16','vmlane.s16','vmlacs.s16','vmlahs.s16','vmlacc.s16','vmlalo.s16','vmlami.s16','vmlapl.s16','vmlavs.s16','vmlavc.s16','vmlahi.s16','vmlals.s16','vmlage.s16','vmlalt.s16','vmlagt.s16','vmlale.s16',
+ 'vmlaeq.s32','vmlane.s32','vmlacs.s32','vmlahs.s32','vmlacc.s32','vmlalo.s32','vmlami.s32','vmlapl.s32','vmlavs.s32','vmlavc.s32','vmlahi.s32','vmlals.s32','vmlage.s32','vmlalt.s32','vmlagt.s32','vmlale.s32',
+ 'vmlaeq.u8','vmlane.u8','vmlacs.u8','vmlahs.u8','vmlacc.u8','vmlalo.u8','vmlami.u8','vmlapl.u8','vmlavs.u8','vmlavc.u8','vmlahi.u8','vmlals.u8','vmlage.u8','vmlalt.u8','vmlagt.u8','vmlale.u8',
+ 'vmlaeq.u16','vmlane.u16','vmlacs.u16','vmlahs.u16','vmlacc.u16','vmlalo.u16','vmlami.u16','vmlapl.u16','vmlavs.u16','vmlavc.u16','vmlahi.u16','vmlals.u16','vmlage.u16','vmlalt.u16','vmlagt.u16','vmlale.u16',
+ 'vmlaeq.u32','vmlane.u32','vmlacs.u32','vmlahs.u32','vmlacc.u32','vmlalo.u32','vmlami.u32','vmlapl.u32','vmlavs.u32','vmlavc.u32','vmlahi.u32','vmlals.u32','vmlage.u32','vmlalt.u32','vmlagt.u32','vmlale.u32',
+ 'vmlaeq.i8','vmlane.i8','vmlacs.i8','vmlahs.i8','vmlacc.i8','vmlalo.i8','vmlami.i8','vmlapl.i8','vmlavs.i8','vmlavc.i8','vmlahi.i8','vmlals.i8','vmlage.i8','vmlalt.i8','vmlagt.i8','vmlale.i8',
+ 'vmlaeq.i16','vmlane.i16','vmlacs.i16','vmlahs.i16','vmlacc.i16','vmlalo.i16','vmlami.i16','vmlapl.i16','vmlavs.i16','vmlavc.i16','vmlahi.i16','vmlals.i16','vmlage.i16','vmlalt.i16','vmlagt.i16','vmlale.i16',
+ 'vmlaeq.i32','vmlane.i32','vmlacs.i32','vmlahs.i32','vmlacc.i32','vmlalo.i32','vmlami.i32','vmlapl.i32','vmlavs.i32','vmlavc.i32','vmlahi.i32','vmlals.i32','vmlage.i32','vmlalt.i32','vmlagt.i32','vmlale.i32',
+
+ 'vmlseq.s8','vmlsne.s8','vmlscs.s8','vmlshs.s8','vmlscc.s8','vmlslo.s8','vmlsmi.s8','vmlspl.s8','vmlsvs.s8','vmlsvc.s8','vmlshi.s8','vmlsls.s8','vmlsge.s8','vmlslt.s8','vmlsgt.s8','vmlsle.s8',
+ 'vmlseq.s16','vmlsne.s16','vmlscs.s16','vmlshs.s16','vmlscc.s16','vmlslo.s16','vmlsmi.s16','vmlspl.s16','vmlsvs.s16','vmlsvc.s16','vmlshi.s16','vmlsls.s16','vmlsge.s16','vmlslt.s16','vmlsgt.s16','vmlsle.s16',
+ 'vmlseq.s32','vmlsne.s32','vmlscs.s32','vmlshs.s32','vmlscc.s32','vmlslo.s32','vmlsmi.s32','vmlspl.s32','vmlsvs.s32','vmlsvc.s32','vmlshi.s32','vmlsls.s32','vmlsge.s32','vmlslt.s32','vmlsgt.s32','vmlsle.s32',
+ 'vmlseq.u8','vmlsne.u8','vmlscs.u8','vmlshs.u8','vmlscc.u8','vmlslo.u8','vmlsmi.u8','vmlspl.u8','vmlsvs.u8','vmlsvc.u8','vmlshi.u8','vmlsls.u8','vmlsge.u8','vmlslt.u8','vmlsgt.u8','vmlsle.u8',
+ 'vmlseq.u16','vmlsne.u16','vmlscs.u16','vmlshs.u16','vmlscc.u16','vmlslo.u16','vmlsmi.u16','vmlspl.u16','vmlsvs.u16','vmlsvc.u16','vmlshi.u16','vmlsls.u16','vmlsge.u16','vmlslt.u16','vmlsgt.u16','vmlsle.u16',
+ 'vmlseq.u32','vmlsne.u32','vmlscs.u32','vmlshs.u32','vmlscc.u32','vmlslo.u32','vmlsmi.u32','vmlspl.u32','vmlsvs.u32','vmlsvc.u32','vmlshi.u32','vmlsls.u32','vmlsge.u32','vmlslt.u32','vmlsgt.u32','vmlsle.u32',
+ 'vmlseq.i8','vmlsne.i8','vmlscs.i8','vmlshs.i8','vmlscc.i8','vmlslo.i8','vmlsmi.i8','vmlspl.i8','vmlsvs.i8','vmlsvc.i8','vmlshi.i8','vmlsls.i8','vmlsge.i8','vmlslt.i8','vmlsgt.i8','vmlsle.i8',
+ 'vmlseq.i16','vmlsne.i16','vmlscs.i16','vmlshs.i16','vmlscc.i16','vmlslo.i16','vmlsmi.i16','vmlspl.i16','vmlsvs.i16','vmlsvc.i16','vmlshi.i16','vmlsls.i16','vmlsge.i16','vmlslt.i16','vmlsgt.i16','vmlsle.i16',
+ 'vmlseq.i32','vmlsne.i32','vmlscs.i32','vmlshs.i32','vmlscc.i32','vmlslo.i32','vmlsmi.i32','vmlspl.i32','vmlsvs.i32','vmlsvc.i32','vmlshi.i32','vmlsls.i32','vmlsge.i32','vmlslt.i32','vmlsgt.i32','vmlsle.i32',
+
+ 'vmuleq.s8','vmulne.s8','vmulcs.s8','vmulhs.s8','vmulcc.s8','vmullo.s8','vmulmi.s8','vmulpl.s8','vmulvs.s8','vmulvc.s8','vmulhi.s8','vmulls.s8','vmulge.s8','vmullt.s8','vmulgt.s8','vmulle.s8',
+ 'vmuleq.s16','vmulne.s16','vmulcs.s16','vmulhs.s16','vmulcc.s16','vmullo.s16','vmulmi.s16','vmulpl.s16','vmulvs.s16','vmulvc.s16','vmulhi.s16','vmulls.s16','vmulge.s16','vmullt.s16','vmulgt.s16','vmulle.s16',
+ 'vmuleq.s32','vmulne.s32','vmulcs.s32','vmulhs.s32','vmulcc.s32','vmullo.s32','vmulmi.s32','vmulpl.s32','vmulvs.s32','vmulvc.s32','vmulhi.s32','vmulls.s32','vmulge.s32','vmullt.s32','vmulgt.s32','vmulle.s32',
+ 'vmuleq.u8','vmulne.u8','vmulcs.u8','vmulhs.u8','vmulcc.u8','vmullo.u8','vmulmi.u8','vmulpl.u8','vmulvs.u8','vmulvc.u8','vmulhi.u8','vmulls.u8','vmulge.u8','vmullt.u8','vmulgt.u8','vmulle.u8',
+ 'vmuleq.u16','vmulne.u16','vmulcs.u16','vmulhs.u16','vmulcc.u16','vmullo.u16','vmulmi.u16','vmulpl.u16','vmulvs.u16','vmulvc.u16','vmulhi.u16','vmulls.u16','vmulge.u16','vmullt.u16','vmulgt.u16','vmulle.u16',
+ 'vmuleq.u32','vmulne.u32','vmulcs.u32','vmulhs.u32','vmulcc.u32','vmullo.u32','vmulmi.u32','vmulpl.u32','vmulvs.u32','vmulvc.u32','vmulhi.u32','vmulls.u32','vmulge.u32','vmullt.u32','vmulgt.u32','vmulle.u32',
+ 'vmuleq.i8','vmulne.i8','vmulcs.i8','vmulhs.i8','vmulcc.i8','vmullo.i8','vmulmi.i8','vmulpl.i8','vmulvs.i8','vmulvc.i8','vmulhi.i8','vmulls.i8','vmulge.i8','vmullt.i8','vmulgt.i8','vmulle.i8',
+ 'vmuleq.i16','vmulne.i16','vmulcs.i16','vmulhs.i16','vmulcc.i16','vmullo.i16','vmulmi.i16','vmulpl.i16','vmulvs.i16','vmulvc.i16','vmulhi.i16','vmulls.i16','vmulge.i16','vmullt.i16','vmulgt.i16','vmulle.i16',
+ 'vmuleq.i32','vmulne.i32','vmulcs.i32','vmulhs.i32','vmulcc.i32','vmullo.i32','vmulmi.i32','vmulpl.i32','vmulvs.i32','vmulvc.i32','vmulhi.i32','vmulls.i32','vmulge.i32','vmullt.i32','vmulgt.i32','vmulle.i32',
+ 'vmuleq.p8','vmulne.p8','vmulcs.p8','vmulhs.p8','vmulcc.p8','vmullo.p8','vmulmi.p8','vmulpl.p8','vmulvs.p8','vmulvc.p8','vmulhi.p8','vmulls.p8','vmulge.p8','vmullt.p8','vmulgt.p8','vmulle.p8',
+
+ 'vrshrneq.i16','vrshrnne.i16','vrshrncs.i16','vrshrnhs.i16','vrshrncc.i16','vrshrnlo.i16','vrshrnmi.i16','vrshrnpl.i16','vrshrnvs.i16','vrshrnvc.i16','vrshrnhi.i16','vrshrnls.i16','vrshrnge.i16','vrshrnlt.i16','vrshrngt.i16','vrshrnle.i16',
+ 'vrshrneq.i32','vrshrnne.i32','vrshrncs.i32','vrshrnhs.i32','vrshrncc.i32','vrshrnlo.i32','vrshrnmi.i32','vrshrnpl.i32','vrshrnvs.i32','vrshrnvc.i32','vrshrnhi.i32','vrshrnls.i32','vrshrnge.i32','vrshrnlt.i32','vrshrngt.i32','vrshrnle.i32',
+ 'vrshrneq.i64','vrshrnne.i64','vrshrncs.i64','vrshrnhs.i64','vrshrncc.i64','vrshrnlo.i64','vrshrnmi.i64','vrshrnpl.i64','vrshrnvs.i64','vrshrnvc.i64','vrshrnhi.i64','vrshrnls.i64','vrshrnge.i64','vrshrnlt.i64','vrshrngt.i64','vrshrnle.i64',
+
+ 'vshrneq.i16','vshrnne.i16','vshrncs.i16','vshrnhs.i16','vshrncc.i16','vshrnlo.i16','vshrnmi.i16','vshrnpl.i16','vshrnvs.i16','vshrnvc.i16','vshrnhi.i16','vshrnls.i16','vshrnge.i16','vshrnlt.i16','vshrngt.i16','vshrnle.i16',
+ 'vshrneq.i32','vshrnne.i32','vshrncs.i32','vshrnhs.i32','vshrncc.i32','vshrnlo.i32','vshrnmi.i32','vshrnpl.i32','vshrnvs.i32','vshrnvc.i32','vshrnhi.i32','vshrnls.i32','vshrnge.i32','vshrnlt.i32','vshrngt.i32','vshrnle.i32',
+ 'vshrneq.i64','vshrnne.i64','vshrncs.i64','vshrnhs.i64','vshrncc.i64','vshrnlo.i64','vshrnmi.i64','vshrnpl.i64','vshrnvs.i64','vshrnvc.i64','vshrnhi.i64','vshrnls.i64','vshrnge.i64','vshrnlt.i64','vshrngt.i64','vshrnle.i64',
+
+ 'vshleq.i8','vshlne.i8','vshlcs.i8','vshlhs.i8','vshlcc.i8','vshllo.i8','vshlmi.i8','vshlpl.i8','vshlvs.i8','vshlvc.i8','vshlhi.i8','vshlls.i8','vshlge.i8','vshllt.i8','vshlgt.i8','vshlle.i8',
+ 'vshleq.i16','vshlne.i16','vshlcs.i16','vshlhs.i16','vshlcc.i16','vshllo.i16','vshlmi.i16','vshlpl.i16','vshlvs.i16','vshlvc.i16','vshlhi.i16','vshlls.i16','vshlge.i16','vshllt.i16','vshlgt.i16','vshlle.i16',
+ 'vshleq.i32','vshlne.i32','vshlcs.i32','vshlhs.i32','vshlcc.i32','vshllo.i32','vshlmi.i32','vshlpl.i32','vshlvs.i32','vshlvc.i32','vshlhi.i32','vshlls.i32','vshlge.i32','vshllt.i32','vshlgt.i32','vshlle.i32',
+ 'vshleq.i64','vshlne.i64','vshlcs.i64','vshlhs.i64','vshlcc.i64','vshllo.i64','vshlmi.i64','vshlpl.i64','vshlvs.i64','vshlvc.i64','vshlhi.i64','vshlls.i64','vshlge.i64','vshllt.i64','vshlgt.i64','vshlle.i64',
+
+ 'vshlleq.i8','vshllne.i8','vshllcs.i8','vshllhs.i8','vshllcc.i8','vshlllo.i8','vshllmi.i8','vshllpl.i8','vshllvs.i8','vshllvc.i8','vshllhi.i8','vshllls.i8','vshllge.i8','vshlllt.i8','vshllgt.i8','vshllle.i8',
+ 'vshlleq.i16','vshllne.i16','vshllcs.i16','vshllhs.i16','vshllcc.i16','vshlllo.i16','vshllmi.i16','vshllpl.i16','vshllvs.i16','vshllvc.i16','vshllhi.i16','vshllls.i16','vshllge.i16','vshlllt.i16','vshllgt.i16','vshllle.i16',
+ 'vshlleq.i32','vshllne.i32','vshllcs.i32','vshllhs.i32','vshllcc.i32','vshlllo.i32','vshllmi.i32','vshllpl.i32','vshllvs.i32','vshllvc.i32','vshllhi.i32','vshllls.i32','vshllge.i32','vshlllt.i32','vshllgt.i32','vshllle.i32'
+ ),
+ /* Conditional NEON SIMD Signed Integer Instructions */
+ 32 => array(
+ 'vabaeq.s8','vabane.s8','vabacs.s8','vabahs.s8','vabacc.s8','vabalo.s8','vabami.s8','vabapl.s8','vabavs.s8','vabavc.s8','vabahi.s8','vabals.s8','vabage.s8','vabalt.s8','vabagt.s8','vabale.s8',
+ 'vabaeq.s16','vabane.s16','vabacs.s16','vabahs.s16','vabacc.s16','vabalo.s16','vabami.s16','vabapl.s16','vabavs.s16','vabavc.s16','vabahi.s16','vabals.s16','vabage.s16','vabalt.s16','vabagt.s16','vabale.s16',
+ 'vabaeq.s32','vabane.s32','vabacs.s32','vabahs.s32','vabacc.s32','vabalo.s32','vabami.s32','vabapl.s32','vabavs.s32','vabavc.s32','vabahi.s32','vabals.s32','vabage.s32','vabalt.s32','vabagt.s32','vabale.s32',
+
+ 'vabaleq.s8','vabalne.s8','vabalcs.s8','vabalhs.s8','vabalcc.s8','vaballo.s8','vabalmi.s8','vabalpl.s8','vabalvs.s8','vabalvc.s8','vabalhi.s8','vaballs.s8','vabalge.s8','vaballt.s8','vabalgt.s8','vaballe.s8',
+ 'vabaleq.s16','vabalne.s16','vabalcs.s16','vabalhs.s16','vabalcc.s16','vaballo.s16','vabalmi.s16','vabalpl.s16','vabalvs.s16','vabalvc.s16','vabalhi.s16','vaballs.s16','vabalge.s16','vaballt.s16','vabalgt.s16','vaballe.s16',
+ 'vabaleq.s32','vabalne.s32','vabalcs.s32','vabalhs.s32','vabalcc.s32','vaballo.s32','vabalmi.s32','vabalpl.s32','vabalvs.s32','vabalvc.s32','vabalhi.s32','vaballs.s32','vabalge.s32','vaballt.s32','vabalgt.s32','vaballe.s32',
+
+ 'vabdeq.s8','vabdne.s8','vabdcs.s8','vabdhs.s8','vabdcc.s8','vabdlo.s8','vabdmi.s8','vabdpl.s8','vabdvs.s8','vabdvc.s8','vabdhi.s8','vabdls.s8','vabdge.s8','vabdlt.s8','vabdgt.s8','vabdle.s8',
+ 'vabdeq.s16','vabdne.s16','vabdcs.s16','vabdhs.s16','vabdcc.s16','vabdlo.s16','vabdmi.s16','vabdpl.s16','vabdvs.s16','vabdvc.s16','vabdhi.s16','vabdls.s16','vabdge.s16','vabdlt.s16','vabdgt.s16','vabdle.s16',
+ 'vabdeq.s32','vabdne.s32','vabdcs.s32','vabdhs.s32','vabdcc.s32','vabdlo.s32','vabdmi.s32','vabdpl.s32','vabdvs.s32','vabdvc.s32','vabdhi.s32','vabdls.s32','vabdge.s32','vabdlt.s32','vabdgt.s32','vabdle.s32',
+
+ 'vabseq.s8','vabsne.s8','vabscs.s8','vabshs.s8','vabscc.s8','vabslo.s8','vabsmi.s8','vabspl.s8','vabsvs.s8','vabsvc.s8','vabshi.s8','vabsls.s8','vabsge.s8','vabslt.s8','vabsgt.s8','vabsle.s8',
+ 'vabseq.s16','vabsne.s16','vabscs.s16','vabshs.s16','vabscc.s16','vabslo.s16','vabsmi.s16','vabspl.s16','vabsvs.s16','vabsvc.s16','vabshi.s16','vabsls.s16','vabsge.s16','vabslt.s16','vabsgt.s16','vabsle.s16',
+ 'vabseq.s32','vabsne.s32','vabscs.s32','vabshs.s32','vabscc.s32','vabslo.s32','vabsmi.s32','vabspl.s32','vabsvs.s32','vabsvc.s32','vabshi.s32','vabsls.s32','vabsge.s32','vabslt.s32','vabsgt.s32','vabsle.s32',
+
+ 'vaddleq.s8','vaddlne.s8','vaddlcs.s8','vaddlhs.s8','vaddlcc.s8','vaddllo.s8','vaddlmi.s8','vaddlpl.s8','vaddlvs.s8','vaddlvc.s8','vaddlhi.s8','vaddlls.s8','vaddlge.s8','vaddllt.s8','vaddlgt.s8','vaddlle.s8',
+ 'vaddleq.s16','vaddlne.s16','vaddlcs.s16','vaddlhs.s16','vaddlcc.s16','vaddllo.s16','vaddlmi.s16','vaddlpl.s16','vaddlvs.s16','vaddlvc.s16','vaddlhi.s16','vaddlls.s16','vaddlge.s16','vaddllt.s16','vaddlgt.s16','vaddlle.s16',
+ 'vaddleq.s32','vaddlne.s32','vaddlcs.s32','vaddlhs.s32','vaddlcc.s32','vaddllo.s32','vaddlmi.s32','vaddlpl.s32','vaddlvs.s32','vaddlvc.s32','vaddlhi.s32','vaddlls.s32','vaddlge.s32','vaddllt.s32','vaddlgt.s32','vaddlle.s32',
+
+ 'vcgeeq.s8','vcgene.s8','vcgecs.s8','vcgehs.s8','vcgecc.s8','vcgelo.s8','vcgemi.s8','vcgepl.s8','vcgevs.s8','vcgevc.s8','vcgehi.s8','vcgels.s8','vcgege.s8','vcgelt.s8','vcgegt.s8','vcgele.s8',
+ 'vcgeeq.s16','vcgene.s16','vcgecs.s16','vcgehs.s16','vcgecc.s16','vcgelo.s16','vcgemi.s16','vcgepl.s16','vcgevs.s16','vcgevc.s16','vcgehi.s16','vcgels.s16','vcgege.s16','vcgelt.s16','vcgegt.s16','vcgele.s16',
+ 'vcgeeq.s32','vcgene.s32','vcgecs.s32','vcgehs.s32','vcgecc.s32','vcgelo.s32','vcgemi.s32','vcgepl.s32','vcgevs.s32','vcgevc.s32','vcgehi.s32','vcgels.s32','vcgege.s32','vcgelt.s32','vcgegt.s32','vcgele.s32',
+
+ 'vcleeq.s8','vclene.s8','vclecs.s8','vclehs.s8','vclecc.s8','vclelo.s8','vclemi.s8','vclepl.s8','vclevs.s8','vclevc.s8','vclehi.s8','vclels.s8','vclege.s8','vclelt.s8','vclegt.s8','vclele.s8',
+ 'vcleeq.s16','vclene.s16','vclecs.s16','vclehs.s16','vclecc.s16','vclelo.s16','vclemi.s16','vclepl.s16','vclevs.s16','vclevc.s16','vclehi.s16','vclels.s16','vclege.s16','vclelt.s16','vclegt.s16','vclele.s16',
+ 'vcleeq.s32','vclene.s32','vclecs.s32','vclehs.s32','vclecc.s32','vclelo.s32','vclemi.s32','vclepl.s32','vclevs.s32','vclevc.s32','vclehi.s32','vclels.s32','vclege.s32','vclelt.s32','vclegt.s32','vclele.s32',
+
+ 'vcgteq.s8','vcgtne.s8','vcgtcs.s8','vcgths.s8','vcgtcc.s8','vcgtlo.s8','vcgtmi.s8','vcgtpl.s8','vcgtvs.s8','vcgtvc.s8','vcgthi.s8','vcgtls.s8','vcgtge.s8','vcgtlt.s8','vcgtgt.s8','vcgtle.s8',
+ 'vcgteq.s16','vcgtne.s16','vcgtcs.s16','vcgths.s16','vcgtcc.s16','vcgtlo.s16','vcgtmi.s16','vcgtpl.s16','vcgtvs.s16','vcgtvc.s16','vcgthi.s16','vcgtls.s16','vcgtge.s16','vcgtlt.s16','vcgtgt.s16','vcgtle.s16',
+ 'vcgteq.s32','vcgtne.s32','vcgtcs.s32','vcgths.s32','vcgtcc.s32','vcgtlo.s32','vcgtmi.s32','vcgtpl.s32','vcgtvs.s32','vcgtvc.s32','vcgthi.s32','vcgtls.s32','vcgtge.s32','vcgtlt.s32','vcgtgt.s32','vcgtle.s32',
+
+ 'vclteq.s8','vcltne.s8','vcltcs.s8','vclths.s8','vcltcc.s8','vcltlo.s8','vcltmi.s8','vcltpl.s8','vcltvs.s8','vcltvc.s8','vclthi.s8','vcltls.s8','vcltge.s8','vcltlt.s8','vcltgt.s8','vcltle.s8',
+ 'vclteq.s16','vcltne.s16','vcltcs.s16','vclths.s16','vcltcc.s16','vcltlo.s16','vcltmi.s16','vcltpl.s16','vcltvs.s16','vcltvc.s16','vclthi.s16','vcltls.s16','vcltge.s16','vcltlt.s16','vcltgt.s16','vcltle.s16',
+ 'vclteq.s32','vcltne.s32','vcltcs.s32','vclths.s32','vcltcc.s32','vcltlo.s32','vcltmi.s32','vcltpl.s32','vcltvs.s32','vcltvc.s32','vclthi.s32','vcltls.s32','vcltge.s32','vcltlt.s32','vcltgt.s32','vcltle.s32',
+
+ 'vclseq.s8','vclsne.s8','vclscs.s8','vclshs.s8','vclscc.s8','vclslo.s8','vclsmi.s8','vclspl.s8','vclsvs.s8','vclsvc.s8','vclshi.s8','vclsls.s8','vclsge.s8','vclslt.s8','vclsgt.s8','vclsle.s8',
+ 'vclseq.s16','vclsne.s16','vclscs.s16','vclshs.s16','vclscc.s16','vclslo.s16','vclsmi.s16','vclspl.s16','vclsvs.s16','vclsvc.s16','vclshi.s16','vclsls.s16','vclsge.s16','vclslt.s16','vclsgt.s16','vclsle.s16',
+ 'vclseq.s32','vclsne.s32','vclscs.s32','vclshs.s32','vclscc.s32','vclslo.s32','vclsmi.s32','vclspl.s32','vclsvs.s32','vclsvc.s32','vclshi.s32','vclsls.s32','vclsge.s32','vclslt.s32','vclsgt.s32','vclsle.s32',
+
+ 'vaddweq.s8','vaddwne.s8','vaddwcs.s8','vaddwhs.s8','vaddwcc.s8','vaddwlo.s8','vaddwmi.s8','vaddwpl.s8','vaddwvs.s8','vaddwvc.s8','vaddwhi.s8','vaddwls.s8','vaddwge.s8','vaddwlt.s8','vaddwgt.s8','vaddwle.s8',
+ 'vaddweq.s16','vaddwne.s16','vaddwcs.s16','vaddwhs.s16','vaddwcc.s16','vaddwlo.s16','vaddwmi.s16','vaddwpl.s16','vaddwvs.s16','vaddwvc.s16','vaddwhi.s16','vaddwls.s16','vaddwge.s16','vaddwlt.s16','vaddwgt.s16','vaddwle.s16',
+ 'vaddweq.s32','vaddwne.s32','vaddwcs.s32','vaddwhs.s32','vaddwcc.s32','vaddwlo.s32','vaddwmi.s32','vaddwpl.s32','vaddwvs.s32','vaddwvc.s32','vaddwhi.s32','vaddwls.s32','vaddwge.s32','vaddwlt.s32','vaddwgt.s32','vaddwle.s32',
+
+ 'vhaddeq.s8','vhaddne.s8','vhaddcs.s8','vhaddhs.s8','vhaddcc.s8','vhaddlo.s8','vhaddmi.s8','vhaddpl.s8','vhaddvs.s8','vhaddvc.s8','vhaddhi.s8','vhaddls.s8','vhaddge.s8','vhaddlt.s8','vhaddgt.s8','vhaddle.s8',
+ 'vhaddeq.s16','vhaddne.s16','vhaddcs.s16','vhaddhs.s16','vhaddcc.s16','vhaddlo.s16','vhaddmi.s16','vhaddpl.s16','vhaddvs.s16','vhaddvc.s16','vhaddhi.s16','vhaddls.s16','vhaddge.s16','vhaddlt.s16','vhaddgt.s16','vhaddle.s16',
+ 'vhaddeq.s32','vhaddne.s32','vhaddcs.s32','vhaddhs.s32','vhaddcc.s32','vhaddlo.s32','vhaddmi.s32','vhaddpl.s32','vhaddvs.s32','vhaddvc.s32','vhaddhi.s32','vhaddls.s32','vhaddge.s32','vhaddlt.s32','vhaddgt.s32','vhaddle.s32',
+
+ 'vhsubeq.s8','vhsubne.s8','vhsubcs.s8','vhsubhs.s8','vhsubcc.s8','vhsublo.s8','vhsubmi.s8','vhsubpl.s8','vhsubvs.s8','vhsubvc.s8','vhsubhi.s8','vhsubls.s8','vhsubge.s8','vhsublt.s8','vhsubgt.s8','vhsuble.s8',
+ 'vhsubeq.s16','vhsubne.s16','vhsubcs.s16','vhsubhs.s16','vhsubcc.s16','vhsublo.s16','vhsubmi.s16','vhsubpl.s16','vhsubvs.s16','vhsubvc.s16','vhsubhi.s16','vhsubls.s16','vhsubge.s16','vhsublt.s16','vhsubgt.s16','vhsuble.s16',
+ 'vhsubeq.s32','vhsubne.s32','vhsubcs.s32','vhsubhs.s32','vhsubcc.s32','vhsublo.s32','vhsubmi.s32','vhsubpl.s32','vhsubvs.s32','vhsubvc.s32','vhsubhi.s32','vhsubls.s32','vhsubge.s32','vhsublt.s32','vhsubgt.s32','vhsuble.s32',
+
+ 'vmaxeq.s8','vmaxne.s8','vmaxcs.s8','vmaxhs.s8','vmaxcc.s8','vmaxlo.s8','vmaxmi.s8','vmaxpl.s8','vmaxvs.s8','vmaxvc.s8','vmaxhi.s8','vmaxls.s8','vmaxge.s8','vmaxlt.s8','vmaxgt.s8','vmaxle.s8',
+ 'vmaxeq.s16','vmaxne.s16','vmaxcs.s16','vmaxhs.s16','vmaxcc.s16','vmaxlo.s16','vmaxmi.s16','vmaxpl.s16','vmaxvs.s16','vmaxvc.s16','vmaxhi.s16','vmaxls.s16','vmaxge.s16','vmaxlt.s16','vmaxgt.s16','vmaxle.s16',
+ 'vmaxeq.s32','vmaxne.s32','vmaxcs.s32','vmaxhs.s32','vmaxcc.s32','vmaxlo.s32','vmaxmi.s32','vmaxpl.s32','vmaxvs.s32','vmaxvc.s32','vmaxhi.s32','vmaxls.s32','vmaxge.s32','vmaxlt.s32','vmaxgt.s32','vmaxle.s32',
+
+ 'vmineq.s8','vminne.s8','vmincs.s8','vminhs.s8','vmincc.s8','vminlo.s8','vminmi.s8','vminpl.s8','vminvs.s8','vminvc.s8','vminhi.s8','vminls.s8','vminge.s8','vminlt.s8','vmingt.s8','vminle.s8',
+ 'vmineq.s16','vminne.s16','vmincs.s16','vminhs.s16','vmincc.s16','vminlo.s16','vminmi.s16','vminpl.s16','vminvs.s16','vminvc.s16','vminhi.s16','vminls.s16','vminge.s16','vminlt.s16','vmingt.s16','vminle.s16',
+ 'vmineq.s32','vminne.s32','vmincs.s32','vminhs.s32','vmincc.s32','vminlo.s32','vminmi.s32','vminpl.s32','vminvs.s32','vminvc.s32','vminhi.s32','vminls.s32','vminge.s32','vminlt.s32','vmingt.s32','vminle.s32',
+
+ 'vmlaleq.s8','vmlalne.s8','vmlalcs.s8','vmlalhs.s8','vmlalcc.s8','vmlallo.s8','vmlalmi.s8','vmlalpl.s8','vmlalvs.s8','vmlalvc.s8','vmlalhi.s8','vmlalls.s8','vmlalge.s8','vmlallt.s8','vmlalgt.s8','vmlalle.s8',
+ 'vmlaleq.s16','vmlalne.s16','vmlalcs.s16','vmlalhs.s16','vmlalcc.s16','vmlallo.s16','vmlalmi.s16','vmlalpl.s16','vmlalvs.s16','vmlalvc.s16','vmlalhi.s16','vmlalls.s16','vmlalge.s16','vmlallt.s16','vmlalgt.s16','vmlalle.s16',
+ 'vmlaleq.s32','vmlalne.s32','vmlalcs.s32','vmlalhs.s32','vmlalcc.s32','vmlallo.s32','vmlalmi.s32','vmlalpl.s32','vmlalvs.s32','vmlalvc.s32','vmlalhi.s32','vmlalls.s32','vmlalge.s32','vmlallt.s32','vmlalgt.s32','vmlalle.s32',
+
+ 'vmlsleq.s8','vmlslne.s8','vmlslcs.s8','vmlslhs.s8','vmlslcc.s8','vmlsllo.s8','vmlslmi.s8','vmlslpl.s8','vmlslvs.s8','vmlslvc.s8','vmlslhi.s8','vmlslls.s8','vmlslge.s8','vmlsllt.s8','vmlslgt.s8','vmlslle.s8',
+ 'vmlsleq.s16','vmlslne.s16','vmlslcs.s16','vmlslhs.s16','vmlslcc.s16','vmlsllo.s16','vmlslmi.s16','vmlslpl.s16','vmlslvs.s16','vmlslvc.s16','vmlslhi.s16','vmlslls.s16','vmlslge.s16','vmlsllt.s16','vmlslgt.s16','vmlslle.s16',
+ 'vmlsleq.s32','vmlslne.s32','vmlslcs.s32','vmlslhs.s32','vmlslcc.s32','vmlsllo.s32','vmlslmi.s32','vmlslpl.s32','vmlslvs.s32','vmlslvc.s32','vmlslhi.s32','vmlslls.s32','vmlslge.s32','vmlsllt.s32','vmlslgt.s32','vmlslle.s32',
+
+ 'vnegeq.s8','vnegne.s8','vnegcs.s8','vneghs.s8','vnegcc.s8','vneglo.s8','vnegmi.s8','vnegpl.s8','vnegvs.s8','vnegvc.s8','vneghi.s8','vnegls.s8','vnegge.s8','vneglt.s8','vneggt.s8','vnegle.s8',
+ 'vnegeq.s16','vnegne.s16','vnegcs.s16','vneghs.s16','vnegcc.s16','vneglo.s16','vnegmi.s16','vnegpl.s16','vnegvs.s16','vnegvc.s16','vneghi.s16','vnegls.s16','vnegge.s16','vneglt.s16','vneggt.s16','vnegle.s16',
+ 'vnegeq.s32','vnegne.s32','vnegcs.s32','vneghs.s32','vnegcc.s32','vneglo.s32','vnegmi.s32','vnegpl.s32','vnegvs.s32','vnegvc.s32','vneghi.s32','vnegls.s32','vnegge.s32','vneglt.s32','vneggt.s32','vnegle.s32',
+
+ 'vpadaleq.s8','vpadalne.s8','vpadalcs.s8','vpadalhs.s8','vpadalcc.s8','vpadallo.s8','vpadalmi.s8','vpadalpl.s8','vpadalvs.s8','vpadalvc.s8','vpadalhi.s8','vpadalls.s8','vpadalge.s8','vpadallt.s8','vpadalgt.s8','vpadalle.s8',
+ 'vpadaleq.s16','vpadalne.s16','vpadalcs.s16','vpadalhs.s16','vpadalcc.s16','vpadallo.s16','vpadalmi.s16','vpadalpl.s16','vpadalvs.s16','vpadalvc.s16','vpadalhi.s16','vpadalls.s16','vpadalge.s16','vpadallt.s16','vpadalgt.s16','vpadalle.s16',
+ 'vpadaleq.s32','vpadalne.s32','vpadalcs.s32','vpadalhs.s32','vpadalcc.s32','vpadallo.s32','vpadalmi.s32','vpadalpl.s32','vpadalvs.s32','vpadalvc.s32','vpadalhi.s32','vpadalls.s32','vpadalge.s32','vpadallt.s32','vpadalgt.s32','vpadalle.s32',
+
+ 'vmovleq.s8','vmovlne.s8','vmovlcs.s8','vmovlhs.s8','vmovlcc.s8','vmovllo.s8','vmovlmi.s8','vmovlpl.s8','vmovlvs.s8','vmovlvc.s8','vmovlhi.s8','vmovlls.s8','vmovlge.s8','vmovllt.s8','vmovlgt.s8','vmovlle.s8',
+ 'vmovleq.s16','vmovlne.s16','vmovlcs.s16','vmovlhs.s16','vmovlcc.s16','vmovllo.s16','vmovlmi.s16','vmovlpl.s16','vmovlvs.s16','vmovlvc.s16','vmovlhi.s16','vmovlls.s16','vmovlge.s16','vmovllt.s16','vmovlgt.s16','vmovlle.s16',
+ 'vmovleq.s32','vmovlne.s32','vmovlcs.s32','vmovlhs.s32','vmovlcc.s32','vmovllo.s32','vmovlmi.s32','vmovlpl.s32','vmovlvs.s32','vmovlvc.s32','vmovlhi.s32','vmovlls.s32','vmovlge.s32','vmovllt.s32','vmovlgt.s32','vmovlle.s32',
+
+ 'vmulleq.s8','vmullne.s8','vmullcs.s8','vmullhs.s8','vmullcc.s8','vmulllo.s8','vmullmi.s8','vmullpl.s8','vmullvs.s8','vmullvc.s8','vmullhi.s8','vmullls.s8','vmullge.s8','vmulllt.s8','vmullgt.s8','vmullle.s8',
+ 'vmulleq.s16','vmullne.s16','vmullcs.s16','vmullhs.s16','vmullcc.s16','vmulllo.s16','vmullmi.s16','vmullpl.s16','vmullvs.s16','vmullvc.s16','vmullhi.s16','vmullls.s16','vmullge.s16','vmulllt.s16','vmullgt.s16','vmullle.s16',
+ 'vmulleq.s32','vmullne.s32','vmullcs.s32','vmullhs.s32','vmullcc.s32','vmulllo.s32','vmullmi.s32','vmullpl.s32','vmullvs.s32','vmullvc.s32','vmullhi.s32','vmullls.s32','vmullge.s32','vmulllt.s32','vmullgt.s32','vmullle.s32',
+
+ 'vpaddleq.s8','vpaddlne.s8','vpaddlcs.s8','vpaddlhs.s8','vpaddlcc.s8','vpaddllo.s8','vpaddlmi.s8','vpaddlpl.s8','vpaddlvs.s8','vpaddlvc.s8','vpaddlhi.s8','vpaddlls.s8','vpaddlge.s8','vpaddllt.s8','vpaddlgt.s8','vpaddlle.s8',
+ 'vpaddleq.s16','vpaddlne.s16','vpaddlcs.s16','vpaddlhs.s16','vpaddlcc.s16','vpaddllo.s16','vpaddlmi.s16','vpaddlpl.s16','vpaddlvs.s16','vpaddlvc.s16','vpaddlhi.s16','vpaddlls.s16','vpaddlge.s16','vpaddllt.s16','vpaddlgt.s16','vpaddlle.s16',
+ 'vpaddleq.s32','vpaddlne.s32','vpaddlcs.s32','vpaddlhs.s32','vpaddlcc.s32','vpaddllo.s32','vpaddlmi.s32','vpaddlpl.s32','vpaddlvs.s32','vpaddlvc.s32','vpaddlhi.s32','vpaddlls.s32','vpaddlge.s32','vpaddllt.s32','vpaddlgt.s32','vpaddlle.s32',
+
+ 'vpmaxeq.s8','vpmaxne.s8','vpmaxcs.s8','vpmaxhs.s8','vpmaxcc.s8','vpmaxlo.s8','vpmaxmi.s8','vpmaxpl.s8','vpmaxvs.s8','vpmaxvc.s8','vpmaxhi.s8','vpmaxls.s8','vpmaxge.s8','vpmaxlt.s8','vpmaxgt.s8','vpmaxle.s8',
+ 'vpmaxeq.s16','vpmaxne.s16','vpmaxcs.s16','vpmaxhs.s16','vpmaxcc.s16','vpmaxlo.s16','vpmaxmi.s16','vpmaxpl.s16','vpmaxvs.s16','vpmaxvc.s16','vpmaxhi.s16','vpmaxls.s16','vpmaxge.s16','vpmaxlt.s16','vpmaxgt.s16','vpmaxle.s16',
+ 'vpmaxeq.s32','vpmaxne.s32','vpmaxcs.s32','vpmaxhs.s32','vpmaxcc.s32','vpmaxlo.s32','vpmaxmi.s32','vpmaxpl.s32','vpmaxvs.s32','vpmaxvc.s32','vpmaxhi.s32','vpmaxls.s32','vpmaxge.s32','vpmaxlt.s32','vpmaxgt.s32','vpmaxle.s32',
+
+ 'vpmineq.s8','vpminne.s8','vpmincs.s8','vpminhs.s8','vpmincc.s8','vpminlo.s8','vpminmi.s8','vpminpl.s8','vpminvs.s8','vpminvc.s8','vpminhi.s8','vpminls.s8','vpminge.s8','vpminlt.s8','vpmingt.s8','vpminle.s8',
+ 'vpmineq.s16','vpminne.s16','vpmincs.s16','vpminhs.s16','vpmincc.s16','vpminlo.s16','vpminmi.s16','vpminpl.s16','vpminvs.s16','vpminvc.s16','vpminhi.s16','vpminls.s16','vpminge.s16','vpminlt.s16','vpmingt.s16','vpminle.s16',
+ 'vpmineq.s32','vpminne.s32','vpmincs.s32','vpminhs.s32','vpmincc.s32','vpminlo.s32','vpminmi.s32','vpminpl.s32','vpminvs.s32','vpminvc.s32','vpminhi.s32','vpminls.s32','vpminge.s32','vpminlt.s32','vpmingt.s32','vpminle.s32',
+
+ 'vqabseq.s8','vqabsne.s8','vqabscs.s8','vqabshs.s8','vqabscc.s8','vqabslo.s8','vqabsmi.s8','vqabspl.s8','vqabsvs.s8','vqabsvc.s8','vqabshi.s8','vqabsls.s8','vqabsge.s8','vqabslt.s8','vqabsgt.s8','vqabsle.s8',
+ 'vqabseq.s16','vqabsne.s16','vqabscs.s16','vqabshs.s16','vqabscc.s16','vqabslo.s16','vqabsmi.s16','vqabspl.s16','vqabsvs.s16','vqabsvc.s16','vqabshi.s16','vqabsls.s16','vqabsge.s16','vqabslt.s16','vqabsgt.s16','vqabsle.s16',
+ 'vqabseq.s32','vqabsne.s32','vqabscs.s32','vqabshs.s32','vqabscc.s32','vqabslo.s32','vqabsmi.s32','vqabspl.s32','vqabsvs.s32','vqabsvc.s32','vqabshi.s32','vqabsls.s32','vqabsge.s32','vqabslt.s32','vqabsgt.s32','vqabsle.s32',
+
+ 'vqaddeq.s8','vqaddne.s8','vqaddcs.s8','vqaddhs.s8','vqaddcc.s8','vqaddlo.s8','vqaddmi.s8','vqaddpl.s8','vqaddvs.s8','vqaddvc.s8','vqaddhi.s8','vqaddls.s8','vqaddge.s8','vqaddlt.s8','vqaddgt.s8','vqaddle.s8',
+ 'vqaddeq.s16','vqaddne.s16','vqaddcs.s16','vqaddhs.s16','vqaddcc.s16','vqaddlo.s16','vqaddmi.s16','vqaddpl.s16','vqaddvs.s16','vqaddvc.s16','vqaddhi.s16','vqaddls.s16','vqaddge.s16','vqaddlt.s16','vqaddgt.s16','vqaddle.s16',
+ 'vqaddeq.s32','vqaddne.s32','vqaddcs.s32','vqaddhs.s32','vqaddcc.s32','vqaddlo.s32','vqaddmi.s32','vqaddpl.s32','vqaddvs.s32','vqaddvc.s32','vqaddhi.s32','vqaddls.s32','vqaddge.s32','vqaddlt.s32','vqaddgt.s32','vqaddle.s32',
+ 'vqaddeq.s64','vqaddne.s64','vqaddcs.s64','vqaddhs.s64','vqaddcc.s64','vqaddlo.s64','vqaddmi.s64','vqaddpl.s64','vqaddvs.s64','vqaddvc.s64','vqaddhi.s64','vqaddls.s64','vqaddge.s64','vqaddlt.s64','vqaddgt.s64','vqaddle.s64',
+
+ 'vqdmlaleq.s16','vqdmlalne.s16','vqdmlalcs.s16','vqdmlalhs.s16','vqdmlalcc.s16','vqdmlallo.s16','vqdmlalmi.s16','vqdmlalpl.s16','vqdmlalvs.s16','vqdmlalvc.s16','vqdmlalhi.s16','vqdmlalls.s16','vqdmlalge.s16','vqdmlallt.s16','vqdmlalgt.s16','vqdmlalle.s16',
+ 'vqdmlaleq.s32','vqdmlalne.s32','vqdmlalcs.s32','vqdmlalhs.s32','vqdmlalcc.s32','vqdmlallo.s32','vqdmlalmi.s32','vqdmlalpl.s32','vqdmlalvs.s32','vqdmlalvc.s32','vqdmlalhi.s32','vqdmlalls.s32','vqdmlalge.s32','vqdmlallt.s32','vqdmlalgt.s32','vqdmlalle.s32',
+
+ 'vqdmlsleq.s16','vqdmlslne.s16','vqdmlslcs.s16','vqdmlslhs.s16','vqdmlslcc.s16','vqdmlsllo.s16','vqdmlslmi.s16','vqdmlslpl.s16','vqdmlslvs.s16','vqdmlslvc.s16','vqdmlslhi.s16','vqdmlslls.s16','vqdmlslge.s16','vqdmlsllt.s16','vqdmlslgt.s16','vqdmlslle.s16',
+ 'vqdmlsleq.s32','vqdmlslne.s32','vqdmlslcs.s32','vqdmlslhs.s32','vqdmlslcc.s32','vqdmlsllo.s32','vqdmlslmi.s32','vqdmlslpl.s32','vqdmlslvs.s32','vqdmlslvc.s32','vqdmlslhi.s32','vqdmlslls.s32','vqdmlslge.s32','vqdmlsllt.s32','vqdmlslgt.s32','vqdmlslle.s32',
+
+ 'vqdmulheq.s16','vqdmulhne.s16','vqdmulhcs.s16','vqdmulhhs.s16','vqdmulhcc.s16','vqdmulhlo.s16','vqdmulhmi.s16','vqdmulhpl.s16','vqdmulhvs.s16','vqdmulhvc.s16','vqdmulhhi.s16','vqdmulhls.s16','vqdmulhge.s16','vqdmulhlt.s16','vqdmulhgt.s16','vqdmulhle.s16',
+ 'vqdmulheq.s32','vqdmulhne.s32','vqdmulhcs.s32','vqdmulhhs.s32','vqdmulhcc.s32','vqdmulhlo.s32','vqdmulhmi.s32','vqdmulhpl.s32','vqdmulhvs.s32','vqdmulhvc.s32','vqdmulhhi.s32','vqdmulhls.s32','vqdmulhge.s32','vqdmulhlt.s32','vqdmulhgt.s32','vqdmulhle.s32',
+
+ 'vqdmulleq.s16','vqdmullne.s16','vqdmullcs.s16','vqdmullhs.s16','vqdmullcc.s16','vqdmulllo.s16','vqdmullmi.s16','vqdmullpl.s16','vqdmullvs.s16','vqdmullvc.s16','vqdmullhi.s16','vqdmullls.s16','vqdmullge.s16','vqdmulllt.s16','vqdmullgt.s16','vqdmullle.s16',
+ 'vqdmulleq.s32','vqdmullne.s32','vqdmullcs.s32','vqdmullhs.s32','vqdmullcc.s32','vqdmulllo.s32','vqdmullmi.s32','vqdmullpl.s32','vqdmullvs.s32','vqdmullvc.s32','vqdmullhi.s32','vqdmullls.s32','vqdmullge.s32','vqdmulllt.s32','vqdmullgt.s32','vqdmullle.s32',
+
+ 'vqmovneq.s16','vqmovnne.s16','vqmovncs.s16','vqmovnhs.s16','vqmovncc.s16','vqmovnlo.s16','vqmovnmi.s16','vqmovnpl.s16','vqmovnvs.s16','vqmovnvc.s16','vqmovnhi.s16','vqmovnls.s16','vqmovnge.s16','vqmovnlt.s16','vqmovngt.s16','vqmovnle.s16',
+ 'vqmovneq.s32','vqmovnne.s32','vqmovncs.s32','vqmovnhs.s32','vqmovncc.s32','vqmovnlo.s32','vqmovnmi.s32','vqmovnpl.s32','vqmovnvs.s32','vqmovnvc.s32','vqmovnhi.s32','vqmovnls.s32','vqmovnge.s32','vqmovnlt.s32','vqmovngt.s32','vqmovnle.s32',
+ 'vqmovneq.s64','vqmovnne.s64','vqmovncs.s64','vqmovnhs.s64','vqmovncc.s64','vqmovnlo.s64','vqmovnmi.s64','vqmovnpl.s64','vqmovnvs.s64','vqmovnvc.s64','vqmovnhi.s64','vqmovnls.s64','vqmovnge.s64','vqmovnlt.s64','vqmovngt.s64','vqmovnle.s64',
+
+ 'vqmovuneq.s16','vqmovunne.s16','vqmovuncs.s16','vqmovunhs.s16','vqmovuncc.s16','vqmovunlo.s16','vqmovunmi.s16','vqmovunpl.s16','vqmovunvs.s16','vqmovunvc.s16','vqmovunhi.s16','vqmovunls.s16','vqmovunge.s16','vqmovunlt.s16','vqmovungt.s16','vqmovunle.s16',
+ 'vqmovuneq.s32','vqmovunne.s32','vqmovuncs.s32','vqmovunhs.s32','vqmovuncc.s32','vqmovunlo.s32','vqmovunmi.s32','vqmovunpl.s32','vqmovunvs.s32','vqmovunvc.s32','vqmovunhi.s32','vqmovunls.s32','vqmovunge.s32','vqmovunlt.s32','vqmovungt.s32','vqmovunle.s32',
+ 'vqmovuneq.s64','vqmovunne.s64','vqmovuncs.s64','vqmovunhs.s64','vqmovuncc.s64','vqmovunlo.s64','vqmovunmi.s64','vqmovunpl.s64','vqmovunvs.s64','vqmovunvc.s64','vqmovunhi.s64','vqmovunls.s64','vqmovunge.s64','vqmovunlt.s64','vqmovungt.s64','vqmovunle.s64',
+
+ 'vqnegeq.s8','vqnegne.s8','vqnegcs.s8','vqneghs.s8','vqnegcc.s8','vqneglo.s8','vqnegmi.s8','vqnegpl.s8','vqnegvs.s8','vqnegvc.s8','vqneghi.s8','vqnegls.s8','vqnegge.s8','vqneglt.s8','vqneggt.s8','vqnegle.s8',
+ 'vqnegeq.s16','vqnegne.s16','vqnegcs.s16','vqneghs.s16','vqnegcc.s16','vqneglo.s16','vqnegmi.s16','vqnegpl.s16','vqnegvs.s16','vqnegvc.s16','vqneghi.s16','vqnegls.s16','vqnegge.s16','vqneglt.s16','vqneggt.s16','vqnegle.s16',
+ 'vqnegeq.s32','vqnegne.s32','vqnegcs.s32','vqneghs.s32','vqnegcc.s32','vqneglo.s32','vqnegmi.s32','vqnegpl.s32','vqnegvs.s32','vqnegvc.s32','vqneghi.s32','vqnegls.s32','vqnegge.s32','vqneglt.s32','vqneggt.s32','vqnegle.s32',
+
+ 'vqrdmulheq.s16','vqrdmulhne.s16','vqrdmulhcs.s16','vqrdmulhhs.s16','vqrdmulhcc.s16','vqrdmulhlo.s16','vqrdmulhmi.s16','vqrdmulhpl.s16','vqrdmulhvs.s16','vqrdmulhvc.s16','vqrdmulhhi.s16','vqrdmulhls.s16','vqrdmulhge.s16','vqrdmulhlt.s16','vqrdmulhgt.s16','vqrdmulhle.s16',
+ 'vqrdmulheq.s32','vqrdmulhne.s32','vqrdmulhcs.s32','vqrdmulhhs.s32','vqrdmulhcc.s32','vqrdmulhlo.s32','vqrdmulhmi.s32','vqrdmulhpl.s32','vqrdmulhvs.s32','vqrdmulhvc.s32','vqrdmulhhi.s32','vqrdmulhls.s32','vqrdmulhge.s32','vqrdmulhlt.s32','vqrdmulhgt.s32','vqrdmulhle.s32',
+
+ 'vqrshleq.s8','vqrshlne.s8','vqrshlcs.s8','vqrshlhs.s8','vqrshlcc.s8','vqrshllo.s8','vqrshlmi.s8','vqrshlpl.s8','vqrshlvs.s8','vqrshlvc.s8','vqrshlhi.s8','vqrshlls.s8','vqrshlge.s8','vqrshllt.s8','vqrshlgt.s8','vqrshlle.s8',
+ 'vqrshleq.s16','vqrshlne.s16','vqrshlcs.s16','vqrshlhs.s16','vqrshlcc.s16','vqrshllo.s16','vqrshlmi.s16','vqrshlpl.s16','vqrshlvs.s16','vqrshlvc.s16','vqrshlhi.s16','vqrshlls.s16','vqrshlge.s16','vqrshllt.s16','vqrshlgt.s16','vqrshlle.s16',
+ 'vqrshleq.s32','vqrshlne.s32','vqrshlcs.s32','vqrshlhs.s32','vqrshlcc.s32','vqrshllo.s32','vqrshlmi.s32','vqrshlpl.s32','vqrshlvs.s32','vqrshlvc.s32','vqrshlhi.s32','vqrshlls.s32','vqrshlge.s32','vqrshllt.s32','vqrshlgt.s32','vqrshlle.s32',
+ 'vqrshleq.s64','vqrshlne.s64','vqrshlcs.s64','vqrshlhs.s64','vqrshlcc.s64','vqrshllo.s64','vqrshlmi.s64','vqrshlpl.s64','vqrshlvs.s64','vqrshlvc.s64','vqrshlhi.s64','vqrshlls.s64','vqrshlge.s64','vqrshllt.s64','vqrshlgt.s64','vqrshlle.s64',
+
+ 'vqrshrneq.s16','vqrshrnne.s16','vqrshrncs.s16','vqrshrnhs.s16','vqrshrncc.s16','vqrshrnlo.s16','vqrshrnmi.s16','vqrshrnpl.s16','vqrshrnvs.s16','vqrshrnvc.s16','vqrshrnhi.s16','vqrshrnls.s16','vqrshrnge.s16','vqrshrnlt.s16','vqrshrngt.s16','vqrshrnle.s16',
+ 'vqrshrneq.s32','vqrshrnne.s32','vqrshrncs.s32','vqrshrnhs.s32','vqrshrncc.s32','vqrshrnlo.s32','vqrshrnmi.s32','vqrshrnpl.s32','vqrshrnvs.s32','vqrshrnvc.s32','vqrshrnhi.s32','vqrshrnls.s32','vqrshrnge.s32','vqrshrnlt.s32','vqrshrngt.s32','vqrshrnle.s32',
+ 'vqrshrneq.s64','vqrshrnne.s64','vqrshrncs.s64','vqrshrnhs.s64','vqrshrncc.s64','vqrshrnlo.s64','vqrshrnmi.s64','vqrshrnpl.s64','vqrshrnvs.s64','vqrshrnvc.s64','vqrshrnhi.s64','vqrshrnls.s64','vqrshrnge.s64','vqrshrnlt.s64','vqrshrngt.s64','vqrshrnle.s64',
+
+ 'vqrshruneq.s16','vqrshrunne.s16','vqrshruncs.s16','vqrshrunhs.s16','vqrshruncc.s16','vqrshrunlo.s16','vqrshrunmi.s16','vqrshrunpl.s16','vqrshrunvs.s16','vqrshrunvc.s16','vqrshrunhi.s16','vqrshrunls.s16','vqrshrunge.s16','vqrshrunlt.s16','vqrshrungt.s16','vqrshrunle.s16',
+ 'vqrshruneq.s32','vqrshrunne.s32','vqrshruncs.s32','vqrshrunhs.s32','vqrshruncc.s32','vqrshrunlo.s32','vqrshrunmi.s32','vqrshrunpl.s32','vqrshrunvs.s32','vqrshrunvc.s32','vqrshrunhi.s32','vqrshrunls.s32','vqrshrunge.s32','vqrshrunlt.s32','vqrshrungt.s32','vqrshrunle.s32',
+ 'vqrshruneq.s64','vqrshrunne.s64','vqrshruncs.s64','vqrshrunhs.s64','vqrshruncc.s64','vqrshrunlo.s64','vqrshrunmi.s64','vqrshrunpl.s64','vqrshrunvs.s64','vqrshrunvc.s64','vqrshrunhi.s64','vqrshrunls.s64','vqrshrunge.s64','vqrshrunlt.s64','vqrshrungt.s64','vqrshrunle.s64',
+
+ 'vqshleq.s8','vqshlne.s8','vqshlcs.s8','vqshlhs.s8','vqshlcc.s8','vqshllo.s8','vqshlmi.s8','vqshlpl.s8','vqshlvs.s8','vqshlvc.s8','vqshlhi.s8','vqshlls.s8','vqshlge.s8','vqshllt.s8','vqshlgt.s8','vqshlle.s8',
+ 'vqshleq.s16','vqshlne.s16','vqshlcs.s16','vqshlhs.s16','vqshlcc.s16','vqshllo.s16','vqshlmi.s16','vqshlpl.s16','vqshlvs.s16','vqshlvc.s16','vqshlhi.s16','vqshlls.s16','vqshlge.s16','vqshllt.s16','vqshlgt.s16','vqshlle.s16',
+ 'vqshleq.s32','vqshlne.s32','vqshlcs.s32','vqshlhs.s32','vqshlcc.s32','vqshllo.s32','vqshlmi.s32','vqshlpl.s32','vqshlvs.s32','vqshlvc.s32','vqshlhi.s32','vqshlls.s32','vqshlge.s32','vqshllt.s32','vqshlgt.s32','vqshlle.s32',
+ 'vqshleq.s64','vqshlne.s64','vqshlcs.s64','vqshlhs.s64','vqshlcc.s64','vqshllo.s64','vqshlmi.s64','vqshlpl.s64','vqshlvs.s64','vqshlvc.s64','vqshlhi.s64','vqshlls.s64','vqshlge.s64','vqshllt.s64','vqshlgt.s64','vqshlle.s64',
+
+ 'vqshlueq.s8','vqshlune.s8','vqshlucs.s8','vqshluhs.s8','vqshlucc.s8','vqshlulo.s8','vqshlumi.s8','vqshlupl.s8','vqshluvs.s8','vqshluvc.s8','vqshluhi.s8','vqshluls.s8','vqshluge.s8','vqshlult.s8','vqshlugt.s8','vqshlule.s8',
+ 'vqshlueq.s16','vqshlune.s16','vqshlucs.s16','vqshluhs.s16','vqshlucc.s16','vqshlulo.s16','vqshlumi.s16','vqshlupl.s16','vqshluvs.s16','vqshluvc.s16','vqshluhi.s16','vqshluls.s16','vqshluge.s16','vqshlult.s16','vqshlugt.s16','vqshlule.s16',
+ 'vqshlueq.s32','vqshlune.s32','vqshlucs.s32','vqshluhs.s32','vqshlucc.s32','vqshlulo.s32','vqshlumi.s32','vqshlupl.s32','vqshluvs.s32','vqshluvc.s32','vqshluhi.s32','vqshluls.s32','vqshluge.s32','vqshlult.s32','vqshlugt.s32','vqshlule.s32',
+ 'vqshlueq.s64','vqshlune.s64','vqshlucs.s64','vqshluhs.s64','vqshlucc.s64','vqshlulo.s64','vqshlumi.s64','vqshlupl.s64','vqshluvs.s64','vqshluvc.s64','vqshluhi.s64','vqshluls.s64','vqshluge.s64','vqshlult.s64','vqshlugt.s64','vqshlule.s64',
+
+ 'vqshrneq.s16','vqshrnne.s16','vqshrncs.s16','vqshrnhs.s16','vqshrncc.s16','vqshrnlo.s16','vqshrnmi.s16','vqshrnpl.s16','vqshrnvs.s16','vqshrnvc.s16','vqshrnhi.s16','vqshrnls.s16','vqshrnge.s16','vqshrnlt.s16','vqshrngt.s16','vqshrnle.s16',
+ 'vqshrneq.s32','vqshrnne.s32','vqshrncs.s32','vqshrnhs.s32','vqshrncc.s32','vqshrnlo.s32','vqshrnmi.s32','vqshrnpl.s32','vqshrnvs.s32','vqshrnvc.s32','vqshrnhi.s32','vqshrnls.s32','vqshrnge.s32','vqshrnlt.s32','vqshrngt.s32','vqshrnle.s32',
+ 'vqshrneq.s64','vqshrnne.s64','vqshrncs.s64','vqshrnhs.s64','vqshrncc.s64','vqshrnlo.s64','vqshrnmi.s64','vqshrnpl.s64','vqshrnvs.s64','vqshrnvc.s64','vqshrnhi.s64','vqshrnls.s64','vqshrnge.s64','vqshrnlt.s64','vqshrngt.s64','vqshrnle.s64',
+
+ 'vqshruneq.s16','vqshrunne.s16','vqshruncs.s16','vqshrunhs.s16','vqshruncc.s16','vqshrunlo.s16','vqshrunmi.s16','vqshrunpl.s16','vqshrunvs.s16','vqshrunvc.s16','vqshrunhi.s16','vqshrunls.s16','vqshrunge.s16','vqshrunlt.s16','vqshrungt.s16','vqshrunle.s16',
+ 'vqshruneq.s32','vqshrunne.s32','vqshruncs.s32','vqshrunhs.s32','vqshruncc.s32','vqshrunlo.s32','vqshrunmi.s32','vqshrunpl.s32','vqshrunvs.s32','vqshrunvc.s32','vqshrunhi.s32','vqshrunls.s32','vqshrunge.s32','vqshrunlt.s32','vqshrungt.s32','vqshrunle.s32',
+ 'vqshruneq.s64','vqshrunne.s64','vqshruncs.s64','vqshrunhs.s64','vqshruncc.s64','vqshrunlo.s64','vqshrunmi.s64','vqshrunpl.s64','vqshrunvs.s64','vqshrunvc.s64','vqshrunhi.s64','vqshrunls.s64','vqshrunge.s64','vqshrunlt.s64','vqshrungt.s64','vqshrunle.s64',
+
+ 'vqsubeq.s8','vqsubne.s8','vqsubcs.s8','vqsubhs.s8','vqsubcc.s8','vqsublo.s8','vqsubmi.s8','vqsubpl.s8','vqsubvs.s8','vqsubvc.s8','vqsubhi.s8','vqsubls.s8','vqsubge.s8','vqsublt.s8','vqsubgt.s8','vqsuble.s8',
+ 'vqsubeq.s16','vqsubne.s16','vqsubcs.s16','vqsubhs.s16','vqsubcc.s16','vqsublo.s16','vqsubmi.s16','vqsubpl.s16','vqsubvs.s16','vqsubvc.s16','vqsubhi.s16','vqsubls.s16','vqsubge.s16','vqsublt.s16','vqsubgt.s16','vqsuble.s16',
+ 'vqsubeq.s32','vqsubne.s32','vqsubcs.s32','vqsubhs.s32','vqsubcc.s32','vqsublo.s32','vqsubmi.s32','vqsubpl.s32','vqsubvs.s32','vqsubvc.s32','vqsubhi.s32','vqsubls.s32','vqsubge.s32','vqsublt.s32','vqsubgt.s32','vqsuble.s32',
+ 'vqsubeq.s64','vqsubne.s64','vqsubcs.s64','vqsubhs.s64','vqsubcc.s64','vqsublo.s64','vqsubmi.s64','vqsubpl.s64','vqsubvs.s64','vqsubvc.s64','vqsubhi.s64','vqsubls.s64','vqsubge.s64','vqsublt.s64','vqsubgt.s64','vqsuble.s64',
+
+ 'vrhaddeq.s8','vrhaddne.s8','vrhaddcs.s8','vrhaddhs.s8','vrhaddcc.s8','vrhaddlo.s8','vrhaddmi.s8','vrhaddpl.s8','vrhaddvs.s8','vrhaddvc.s8','vrhaddhi.s8','vrhaddls.s8','vrhaddge.s8','vrhaddlt.s8','vrhaddgt.s8','vrhaddle.s8',
+ 'vrhaddeq.s16','vrhaddne.s16','vrhaddcs.s16','vrhaddhs.s16','vrhaddcc.s16','vrhaddlo.s16','vrhaddmi.s16','vrhaddpl.s16','vrhaddvs.s16','vrhaddvc.s16','vrhaddhi.s16','vrhaddls.s16','vrhaddge.s16','vrhaddlt.s16','vrhaddgt.s16','vrhaddle.s16',
+ 'vrhaddeq.s32','vrhaddne.s32','vrhaddcs.s32','vrhaddhs.s32','vrhaddcc.s32','vrhaddlo.s32','vrhaddmi.s32','vrhaddpl.s32','vrhaddvs.s32','vrhaddvc.s32','vrhaddhi.s32','vrhaddls.s32','vrhaddge.s32','vrhaddlt.s32','vrhaddgt.s32','vrhaddle.s32',
+
+ 'vrshleq.s8','vrshlne.s8','vrshlcs.s8','vrshlhs.s8','vrshlcc.s8','vrshllo.s8','vrshlmi.s8','vrshlpl.s8','vrshlvs.s8','vrshlvc.s8','vrshlhi.s8','vrshlls.s8','vrshlge.s8','vrshllt.s8','vrshlgt.s8','vrshlle.s8',
+ 'vrshleq.s16','vrshlne.s16','vrshlcs.s16','vrshlhs.s16','vrshlcc.s16','vrshllo.s16','vrshlmi.s16','vrshlpl.s16','vrshlvs.s16','vrshlvc.s16','vrshlhi.s16','vrshlls.s16','vrshlge.s16','vrshllt.s16','vrshlgt.s16','vrshlle.s16',
+ 'vrshleq.s32','vrshlne.s32','vrshlcs.s32','vrshlhs.s32','vrshlcc.s32','vrshllo.s32','vrshlmi.s32','vrshlpl.s32','vrshlvs.s32','vrshlvc.s32','vrshlhi.s32','vrshlls.s32','vrshlge.s32','vrshllt.s32','vrshlgt.s32','vrshlle.s32',
+ 'vrshleq.s64','vrshlne.s64','vrshlcs.s64','vrshlhs.s64','vrshlcc.s64','vrshllo.s64','vrshlmi.s64','vrshlpl.s64','vrshlvs.s64','vrshlvc.s64','vrshlhi.s64','vrshlls.s64','vrshlge.s64','vrshllt.s64','vrshlgt.s64','vrshlle.s64',
+
+ 'vrshreq.s8','vrshrne.s8','vrshrcs.s8','vrshrhs.s8','vrshrcc.s8','vrshrlo.s8','vrshrmi.s8','vrshrpl.s8','vrshrvs.s8','vrshrvc.s8','vrshrhi.s8','vrshrls.s8','vrshrge.s8','vrshrlt.s8','vrshrgt.s8','vrshrle.s8',
+ 'vrshreq.s16','vrshrne.s16','vrshrcs.s16','vrshrhs.s16','vrshrcc.s16','vrshrlo.s16','vrshrmi.s16','vrshrpl.s16','vrshrvs.s16','vrshrvc.s16','vrshrhi.s16','vrshrls.s16','vrshrge.s16','vrshrlt.s16','vrshrgt.s16','vrshrle.s16',
+ 'vrshreq.s32','vrshrne.s32','vrshrcs.s32','vrshrhs.s32','vrshrcc.s32','vrshrlo.s32','vrshrmi.s32','vrshrpl.s32','vrshrvs.s32','vrshrvc.s32','vrshrhi.s32','vrshrls.s32','vrshrge.s32','vrshrlt.s32','vrshrgt.s32','vrshrle.s32',
+ 'vrshreq.s64','vrshrne.s64','vrshrcs.s64','vrshrhs.s64','vrshrcc.s64','vrshrlo.s64','vrshrmi.s64','vrshrpl.s64','vrshrvs.s64','vrshrvc.s64','vrshrhi.s64','vrshrls.s64','vrshrge.s64','vrshrlt.s64','vrshrgt.s64','vrshrle.s64',
+
+ 'vrsraeq.s8','vrsrane.s8','vrsracs.s8','vrsrahs.s8','vrsracc.s8','vrsralo.s8','vrsrami.s8','vrsrapl.s8','vrsravs.s8','vrsravc.s8','vrsrahi.s8','vrsrals.s8','vrsrage.s8','vrsralt.s8','vrsragt.s8','vrsrale.s8',
+ 'vrsraeq.s16','vrsrane.s16','vrsracs.s16','vrsrahs.s16','vrsracc.s16','vrsralo.s16','vrsrami.s16','vrsrapl.s16','vrsravs.s16','vrsravc.s16','vrsrahi.s16','vrsrals.s16','vrsrage.s16','vrsralt.s16','vrsragt.s16','vrsrale.s16',
+ 'vrsraeq.s32','vrsrane.s32','vrsracs.s32','vrsrahs.s32','vrsracc.s32','vrsralo.s32','vrsrami.s32','vrsrapl.s32','vrsravs.s32','vrsravc.s32','vrsrahi.s32','vrsrals.s32','vrsrage.s32','vrsralt.s32','vrsragt.s32','vrsrale.s32',
+ 'vrsraeq.s64','vrsrane.s64','vrsracs.s64','vrsrahs.s64','vrsracc.s64','vrsralo.s64','vrsrami.s64','vrsrapl.s64','vrsravs.s64','vrsravc.s64','vrsrahi.s64','vrsrals.s64','vrsrage.s64','vrsralt.s64','vrsragt.s64','vrsrale.s64',
+
+ 'vshleq.s8','vshlne.s8','vshlcs.s8','vshlhs.s8','vshlcc.s8','vshllo.s8','vshlmi.s8','vshlpl.s8','vshlvs.s8','vshlvc.s8','vshlhi.s8','vshlls.s8','vshlge.s8','vshllt.s8','vshlgt.s8','vshlle.s8',
+ 'vshleq.s16','vshlne.s16','vshlcs.s16','vshlhs.s16','vshlcc.s16','vshllo.s16','vshlmi.s16','vshlpl.s16','vshlvs.s16','vshlvc.s16','vshlhi.s16','vshlls.s16','vshlge.s16','vshllt.s16','vshlgt.s16','vshlle.s16',
+ 'vshleq.s32','vshlne.s32','vshlcs.s32','vshlhs.s32','vshlcc.s32','vshllo.s32','vshlmi.s32','vshlpl.s32','vshlvs.s32','vshlvc.s32','vshlhi.s32','vshlls.s32','vshlge.s32','vshllt.s32','vshlgt.s32','vshlle.s32',
+ 'vshleq.s64','vshlne.s64','vshlcs.s64','vshlhs.s64','vshlcc.s64','vshllo.s64','vshlmi.s64','vshlpl.s64','vshlvs.s64','vshlvc.s64','vshlhi.s64','vshlls.s64','vshlge.s64','vshllt.s64','vshlgt.s64','vshlle.s64',
+
+ 'vshlleq.s8','vshllne.s8','vshllcs.s8','vshllhs.s8','vshllcc.s8','vshlllo.s8','vshllmi.s8','vshllpl.s8','vshllvs.s8','vshllvc.s8','vshllhi.s8','vshllls.s8','vshllge.s8','vshlllt.s8','vshllgt.s8','vshllle.s8',
+ 'vshlleq.s16','vshllne.s16','vshllcs.s16','vshllhs.s16','vshllcc.s16','vshlllo.s16','vshllmi.s16','vshllpl.s16','vshllvs.s16','vshllvc.s16','vshllhi.s16','vshllls.s16','vshllge.s16','vshlllt.s16','vshllgt.s16','vshllle.s16',
+ 'vshlleq.s32','vshllne.s32','vshllcs.s32','vshllhs.s32','vshllcc.s32','vshlllo.s32','vshllmi.s32','vshllpl.s32','vshllvs.s32','vshllvc.s32','vshllhi.s32','vshllls.s32','vshllge.s32','vshlllt.s32','vshllgt.s32','vshllle.s32',
+
+ 'vshreq.s8','vshrne.s8','vshrcs.s8','vshrhs.s8','vshrcc.s8','vshrlo.s8','vshrmi.s8','vshrpl.s8','vshrvs.s8','vshrvc.s8','vshrhi.s8','vshrls.s8','vshrge.s8','vshrlt.s8','vshrgt.s8','vshrle.s8',
+ 'vshreq.s16','vshrne.s16','vshrcs.s16','vshrhs.s16','vshrcc.s16','vshrlo.s16','vshrmi.s16','vshrpl.s16','vshrvs.s16','vshrvc.s16','vshrhi.s16','vshrls.s16','vshrge.s16','vshrlt.s16','vshrgt.s16','vshrle.s16',
+ 'vshreq.s32','vshrne.s32','vshrcs.s32','vshrhs.s32','vshrcc.s32','vshrlo.s32','vshrmi.s32','vshrpl.s32','vshrvs.s32','vshrvc.s32','vshrhi.s32','vshrls.s32','vshrge.s32','vshrlt.s32','vshrgt.s32','vshrle.s32',
+ 'vshreq.s64','vshrne.s64','vshrcs.s64','vshrhs.s64','vshrcc.s64','vshrlo.s64','vshrmi.s64','vshrpl.s64','vshrvs.s64','vshrvc.s64','vshrhi.s64','vshrls.s64','vshrge.s64','vshrlt.s64','vshrgt.s64','vshrle.s64',
+
+ 'vsraeq.s8','vsrane.s8','vsracs.s8','vsrahs.s8','vsracc.s8','vsralo.s8','vsrami.s8','vsrapl.s8','vsravs.s8','vsravc.s8','vsrahi.s8','vsrals.s8','vsrage.s8','vsralt.s8','vsragt.s8','vsrale.s8',
+ 'vsraeq.s16','vsrane.s16','vsracs.s16','vsrahs.s16','vsracc.s16','vsralo.s16','vsrami.s16','vsrapl.s16','vsravs.s16','vsravc.s16','vsrahi.s16','vsrals.s16','vsrage.s16','vsralt.s16','vsragt.s16','vsrale.s16',
+ 'vsraeq.s32','vsrane.s32','vsracs.s32','vsrahs.s32','vsracc.s32','vsralo.s32','vsrami.s32','vsrapl.s32','vsravs.s32','vsravc.s32','vsrahi.s32','vsrals.s32','vsrage.s32','vsralt.s32','vsragt.s32','vsrale.s32',
+ 'vsraeq.s64','vsrane.s64','vsracs.s64','vsrahs.s64','vsracc.s64','vsralo.s64','vsrami.s64','vsrapl.s64','vsravs.s64','vsravc.s64','vsrahi.s64','vsrals.s64','vsrage.s64','vsralt.s64','vsragt.s64','vsrale.s64',
+
+ 'vsubleq.s8','vsublne.s8','vsublcs.s8','vsublhs.s8','vsublcc.s8','vsubllo.s8','vsublmi.s8','vsublpl.s8','vsublvs.s8','vsublvc.s8','vsublhi.s8','vsublls.s8','vsublge.s8','vsubllt.s8','vsublgt.s8','vsublle.s8',
+ 'vsubleq.s16','vsublne.s16','vsublcs.s16','vsublhs.s16','vsublcc.s16','vsubllo.s16','vsublmi.s16','vsublpl.s16','vsublvs.s16','vsublvc.s16','vsublhi.s16','vsublls.s16','vsublge.s16','vsubllt.s16','vsublgt.s16','vsublle.s16',
+ 'vsubleq.s32','vsublne.s32','vsublcs.s32','vsublhs.s32','vsublcc.s32','vsubllo.s32','vsublmi.s32','vsublpl.s32','vsublvs.s32','vsublvc.s32','vsublhi.s32','vsublls.s32','vsublge.s32','vsubllt.s32','vsublgt.s32','vsublle.s32',
+
+ 'vsubheq.s8','vsubhne.s8','vsubhcs.s8','vsubhhs.s8','vsubhcc.s8','vsubhlo.s8','vsubhmi.s8','vsubhpl.s8','vsubhvs.s8','vsubhvc.s8','vsubhhi.s8','vsubhls.s8','vsubhge.s8','vsubhlt.s8','vsubhgt.s8','vsubhle.s8',
+ 'vsubheq.s16','vsubhne.s16','vsubhcs.s16','vsubhhs.s16','vsubhcc.s16','vsubhlo.s16','vsubhmi.s16','vsubhpl.s16','vsubhvs.s16','vsubhvc.s16','vsubhhi.s16','vsubhls.s16','vsubhge.s16','vsubhlt.s16','vsubhgt.s16','vsubhle.s16',
+ 'vsubheq.s32','vsubhne.s32','vsubhcs.s32','vsubhhs.s32','vsubhcc.s32','vsubhlo.s32','vsubhmi.s32','vsubhpl.s32','vsubhvs.s32','vsubhvc.s32','vsubhhi.s32','vsubhls.s32','vsubhge.s32','vsubhlt.s32','vsubhgt.s32','vsubhle.s32'
+ ),
+ /* Conditional NEON SIMD Unsigned Integer Instructions */
+ 33 => array(
+ 'vabaeq.u8','vabane.u8','vabacs.u8','vabahs.u8','vabacc.u8','vabalo.u8','vabami.u8','vabapl.u8','vabavs.u8','vabavc.u8','vabahi.u8','vabals.u8','vabage.u8','vabalt.u8','vabagt.u8','vabale.u8',
+ 'vabaeq.u16','vabane.u16','vabacs.u16','vabahs.u16','vabacc.u16','vabalo.u16','vabami.u16','vabapl.u16','vabavs.u16','vabavc.u16','vabahi.u16','vabals.u16','vabage.u16','vabalt.u16','vabagt.u16','vabale.u16',
+ 'vabaeq.u32','vabane.u32','vabacs.u32','vabahs.u32','vabacc.u32','vabalo.u32','vabami.u32','vabapl.u32','vabavs.u32','vabavc.u32','vabahi.u32','vabals.u32','vabage.u32','vabalt.u32','vabagt.u32','vabale.u32',
+
+ 'vabaleq.u8','vabalne.u8','vabalcs.u8','vabalhs.u8','vabalcc.u8','vaballo.u8','vabalmi.u8','vabalpl.u8','vabalvs.u8','vabalvc.u8','vabalhi.u8','vaballs.u8','vabalge.u8','vaballt.u8','vabalgt.u8','vaballe.u8',
+ 'vabaleq.u16','vabalne.u16','vabalcs.u16','vabalhs.u16','vabalcc.u16','vaballo.u16','vabalmi.u16','vabalpl.u16','vabalvs.u16','vabalvc.u16','vabalhi.u16','vaballs.u16','vabalge.u16','vaballt.u16','vabalgt.u16','vaballe.u16',
+ 'vabaleq.u32','vabalne.u32','vabalcs.u32','vabalhs.u32','vabalcc.u32','vaballo.u32','vabalmi.u32','vabalpl.u32','vabalvs.u32','vabalvc.u32','vabalhi.u32','vaballs.u32','vabalge.u32','vaballt.u32','vabalgt.u32','vaballe.u32',
+
+ 'vabdeq.u8','vabdne.u8','vabdcs.u8','vabdhs.u8','vabdcc.u8','vabdlo.u8','vabdmi.u8','vabdpl.u8','vabdvs.u8','vabdvc.u8','vabdhi.u8','vabdls.u8','vabdge.u8','vabdlt.u8','vabdgt.u8','vabdle.u8',
+ 'vabdeq.u16','vabdne.u16','vabdcs.u16','vabdhs.u16','vabdcc.u16','vabdlo.u16','vabdmi.u16','vabdpl.u16','vabdvs.u16','vabdvc.u16','vabdhi.u16','vabdls.u16','vabdge.u16','vabdlt.u16','vabdgt.u16','vabdle.u16',
+ 'vabdeq.u32','vabdne.u32','vabdcs.u32','vabdhs.u32','vabdcc.u32','vabdlo.u32','vabdmi.u32','vabdpl.u32','vabdvs.u32','vabdvc.u32','vabdhi.u32','vabdls.u32','vabdge.u32','vabdlt.u32','vabdgt.u32','vabdle.u32',
+
+ 'vaddleq.u8','vaddlne.u8','vaddlcs.u8','vaddlhs.u8','vaddlcc.u8','vaddllo.u8','vaddlmi.u8','vaddlpl.u8','vaddlvs.u8','vaddlvc.u8','vaddlhi.u8','vaddlls.u8','vaddlge.u8','vaddllt.u8','vaddlgt.u8','vaddlle.u8',
+ 'vaddleq.u16','vaddlne.u16','vaddlcs.u16','vaddlhs.u16','vaddlcc.u16','vaddllo.u16','vaddlmi.u16','vaddlpl.u16','vaddlvs.u16','vaddlvc.u16','vaddlhi.u16','vaddlls.u16','vaddlge.u16','vaddllt.u16','vaddlgt.u16','vaddlle.u16',
+ 'vaddleq.u32','vaddlne.u32','vaddlcs.u32','vaddlhs.u32','vaddlcc.u32','vaddllo.u32','vaddlmi.u32','vaddlpl.u32','vaddlvs.u32','vaddlvc.u32','vaddlhi.u32','vaddlls.u32','vaddlge.u32','vaddllt.u32','vaddlgt.u32','vaddlle.u32',
+
+ 'vsubleq.u8','vsublne.u8','vsublcs.u8','vsublhs.u8','vsublcc.u8','vsubllo.u8','vsublmi.u8','vsublpl.u8','vsublvs.u8','vsublvc.u8','vsublhi.u8','vsublls.u8','vsublge.u8','vsubllt.u8','vsublgt.u8','vsublle.u8',
+ 'vsubleq.u16','vsublne.u16','vsublcs.u16','vsublhs.u16','vsublcc.u16','vsubllo.u16','vsublmi.u16','vsublpl.u16','vsublvs.u16','vsublvc.u16','vsublhi.u16','vsublls.u16','vsublge.u16','vsubllt.u16','vsublgt.u16','vsublle.u16',
+ 'vsubleq.u32','vsublne.u32','vsublcs.u32','vsublhs.u32','vsublcc.u32','vsubllo.u32','vsublmi.u32','vsublpl.u32','vsublvs.u32','vsublvc.u32','vsublhi.u32','vsublls.u32','vsublge.u32','vsubllt.u32','vsublgt.u32','vsublle.u32',
+
+ 'vaddweq.u8','vaddwne.u8','vaddwcs.u8','vaddwhs.u8','vaddwcc.u8','vaddwlo.u8','vaddwmi.u8','vaddwpl.u8','vaddwvs.u8','vaddwvc.u8','vaddwhi.u8','vaddwls.u8','vaddwge.u8','vaddwlt.u8','vaddwgt.u8','vaddwle.u8',
+ 'vaddweq.u16','vaddwne.u16','vaddwcs.u16','vaddwhs.u16','vaddwcc.u16','vaddwlo.u16','vaddwmi.u16','vaddwpl.u16','vaddwvs.u16','vaddwvc.u16','vaddwhi.u16','vaddwls.u16','vaddwge.u16','vaddwlt.u16','vaddwgt.u16','vaddwle.u16',
+ 'vaddweq.u32','vaddwne.u32','vaddwcs.u32','vaddwhs.u32','vaddwcc.u32','vaddwlo.u32','vaddwmi.u32','vaddwpl.u32','vaddwvs.u32','vaddwvc.u32','vaddwhi.u32','vaddwls.u32','vaddwge.u32','vaddwlt.u32','vaddwgt.u32','vaddwle.u32',
+
+ 'vsubheq.u8','vsubhne.u8','vsubhcs.u8','vsubhhs.u8','vsubhcc.u8','vsubhlo.u8','vsubhmi.u8','vsubhpl.u8','vsubhvs.u8','vsubhvc.u8','vsubhhi.u8','vsubhls.u8','vsubhge.u8','vsubhlt.u8','vsubhgt.u8','vsubhle.u8',
+ 'vsubheq.u16','vsubhne.u16','vsubhcs.u16','vsubhhs.u16','vsubhcc.u16','vsubhlo.u16','vsubhmi.u16','vsubhpl.u16','vsubhvs.u16','vsubhvc.u16','vsubhhi.u16','vsubhls.u16','vsubhge.u16','vsubhlt.u16','vsubhgt.u16','vsubhle.u16',
+ 'vsubheq.u32','vsubhne.u32','vsubhcs.u32','vsubhhs.u32','vsubhcc.u32','vsubhlo.u32','vsubhmi.u32','vsubhpl.u32','vsubhvs.u32','vsubhvc.u32','vsubhhi.u32','vsubhls.u32','vsubhge.u32','vsubhlt.u32','vsubhgt.u32','vsubhle.u32',
+
+ 'vhaddeq.u8','vhaddne.u8','vhaddcs.u8','vhaddhs.u8','vhaddcc.u8','vhaddlo.u8','vhaddmi.u8','vhaddpl.u8','vhaddvs.u8','vhaddvc.u8','vhaddhi.u8','vhaddls.u8','vhaddge.u8','vhaddlt.u8','vhaddgt.u8','vhaddle.u8',
+ 'vhaddeq.u16','vhaddne.u16','vhaddcs.u16','vhaddhs.u16','vhaddcc.u16','vhaddlo.u16','vhaddmi.u16','vhaddpl.u16','vhaddvs.u16','vhaddvc.u16','vhaddhi.u16','vhaddls.u16','vhaddge.u16','vhaddlt.u16','vhaddgt.u16','vhaddle.u16',
+ 'vhaddeq.u32','vhaddne.u32','vhaddcs.u32','vhaddhs.u32','vhaddcc.u32','vhaddlo.u32','vhaddmi.u32','vhaddpl.u32','vhaddvs.u32','vhaddvc.u32','vhaddhi.u32','vhaddls.u32','vhaddge.u32','vhaddlt.u32','vhaddgt.u32','vhaddle.u32',
+
+ 'vhsubeq.u8','vhsubne.u8','vhsubcs.u8','vhsubhs.u8','vhsubcc.u8','vhsublo.u8','vhsubmi.u8','vhsubpl.u8','vhsubvs.u8','vhsubvc.u8','vhsubhi.u8','vhsubls.u8','vhsubge.u8','vhsublt.u8','vhsubgt.u8','vhsuble.u8',
+ 'vhsubeq.u16','vhsubne.u16','vhsubcs.u16','vhsubhs.u16','vhsubcc.u16','vhsublo.u16','vhsubmi.u16','vhsubpl.u16','vhsubvs.u16','vhsubvc.u16','vhsubhi.u16','vhsubls.u16','vhsubge.u16','vhsublt.u16','vhsubgt.u16','vhsuble.u16',
+ 'vhsubeq.u32','vhsubne.u32','vhsubcs.u32','vhsubhs.u32','vhsubcc.u32','vhsublo.u32','vhsubmi.u32','vhsubpl.u32','vhsubvs.u32','vhsubvc.u32','vhsubhi.u32','vhsubls.u32','vhsubge.u32','vhsublt.u32','vhsubgt.u32','vhsuble.u32',
+
+ 'vpadaleq.u8','vpadalne.u8','vpadalcs.u8','vpadalhs.u8','vpadalcc.u8','vpadallo.u8','vpadalmi.u8','vpadalpl.u8','vpadalvs.u8','vpadalvc.u8','vpadalhi.u8','vpadalls.u8','vpadalge.u8','vpadallt.u8','vpadalgt.u8','vpadalle.u8',
+ 'vpadaleq.u16','vpadalne.u16','vpadalcs.u16','vpadalhs.u16','vpadalcc.u16','vpadallo.u16','vpadalmi.u16','vpadalpl.u16','vpadalvs.u16','vpadalvc.u16','vpadalhi.u16','vpadalls.u16','vpadalge.u16','vpadallt.u16','vpadalgt.u16','vpadalle.u16',
+ 'vpadaleq.u32','vpadalne.u32','vpadalcs.u32','vpadalhs.u32','vpadalcc.u32','vpadallo.u32','vpadalmi.u32','vpadalpl.u32','vpadalvs.u32','vpadalvc.u32','vpadalhi.u32','vpadalls.u32','vpadalge.u32','vpadallt.u32','vpadalgt.u32','vpadalle.u32',
+
+ 'vpaddleq.u8','vpaddlne.u8','vpaddlcs.u8','vpaddlhs.u8','vpaddlcc.u8','vpaddllo.u8','vpaddlmi.u8','vpaddlpl.u8','vpaddlvs.u8','vpaddlvc.u8','vpaddlhi.u8','vpaddlls.u8','vpaddlge.u8','vpaddllt.u8','vpaddlgt.u8','vpaddlle.u8',
+ 'vpaddleq.u16','vpaddlne.u16','vpaddlcs.u16','vpaddlhs.u16','vpaddlcc.u16','vpaddllo.u16','vpaddlmi.u16','vpaddlpl.u16','vpaddlvs.u16','vpaddlvc.u16','vpaddlhi.u16','vpaddlls.u16','vpaddlge.u16','vpaddllt.u16','vpaddlgt.u16','vpaddlle.u16',
+ 'vpaddleq.u32','vpaddlne.u32','vpaddlcs.u32','vpaddlhs.u32','vpaddlcc.u32','vpaddllo.u32','vpaddlmi.u32','vpaddlpl.u32','vpaddlvs.u32','vpaddlvc.u32','vpaddlhi.u32','vpaddlls.u32','vpaddlge.u32','vpaddllt.u32','vpaddlgt.u32','vpaddlle.u32',
+
+ 'vcgeeq.u8','vcgene.u8','vcgecs.u8','vcgehs.u8','vcgecc.u8','vcgelo.u8','vcgemi.u8','vcgepl.u8','vcgevs.u8','vcgevc.u8','vcgehi.u8','vcgels.u8','vcgege.u8','vcgelt.u8','vcgegt.u8','vcgele.u8',
+ 'vcgeeq.u16','vcgene.u16','vcgecs.u16','vcgehs.u16','vcgecc.u16','vcgelo.u16','vcgemi.u16','vcgepl.u16','vcgevs.u16','vcgevc.u16','vcgehi.u16','vcgels.u16','vcgege.u16','vcgelt.u16','vcgegt.u16','vcgele.u16',
+ 'vcgeeq.u32','vcgene.u32','vcgecs.u32','vcgehs.u32','vcgecc.u32','vcgelo.u32','vcgemi.u32','vcgepl.u32','vcgevs.u32','vcgevc.u32','vcgehi.u32','vcgels.u32','vcgege.u32','vcgelt.u32','vcgegt.u32','vcgele.u32',
+
+ 'vcleeq.u8','vclene.u8','vclecs.u8','vclehs.u8','vclecc.u8','vclelo.u8','vclemi.u8','vclepl.u8','vclevs.u8','vclevc.u8','vclehi.u8','vclels.u8','vclege.u8','vclelt.u8','vclegt.u8','vclele.u8',
+ 'vcleeq.u16','vclene.u16','vclecs.u16','vclehs.u16','vclecc.u16','vclelo.u16','vclemi.u16','vclepl.u16','vclevs.u16','vclevc.u16','vclehi.u16','vclels.u16','vclege.u16','vclelt.u16','vclegt.u16','vclele.u16',
+ 'vcleeq.u32','vclene.u32','vclecs.u32','vclehs.u32','vclecc.u32','vclelo.u32','vclemi.u32','vclepl.u32','vclevs.u32','vclevc.u32','vclehi.u32','vclels.u32','vclege.u32','vclelt.u32','vclegt.u32','vclele.u32',
+
+ 'vcgteq.u8','vcgtne.u8','vcgtcs.u8','vcgths.u8','vcgtcc.u8','vcgtlo.u8','vcgtmi.u8','vcgtpl.u8','vcgtvs.u8','vcgtvc.u8','vcgthi.u8','vcgtls.u8','vcgtge.u8','vcgtlt.u8','vcgtgt.u8','vcgtle.u8',
+ 'vcgteq.u16','vcgtne.u16','vcgtcs.u16','vcgths.u16','vcgtcc.u16','vcgtlo.u16','vcgtmi.u16','vcgtpl.u16','vcgtvs.u16','vcgtvc.u16','vcgthi.u16','vcgtls.u16','vcgtge.u16','vcgtlt.u16','vcgtgt.u16','vcgtle.u16',
+ 'vcgteq.u32','vcgtne.u32','vcgtcs.u32','vcgths.u32','vcgtcc.u32','vcgtlo.u32','vcgtmi.u32','vcgtpl.u32','vcgtvs.u32','vcgtvc.u32','vcgthi.u32','vcgtls.u32','vcgtge.u32','vcgtlt.u32','vcgtgt.u32','vcgtle.u32',
+
+ 'vclteq.u8','vcltne.u8','vcltcs.u8','vclths.u8','vcltcc.u8','vcltlo.u8','vcltmi.u8','vcltpl.u8','vcltvs.u8','vcltvc.u8','vclthi.u8','vcltls.u8','vcltge.u8','vcltlt.u8','vcltgt.u8','vcltle.u8',
+ 'vclteq.u16','vcltne.u16','vcltcs.u16','vclths.u16','vcltcc.u16','vcltlo.u16','vcltmi.u16','vcltpl.u16','vcltvs.u16','vcltvc.u16','vclthi.u16','vcltls.u16','vcltge.u16','vcltlt.u16','vcltgt.u16','vcltle.u16',
+ 'vclteq.u32','vcltne.u32','vcltcs.u32','vclths.u32','vcltcc.u32','vcltlo.u32','vcltmi.u32','vcltpl.u32','vcltvs.u32','vcltvc.u32','vclthi.u32','vcltls.u32','vcltge.u32','vcltlt.u32','vcltgt.u32','vcltle.u32',
+
+ 'vmaxeq.u8','vmaxne.u8','vmaxcs.u8','vmaxhs.u8','vmaxcc.u8','vmaxlo.u8','vmaxmi.u8','vmaxpl.u8','vmaxvs.u8','vmaxvc.u8','vmaxhi.u8','vmaxls.u8','vmaxge.u8','vmaxlt.u8','vmaxgt.u8','vmaxle.u8',
+ 'vmaxeq.u16','vmaxne.u16','vmaxcs.u16','vmaxhs.u16','vmaxcc.u16','vmaxlo.u16','vmaxmi.u16','vmaxpl.u16','vmaxvs.u16','vmaxvc.u16','vmaxhi.u16','vmaxls.u16','vmaxge.u16','vmaxlt.u16','vmaxgt.u16','vmaxle.u16',
+ 'vmaxeq.u32','vmaxne.u32','vmaxcs.u32','vmaxhs.u32','vmaxcc.u32','vmaxlo.u32','vmaxmi.u32','vmaxpl.u32','vmaxvs.u32','vmaxvc.u32','vmaxhi.u32','vmaxls.u32','vmaxge.u32','vmaxlt.u32','vmaxgt.u32','vmaxle.u32',
+
+ 'vmineq.u8','vminne.u8','vmincs.u8','vminhs.u8','vmincc.u8','vminlo.u8','vminmi.u8','vminpl.u8','vminvs.u8','vminvc.u8','vminhi.u8','vminls.u8','vminge.u8','vminlt.u8','vmingt.u8','vminle.u8',
+ 'vmineq.u16','vminne.u16','vmincs.u16','vminhs.u16','vmincc.u16','vminlo.u16','vminmi.u16','vminpl.u16','vminvs.u16','vminvc.u16','vminhi.u16','vminls.u16','vminge.u16','vminlt.u16','vmingt.u16','vminle.u16',
+ 'vmineq.u32','vminne.u32','vmincs.u32','vminhs.u32','vmincc.u32','vminlo.u32','vminmi.u32','vminpl.u32','vminvs.u32','vminvc.u32','vminhi.u32','vminls.u32','vminge.u32','vminlt.u32','vmingt.u32','vminle.u32',
+
+ 'vmlaleq.u8','vmlalne.u8','vmlalcs.u8','vmlalhs.u8','vmlalcc.u8','vmlallo.u8','vmlalmi.u8','vmlalpl.u8','vmlalvs.u8','vmlalvc.u8','vmlalhi.u8','vmlalls.u8','vmlalge.u8','vmlallt.u8','vmlalgt.u8','vmlalle.u8',
+ 'vmlaleq.u16','vmlalne.u16','vmlalcs.u16','vmlalhs.u16','vmlalcc.u16','vmlallo.u16','vmlalmi.u16','vmlalpl.u16','vmlalvs.u16','vmlalvc.u16','vmlalhi.u16','vmlalls.u16','vmlalge.u16','vmlallt.u16','vmlalgt.u16','vmlalle.u16',
+ 'vmlaleq.u32','vmlalne.u32','vmlalcs.u32','vmlalhs.u32','vmlalcc.u32','vmlallo.u32','vmlalmi.u32','vmlalpl.u32','vmlalvs.u32','vmlalvc.u32','vmlalhi.u32','vmlalls.u32','vmlalge.u32','vmlallt.u32','vmlalgt.u32','vmlalle.u32',
+
+ 'vmlsleq.u8','vmlslne.u8','vmlslcs.u8','vmlslhs.u8','vmlslcc.u8','vmlsllo.u8','vmlslmi.u8','vmlslpl.u8','vmlslvs.u8','vmlslvc.u8','vmlslhi.u8','vmlslls.u8','vmlslge.u8','vmlsllt.u8','vmlslgt.u8','vmlslle.u8',
+ 'vmlsleq.u16','vmlslne.u16','vmlslcs.u16','vmlslhs.u16','vmlslcc.u16','vmlsllo.u16','vmlslmi.u16','vmlslpl.u16','vmlslvs.u16','vmlslvc.u16','vmlslhi.u16','vmlslls.u16','vmlslge.u16','vmlsllt.u16','vmlslgt.u16','vmlslle.u16',
+ 'vmlsleq.u32','vmlslne.u32','vmlslcs.u32','vmlslhs.u32','vmlslcc.u32','vmlsllo.u32','vmlslmi.u32','vmlslpl.u32','vmlslvs.u32','vmlslvc.u32','vmlslhi.u32','vmlslls.u32','vmlslge.u32','vmlsllt.u32','vmlslgt.u32','vmlslle.u32',
+
+ 'vmulleq.u8','vmullne.u8','vmullcs.u8','vmullhs.u8','vmullcc.u8','vmulllo.u8','vmullmi.u8','vmullpl.u8','vmullvs.u8','vmullvc.u8','vmullhi.u8','vmullls.u8','vmullge.u8','vmulllt.u8','vmullgt.u8','vmullle.u8',
+ 'vmulleq.u16','vmullne.u16','vmullcs.u16','vmullhs.u16','vmullcc.u16','vmulllo.u16','vmullmi.u16','vmullpl.u16','vmullvs.u16','vmullvc.u16','vmullhi.u16','vmullls.u16','vmullge.u16','vmulllt.u16','vmullgt.u16','vmullle.u16',
+ 'vmulleq.u32','vmullne.u32','vmullcs.u32','vmullhs.u32','vmullcc.u32','vmulllo.u32','vmullmi.u32','vmullpl.u32','vmullvs.u32','vmullvc.u32','vmullhi.u32','vmullls.u32','vmullge.u32','vmulllt.u32','vmullgt.u32','vmullle.u32',
+
+ 'vmovleq.u8','vmovlne.u8','vmovlcs.u8','vmovlhs.u8','vmovlcc.u8','vmovllo.u8','vmovlmi.u8','vmovlpl.u8','vmovlvs.u8','vmovlvc.u8','vmovlhi.u8','vmovlls.u8','vmovlge.u8','vmovllt.u8','vmovlgt.u8','vmovlle.u8',
+ 'vmovleq.u16','vmovlne.u16','vmovlcs.u16','vmovlhs.u16','vmovlcc.u16','vmovllo.u16','vmovlmi.u16','vmovlpl.u16','vmovlvs.u16','vmovlvc.u16','vmovlhi.u16','vmovlls.u16','vmovlge.u16','vmovllt.u16','vmovlgt.u16','vmovlle.u16',
+ 'vmovleq.u32','vmovlne.u32','vmovlcs.u32','vmovlhs.u32','vmovlcc.u32','vmovllo.u32','vmovlmi.u32','vmovlpl.u32','vmovlvs.u32','vmovlvc.u32','vmovlhi.u32','vmovlls.u32','vmovlge.u32','vmovllt.u32','vmovlgt.u32','vmovlle.u32',
+
+ 'vshleq.u8','vshlne.u8','vshlcs.u8','vshlhs.u8','vshlcc.u8','vshllo.u8','vshlmi.u8','vshlpl.u8','vshlvs.u8','vshlvc.u8','vshlhi.u8','vshlls.u8','vshlge.u8','vshllt.u8','vshlgt.u8','vshlle.u8',
+ 'vshleq.u16','vshlne.u16','vshlcs.u16','vshlhs.u16','vshlcc.u16','vshllo.u16','vshlmi.u16','vshlpl.u16','vshlvs.u16','vshlvc.u16','vshlhi.u16','vshlls.u16','vshlge.u16','vshllt.u16','vshlgt.u16','vshlle.u16',
+ 'vshleq.u32','vshlne.u32','vshlcs.u32','vshlhs.u32','vshlcc.u32','vshllo.u32','vshlmi.u32','vshlpl.u32','vshlvs.u32','vshlvc.u32','vshlhi.u32','vshlls.u32','vshlge.u32','vshllt.u32','vshlgt.u32','vshlle.u32',
+ 'vshleq.u64','vshlne.u64','vshlcs.u64','vshlhs.u64','vshlcc.u64','vshllo.u64','vshlmi.u64','vshlpl.u64','vshlvs.u64','vshlvc.u64','vshlhi.u64','vshlls.u64','vshlge.u64','vshllt.u64','vshlgt.u64','vshlle.u64',
+
+ 'vshlleq.u8','vshllne.u8','vshllcs.u8','vshllhs.u8','vshllcc.u8','vshlllo.u8','vshllmi.u8','vshllpl.u8','vshllvs.u8','vshllvc.u8','vshllhi.u8','vshllls.u8','vshllge.u8','vshlllt.u8','vshllgt.u8','vshllle.u8',
+ 'vshlleq.u16','vshllne.u16','vshllcs.u16','vshllhs.u16','vshllcc.u16','vshlllo.u16','vshllmi.u16','vshllpl.u16','vshllvs.u16','vshllvc.u16','vshllhi.u16','vshllls.u16','vshllge.u16','vshlllt.u16','vshllgt.u16','vshllle.u16',
+ 'vshlleq.u32','vshllne.u32','vshllcs.u32','vshllhs.u32','vshllcc.u32','vshlllo.u32','vshllmi.u32','vshllpl.u32','vshllvs.u32','vshllvc.u32','vshllhi.u32','vshllls.u32','vshllge.u32','vshlllt.u32','vshllgt.u32','vshllle.u32',
+
+ 'vshreq.u8','vshrne.u8','vshrcs.u8','vshrhs.u8','vshrcc.u8','vshrlo.u8','vshrmi.u8','vshrpl.u8','vshrvs.u8','vshrvc.u8','vshrhi.u8','vshrls.u8','vshrge.u8','vshrlt.u8','vshrgt.u8','vshrle.u8',
+ 'vshreq.u16','vshrne.u16','vshrcs.u16','vshrhs.u16','vshrcc.u16','vshrlo.u16','vshrmi.u16','vshrpl.u16','vshrvs.u16','vshrvc.u16','vshrhi.u16','vshrls.u16','vshrge.u16','vshrlt.u16','vshrgt.u16','vshrle.u16',
+ 'vshreq.u32','vshrne.u32','vshrcs.u32','vshrhs.u32','vshrcc.u32','vshrlo.u32','vshrmi.u32','vshrpl.u32','vshrvs.u32','vshrvc.u32','vshrhi.u32','vshrls.u32','vshrge.u32','vshrlt.u32','vshrgt.u32','vshrle.u32',
+ 'vshreq.u64','vshrne.u64','vshrcs.u64','vshrhs.u64','vshrcc.u64','vshrlo.u64','vshrmi.u64','vshrpl.u64','vshrvs.u64','vshrvc.u64','vshrhi.u64','vshrls.u64','vshrge.u64','vshrlt.u64','vshrgt.u64','vshrle.u64',
+
+ 'vsraeq.u8','vsrane.u8','vsracs.u8','vsrahs.u8','vsracc.u8','vsralo.u8','vsrami.u8','vsrapl.u8','vsravs.u8','vsravc.u8','vsrahi.u8','vsrals.u8','vsrage.u8','vsralt.u8','vsragt.u8','vsrale.u8',
+ 'vsraeq.u16','vsrane.u16','vsracs.u16','vsrahs.u16','vsracc.u16','vsralo.u16','vsrami.u16','vsrapl.u16','vsravs.u16','vsravc.u16','vsrahi.u16','vsrals.u16','vsrage.u16','vsralt.u16','vsragt.u16','vsrale.u16',
+ 'vsraeq.u32','vsrane.u32','vsracs.u32','vsrahs.u32','vsracc.u32','vsralo.u32','vsrami.u32','vsrapl.u32','vsravs.u32','vsravc.u32','vsrahi.u32','vsrals.u32','vsrage.u32','vsralt.u32','vsragt.u32','vsrale.u32',
+ 'vsraeq.u64','vsrane.u64','vsracs.u64','vsrahs.u64','vsracc.u64','vsralo.u64','vsrami.u64','vsrapl.u64','vsravs.u64','vsravc.u64','vsrahi.u64','vsrals.u64','vsrage.u64','vsralt.u64','vsragt.u64','vsrale.u64',
+
+ 'vpmaxeq.u8','vpmaxne.u8','vpmaxcs.u8','vpmaxhs.u8','vpmaxcc.u8','vpmaxlo.u8','vpmaxmi.u8','vpmaxpl.u8','vpmaxvs.u8','vpmaxvc.u8','vpmaxhi.u8','vpmaxls.u8','vpmaxge.u8','vpmaxlt.u8','vpmaxgt.u8','vpmaxle.u8',
+ 'vpmaxeq.u16','vpmaxne.u16','vpmaxcs.u16','vpmaxhs.u16','vpmaxcc.u16','vpmaxlo.u16','vpmaxmi.u16','vpmaxpl.u16','vpmaxvs.u16','vpmaxvc.u16','vpmaxhi.u16','vpmaxls.u16','vpmaxge.u16','vpmaxlt.u16','vpmaxgt.u16','vpmaxle.u16',
+ 'vpmaxeq.u32','vpmaxne.u32','vpmaxcs.u32','vpmaxhs.u32','vpmaxcc.u32','vpmaxlo.u32','vpmaxmi.u32','vpmaxpl.u32','vpmaxvs.u32','vpmaxvc.u32','vpmaxhi.u32','vpmaxls.u32','vpmaxge.u32','vpmaxlt.u32','vpmaxgt.u32','vpmaxle.u32',
+
+ 'vpmineq.u8','vpminne.u8','vpmincs.u8','vpminhs.u8','vpmincc.u8','vpminlo.u8','vpminmi.u8','vpminpl.u8','vpminvs.u8','vpminvc.u8','vpminhi.u8','vpminls.u8','vpminge.u8','vpminlt.u8','vpmingt.u8','vpminle.u8',
+ 'vpmineq.u16','vpminne.u16','vpmincs.u16','vpminhs.u16','vpmincc.u16','vpminlo.u16','vpminmi.u16','vpminpl.u16','vpminvs.u16','vpminvc.u16','vpminhi.u16','vpminls.u16','vpminge.u16','vpminlt.u16','vpmingt.u16','vpminle.u16',
+ 'vpmineq.u32','vpminne.u32','vpmincs.u32','vpminhs.u32','vpmincc.u32','vpminlo.u32','vpminmi.u32','vpminpl.u32','vpminvs.u32','vpminvc.u32','vpminhi.u32','vpminls.u32','vpminge.u32','vpminlt.u32','vpmingt.u32','vpminle.u32',
+
+ 'vqaddeq.u8','vqaddne.u8','vqaddcs.u8','vqaddhs.u8','vqaddcc.u8','vqaddlo.u8','vqaddmi.u8','vqaddpl.u8','vqaddvs.u8','vqaddvc.u8','vqaddhi.u8','vqaddls.u8','vqaddge.u8','vqaddlt.u8','vqaddgt.u8','vqaddle.u8',
+ 'vqaddeq.u16','vqaddne.u16','vqaddcs.u16','vqaddhs.u16','vqaddcc.u16','vqaddlo.u16','vqaddmi.u16','vqaddpl.u16','vqaddvs.u16','vqaddvc.u16','vqaddhi.u16','vqaddls.u16','vqaddge.u16','vqaddlt.u16','vqaddgt.u16','vqaddle.u16',
+ 'vqaddeq.u32','vqaddne.u32','vqaddcs.u32','vqaddhs.u32','vqaddcc.u32','vqaddlo.u32','vqaddmi.u32','vqaddpl.u32','vqaddvs.u32','vqaddvc.u32','vqaddhi.u32','vqaddls.u32','vqaddge.u32','vqaddlt.u32','vqaddgt.u32','vqaddle.u32',
+ 'vqaddeq.u64','vqaddne.u64','vqaddcs.u64','vqaddhs.u64','vqaddcc.u64','vqaddlo.u64','vqaddmi.u64','vqaddpl.u64','vqaddvs.u64','vqaddvc.u64','vqaddhi.u64','vqaddls.u64','vqaddge.u64','vqaddlt.u64','vqaddgt.u64','vqaddle.u64',
+
+ 'vqsubeq.u8','vqsubne.u8','vqsubcs.u8','vqsubhs.u8','vqsubcc.u8','vqsublo.u8','vqsubmi.u8','vqsubpl.u8','vqsubvs.u8','vqsubvc.u8','vqsubhi.u8','vqsubls.u8','vqsubge.u8','vqsublt.u8','vqsubgt.u8','vqsuble.u8',
+ 'vqsubeq.u16','vqsubne.u16','vqsubcs.u16','vqsubhs.u16','vqsubcc.u16','vqsublo.u16','vqsubmi.u16','vqsubpl.u16','vqsubvs.u16','vqsubvc.u16','vqsubhi.u16','vqsubls.u16','vqsubge.u16','vqsublt.u16','vqsubgt.u16','vqsuble.u16',
+ 'vqsubeq.u32','vqsubne.u32','vqsubcs.u32','vqsubhs.u32','vqsubcc.u32','vqsublo.u32','vqsubmi.u32','vqsubpl.u32','vqsubvs.u32','vqsubvc.u32','vqsubhi.u32','vqsubls.u32','vqsubge.u32','vqsublt.u32','vqsubgt.u32','vqsuble.u32',
+ 'vqsubeq.u64','vqsubne.u64','vqsubcs.u64','vqsubhs.u64','vqsubcc.u64','vqsublo.u64','vqsubmi.u64','vqsubpl.u64','vqsubvs.u64','vqsubvc.u64','vqsubhi.u64','vqsubls.u64','vqsubge.u64','vqsublt.u64','vqsubgt.u64','vqsuble.u64',
+
+ 'vqmovneq.u16','vqmovnne.u16','vqmovncs.u16','vqmovnhs.u16','vqmovncc.u16','vqmovnlo.u16','vqmovnmi.u16','vqmovnpl.u16','vqmovnvs.u16','vqmovnvc.u16','vqmovnhi.u16','vqmovnls.u16','vqmovnge.u16','vqmovnlt.u16','vqmovngt.u16','vqmovnle.u16',
+ 'vqmovneq.u32','vqmovnne.u32','vqmovncs.u32','vqmovnhs.u32','vqmovncc.u32','vqmovnlo.u32','vqmovnmi.u32','vqmovnpl.u32','vqmovnvs.u32','vqmovnvc.u32','vqmovnhi.u32','vqmovnls.u32','vqmovnge.u32','vqmovnlt.u32','vqmovngt.u32','vqmovnle.u32',
+ 'vqmovneq.u64','vqmovnne.u64','vqmovncs.u64','vqmovnhs.u64','vqmovncc.u64','vqmovnlo.u64','vqmovnmi.u64','vqmovnpl.u64','vqmovnvs.u64','vqmovnvc.u64','vqmovnhi.u64','vqmovnls.u64','vqmovnge.u64','vqmovnlt.u64','vqmovngt.u64','vqmovnle.u64',
+
+ 'vqshleq.u8','vqshlne.u8','vqshlcs.u8','vqshlhs.u8','vqshlcc.u8','vqshllo.u8','vqshlmi.u8','vqshlpl.u8','vqshlvs.u8','vqshlvc.u8','vqshlhi.u8','vqshlls.u8','vqshlge.u8','vqshllt.u8','vqshlgt.u8','vqshlle.u8',
+ 'vqshleq.u16','vqshlne.u16','vqshlcs.u16','vqshlhs.u16','vqshlcc.u16','vqshllo.u16','vqshlmi.u16','vqshlpl.u16','vqshlvs.u16','vqshlvc.u16','vqshlhi.u16','vqshlls.u16','vqshlge.u16','vqshllt.u16','vqshlgt.u16','vqshlle.u16',
+ 'vqshleq.u32','vqshlne.u32','vqshlcs.u32','vqshlhs.u32','vqshlcc.u32','vqshllo.u32','vqshlmi.u32','vqshlpl.u32','vqshlvs.u32','vqshlvc.u32','vqshlhi.u32','vqshlls.u32','vqshlge.u32','vqshllt.u32','vqshlgt.u32','vqshlle.u32',
+ 'vqshleq.u64','vqshlne.u64','vqshlcs.u64','vqshlhs.u64','vqshlcc.u64','vqshllo.u64','vqshlmi.u64','vqshlpl.u64','vqshlvs.u64','vqshlvc.u64','vqshlhi.u64','vqshlls.u64','vqshlge.u64','vqshllt.u64','vqshlgt.u64','vqshlle.u64',
+
+ 'vqshrneq.u16','vqshrnne.u16','vqshrncs.u16','vqshrnhs.u16','vqshrncc.u16','vqshrnlo.u16','vqshrnmi.u16','vqshrnpl.u16','vqshrnvs.u16','vqshrnvc.u16','vqshrnhi.u16','vqshrnls.u16','vqshrnge.u16','vqshrnlt.u16','vqshrngt.u16','vqshrnle.u16',
+ 'vqshrneq.u32','vqshrnne.u32','vqshrncs.u32','vqshrnhs.u32','vqshrncc.u32','vqshrnlo.u32','vqshrnmi.u32','vqshrnpl.u32','vqshrnvs.u32','vqshrnvc.u32','vqshrnhi.u32','vqshrnls.u32','vqshrnge.u32','vqshrnlt.u32','vqshrngt.u32','vqshrnle.u32',
+ 'vqshrneq.u64','vqshrnne.u64','vqshrncs.u64','vqshrnhs.u64','vqshrncc.u64','vqshrnlo.u64','vqshrnmi.u64','vqshrnpl.u64','vqshrnvs.u64','vqshrnvc.u64','vqshrnhi.u64','vqshrnls.u64','vqshrnge.u64','vqshrnlt.u64','vqshrngt.u64','vqshrnle.u64',
+
+ 'vqrshleq.u8','vqrshlne.u8','vqrshlcs.u8','vqrshlhs.u8','vqrshlcc.u8','vqrshllo.u8','vqrshlmi.u8','vqrshlpl.u8','vqrshlvs.u8','vqrshlvc.u8','vqrshlhi.u8','vqrshlls.u8','vqrshlge.u8','vqrshllt.u8','vqrshlgt.u8','vqrshlle.u8',
+ 'vqrshleq.u16','vqrshlne.u16','vqrshlcs.u16','vqrshlhs.u16','vqrshlcc.u16','vqrshllo.u16','vqrshlmi.u16','vqrshlpl.u16','vqrshlvs.u16','vqrshlvc.u16','vqrshlhi.u16','vqrshlls.u16','vqrshlge.u16','vqrshllt.u16','vqrshlgt.u16','vqrshlle.u16',
+ 'vqrshleq.u32','vqrshlne.u32','vqrshlcs.u32','vqrshlhs.u32','vqrshlcc.u32','vqrshllo.u32','vqrshlmi.u32','vqrshlpl.u32','vqrshlvs.u32','vqrshlvc.u32','vqrshlhi.u32','vqrshlls.u32','vqrshlge.u32','vqrshllt.u32','vqrshlgt.u32','vqrshlle.u32',
+ 'vqrshleq.u64','vqrshlne.u64','vqrshlcs.u64','vqrshlhs.u64','vqrshlcc.u64','vqrshllo.u64','vqrshlmi.u64','vqrshlpl.u64','vqrshlvs.u64','vqrshlvc.u64','vqrshlhi.u64','vqrshlls.u64','vqrshlge.u64','vqrshllt.u64','vqrshlgt.u64','vqrshlle.u64',
+
+ 'vqrshrneq.u16','vqrshrnne.u16','vqrshrncs.u16','vqrshrnhs.u16','vqrshrncc.u16','vqrshrnlo.u16','vqrshrnmi.u16','vqrshrnpl.u16','vqrshrnvs.u16','vqrshrnvc.u16','vqrshrnhi.u16','vqrshrnls.u16','vqrshrnge.u16','vqrshrnlt.u16','vqrshrngt.u16','vqrshrnle.u16',
+ 'vqrshrneq.u32','vqrshrnne.u32','vqrshrncs.u32','vqrshrnhs.u32','vqrshrncc.u32','vqrshrnlo.u32','vqrshrnmi.u32','vqrshrnpl.u32','vqrshrnvs.u32','vqrshrnvc.u32','vqrshrnhi.u32','vqrshrnls.u32','vqrshrnge.u32','vqrshrnlt.u32','vqrshrngt.u32','vqrshrnle.u32',
+ 'vqrshrneq.u64','vqrshrnne.u64','vqrshrncs.u64','vqrshrnhs.u64','vqrshrncc.u64','vqrshrnlo.u64','vqrshrnmi.u64','vqrshrnpl.u64','vqrshrnvs.u64','vqrshrnvc.u64','vqrshrnhi.u64','vqrshrnls.u64','vqrshrnge.u64','vqrshrnlt.u64','vqrshrngt.u64','vqrshrnle.u64',
+
+ 'vrhaddeq.u8','vrhaddne.u8','vrhaddcs.u8','vrhaddhs.u8','vrhaddcc.u8','vrhaddlo.u8','vrhaddmi.u8','vrhaddpl.u8','vrhaddvs.u8','vrhaddvc.u8','vrhaddhi.u8','vrhaddls.u8','vrhaddge.u8','vrhaddlt.u8','vrhaddgt.u8','vrhaddle.u8',
+ 'vrhaddeq.u16','vrhaddne.u16','vrhaddcs.u16','vrhaddhs.u16','vrhaddcc.u16','vrhaddlo.u16','vrhaddmi.u16','vrhaddpl.u16','vrhaddvs.u16','vrhaddvc.u16','vrhaddhi.u16','vrhaddls.u16','vrhaddge.u16','vrhaddlt.u16','vrhaddgt.u16','vrhaddle.u16',
+ 'vrhaddeq.u32','vrhaddne.u32','vrhaddcs.u32','vrhaddhs.u32','vrhaddcc.u32','vrhaddlo.u32','vrhaddmi.u32','vrhaddpl.u32','vrhaddvs.u32','vrhaddvc.u32','vrhaddhi.u32','vrhaddls.u32','vrhaddge.u32','vrhaddlt.u32','vrhaddgt.u32','vrhaddle.u32',
+
+ 'vrshleq.u8','vrshlne.u8','vrshlcs.u8','vrshlhs.u8','vrshlcc.u8','vrshllo.u8','vrshlmi.u8','vrshlpl.u8','vrshlvs.u8','vrshlvc.u8','vrshlhi.u8','vrshlls.u8','vrshlge.u8','vrshllt.u8','vrshlgt.u8','vrshlle.u8',
+ 'vrshleq.u16','vrshlne.u16','vrshlcs.u16','vrshlhs.u16','vrshlcc.u16','vrshllo.u16','vrshlmi.u16','vrshlpl.u16','vrshlvs.u16','vrshlvc.u16','vrshlhi.u16','vrshlls.u16','vrshlge.u16','vrshllt.u16','vrshlgt.u16','vrshlle.u16',
+ 'vrshleq.u32','vrshlne.u32','vrshlcs.u32','vrshlhs.u32','vrshlcc.u32','vrshllo.u32','vrshlmi.u32','vrshlpl.u32','vrshlvs.u32','vrshlvc.u32','vrshlhi.u32','vrshlls.u32','vrshlge.u32','vrshllt.u32','vrshlgt.u32','vrshlle.u32',
+ 'vrshleq.u64','vrshlne.u64','vrshlcs.u64','vrshlhs.u64','vrshlcc.u64','vrshllo.u64','vrshlmi.u64','vrshlpl.u64','vrshlvs.u64','vrshlvc.u64','vrshlhi.u64','vrshlls.u64','vrshlge.u64','vrshllt.u64','vrshlgt.u64','vrshlle.u64',
+
+ 'vrshreq.u8','vrshrne.u8','vrshrcs.u8','vrshrhs.u8','vrshrcc.u8','vrshrlo.u8','vrshrmi.u8','vrshrpl.u8','vrshrvs.u8','vrshrvc.u8','vrshrhi.u8','vrshrls.u8','vrshrge.u8','vrshrlt.u8','vrshrgt.u8','vrshrle.u8',
+ 'vrshreq.u16','vrshrne.u16','vrshrcs.u16','vrshrhs.u16','vrshrcc.u16','vrshrlo.u16','vrshrmi.u16','vrshrpl.u16','vrshrvs.u16','vrshrvc.u16','vrshrhi.u16','vrshrls.u16','vrshrge.u16','vrshrlt.u16','vrshrgt.u16','vrshrle.u16',
+ 'vrshreq.u32','vrshrne.u32','vrshrcs.u32','vrshrhs.u32','vrshrcc.u32','vrshrlo.u32','vrshrmi.u32','vrshrpl.u32','vrshrvs.u32','vrshrvc.u32','vrshrhi.u32','vrshrls.u32','vrshrge.u32','vrshrlt.u32','vrshrgt.u32','vrshrle.u32',
+ 'vrshreq.u64','vrshrne.u64','vrshrcs.u64','vrshrhs.u64','vrshrcc.u64','vrshrlo.u64','vrshrmi.u64','vrshrpl.u64','vrshrvs.u64','vrshrvc.u64','vrshrhi.u64','vrshrls.u64','vrshrge.u64','vrshrlt.u64','vrshrgt.u64','vrshrle.u64',
+
+ 'vrsraeq.u8','vrsrane.u8','vrsracs.u8','vrsrahs.u8','vrsracc.u8','vrsralo.u8','vrsrami.u8','vrsrapl.u8','vrsravs.u8','vrsravc.u8','vrsrahi.u8','vrsrals.u8','vrsrage.u8','vrsralt.u8','vrsragt.u8','vrsrale.u8',
+ 'vrsraeq.u16','vrsrane.u16','vrsracs.u16','vrsrahs.u16','vrsracc.u16','vrsralo.u16','vrsrami.u16','vrsrapl.u16','vrsravs.u16','vrsravc.u16','vrsrahi.u16','vrsrals.u16','vrsrage.u16','vrsralt.u16','vrsragt.u16','vrsrale.u16',
+ 'vrsraeq.u32','vrsrane.u32','vrsracs.u32','vrsrahs.u32','vrsracc.u32','vrsralo.u32','vrsrami.u32','vrsrapl.u32','vrsravs.u32','vrsravc.u32','vrsrahi.u32','vrsrals.u32','vrsrage.u32','vrsralt.u32','vrsragt.u32','vrsrale.u32',
+ 'vrsraeq.u64','vrsrane.u64','vrsracs.u64','vrsrahs.u64','vrsracc.u64','vrsralo.u64','vrsrami.u64','vrsrapl.u64','vrsravs.u64','vrsravc.u64','vrsrahi.u64','vrsrals.u64','vrsrage.u64','vrsralt.u64','vrsragt.u64','vrsrale.u64',
+ ),
+ /* Conditional VFPv3 & NEON SIMD Floating-Point Instructions */
+ 34 => array(
+ 'vabdeq.f32','vabdne.f32','vabdcs.f32','vabdhs.f32','vabdcc.f32','vabdlo.f32','vabdmi.f32','vabdpl.f32','vabdvs.f32','vabdvc.f32','vabdhi.f32','vabdls.f32','vabdge.f32','vabdlt.f32','vabdgt.f32','vabdle.f32',
+
+ 'vabseq.f32','vabsne.f32','vabscs.f32','vabshs.f32','vabscc.f32','vabslo.f32','vabsmi.f32','vabspl.f32','vabsvs.f32','vabsvc.f32','vabshi.f32','vabsls.f32','vabsge.f32','vabslt.f32','vabsgt.f32','vabsle.f32',
+ 'vabseq.f64','vabsne.f64','vabscs.f64','vabshs.f64','vabscc.f64','vabslo.f64','vabsmi.f64','vabspl.f64','vabsvs.f64','vabsvc.f64','vabshi.f64','vabsls.f64','vabsge.f64','vabslt.f64','vabsgt.f64','vabsle.f64',
+
+ 'vacgeeq.f32','vacgene.f32','vacgecs.f32','vacgehs.f32','vacgecc.f32','vacgelo.f32','vacgemi.f32','vacgepl.f32','vacgevs.f32','vacgevc.f32','vacgehi.f32','vacgels.f32','vacgege.f32','vacgelt.f32','vacgegt.f32','vacgele.f32',
+ 'vacgteq.f32','vacgtne.f32','vacgtcs.f32','vacgths.f32','vacgtcc.f32','vacgtlo.f32','vacgtmi.f32','vacgtpl.f32','vacgtvs.f32','vacgtvc.f32','vacgthi.f32','vacgtls.f32','vacgtge.f32','vacgtlt.f32','vacgtgt.f32','vacgtle.f32',
+ 'vacleeq.f32','vaclene.f32','vaclecs.f32','vaclehs.f32','vaclecc.f32','vaclelo.f32','vaclemi.f32','vaclepl.f32','vaclevs.f32','vaclevc.f32','vaclehi.f32','vaclels.f32','vaclege.f32','vaclelt.f32','vaclegt.f32','vaclele.f32',
+ 'vaclteq.f32','vacltne.f32','vacltcs.f32','vaclths.f32','vacltcc.f32','vacltlo.f32','vacltmi.f32','vacltpl.f32','vacltvs.f32','vacltvc.f32','vaclthi.f32','vacltls.f32','vacltge.f32','vacltlt.f32','vacltgt.f32','vacltle.f32',
+
+ 'vaddeq.f32','vaddne.f32','vaddcs.f32','vaddhs.f32','vaddcc.f32','vaddlo.f32','vaddmi.f32','vaddpl.f32','vaddvs.f32','vaddvc.f32','vaddhi.f32','vaddls.f32','vaddge.f32','vaddlt.f32','vaddgt.f32','vaddle.f32',
+ 'vaddeq.f64','vaddne.f64','vaddcs.f64','vaddhs.f64','vaddcc.f64','vaddlo.f64','vaddmi.f64','vaddpl.f64','vaddvs.f64','vaddvc.f64','vaddhi.f64','vaddls.f64','vaddge.f64','vaddlt.f64','vaddgt.f64','vaddle.f64',
+
+ 'vceqeq.f32','vceqne.f32','vceqcs.f32','vceqhs.f32','vceqcc.f32','vceqlo.f32','vceqmi.f32','vceqpl.f32','vceqvs.f32','vceqvc.f32','vceqhi.f32','vceqls.f32','vceqge.f32','vceqlt.f32','vceqgt.f32','vceqle.f32',
+ 'vcgeeq.f32','vcgene.f32','vcgecs.f32','vcgehs.f32','vcgecc.f32','vcgelo.f32','vcgemi.f32','vcgepl.f32','vcgevs.f32','vcgevc.f32','vcgehi.f32','vcgels.f32','vcgege.f32','vcgelt.f32','vcgegt.f32','vcgele.f32',
+ 'vcleeq.f32','vclene.f32','vclecs.f32','vclehs.f32','vclecc.f32','vclelo.f32','vclemi.f32','vclepl.f32','vclevs.f32','vclevc.f32','vclehi.f32','vclels.f32','vclege.f32','vclelt.f32','vclegt.f32','vclele.f32',
+ 'vcgteq.f32','vcgtne.f32','vcgtcs.f32','vcgths.f32','vcgtcc.f32','vcgtlo.f32','vcgtmi.f32','vcgtpl.f32','vcgtvs.f32','vcgtvc.f32','vcgthi.f32','vcgtls.f32','vcgtge.f32','vcgtlt.f32','vcgtgt.f32','vcgtle.f32',
+ 'vclteq.f32','vcltne.f32','vcltcs.f32','vclths.f32','vcltcc.f32','vcltlo.f32','vcltmi.f32','vcltpl.f32','vcltvs.f32','vcltvc.f32','vclthi.f32','vcltls.f32','vcltge.f32','vcltlt.f32','vcltgt.f32','vcltle.f32',
+
+ 'vcmpeq.f32','vcmpne.f32','vcmpcs.f32','vcmphs.f32','vcmpcc.f32','vcmplo.f32','vcmpmi.f32','vcmppl.f32','vcmpvs.f32','vcmpvc.f32','vcmphi.f32','vcmpls.f32','vcmpge.f32','vcmplt.f32','vcmpgt.f32','vcmple.f32',
+ 'vcmpeq.f64','vcmpne.f64','vcmpcs.f64','vcmphs.f64','vcmpcc.f64','vcmplo.f64','vcmpmi.f64','vcmppl.f64','vcmpvs.f64','vcmpvc.f64','vcmphi.f64','vcmpls.f64','vcmpge.f64','vcmplt.f64','vcmpgt.f64','vcmple.f64',
+
+ 'vcmpeeq.f32','vcmpene.f32','vcmpecs.f32','vcmpehs.f32','vcmpecc.f32','vcmpelo.f32','vcmpemi.f32','vcmpepl.f32','vcmpevs.f32','vcmpevc.f32','vcmpehi.f32','vcmpels.f32','vcmpege.f32','vcmpelt.f32','vcmpegt.f32','vcmpele.f32',
+ 'vcmpeeq.f64','vcmpene.f64','vcmpecs.f64','vcmpehs.f64','vcmpecc.f64','vcmpelo.f64','vcmpemi.f64','vcmpepl.f64','vcmpevs.f64','vcmpevc.f64','vcmpehi.f64','vcmpels.f64','vcmpege.f64','vcmpelt.f64','vcmpegt.f64','vcmpele.f64',
+
+ 'vcvteq.s16.f32','vcvtne.s16.f32','vcvtcs.s16.f32','vcvths.s16.f32','vcvtcc.s16.f32','vcvtlo.s16.f32','vcvtmi.s16.f32','vcvtpl.s16.f32','vcvtvs.s16.f32','vcvtvc.s16.f32','vcvthi.s16.f32','vcvtls.s16.f32','vcvtge.s16.f32','vcvtlt.s16.f32','vcvtgt.s16.f32','vcvtle.s16.f32',
+ 'vcvteq.s16.f64','vcvtne.s16.f64','vcvtcs.s16.f64','vcvths.s16.f64','vcvtcc.s16.f64','vcvtlo.s16.f64','vcvtmi.s16.f64','vcvtpl.s16.f64','vcvtvs.s16.f64','vcvtvc.s16.f64','vcvthi.s16.f64','vcvtls.s16.f64','vcvtge.s16.f64','vcvtlt.s16.f64','vcvtgt.s16.f64','vcvtle.s16.f64',
+ 'vcvteq.s32.f32','vcvtne.s32.f32','vcvtcs.s32.f32','vcvths.s32.f32','vcvtcc.s32.f32','vcvtlo.s32.f32','vcvtmi.s32.f32','vcvtpl.s32.f32','vcvtvs.s32.f32','vcvtvc.s32.f32','vcvthi.s32.f32','vcvtls.s32.f32','vcvtge.s32.f32','vcvtlt.s32.f32','vcvtgt.s32.f32','vcvtle.s32.f32',
+ 'vcvteq.s32.f64','vcvtne.s32.f64','vcvtcs.s32.f64','vcvths.s32.f64','vcvtcc.s32.f64','vcvtlo.s32.f64','vcvtmi.s32.f64','vcvtpl.s32.f64','vcvtvs.s32.f64','vcvtvc.s32.f64','vcvthi.s32.f64','vcvtls.s32.f64','vcvtge.s32.f64','vcvtlt.s32.f64','vcvtgt.s32.f64','vcvtle.s32.f64',
+ 'vcvteq.u16.f32','vcvtne.u16.f32','vcvtcs.u16.f32','vcvths.u16.f32','vcvtcc.u16.f32','vcvtlo.u16.f32','vcvtmi.u16.f32','vcvtpl.u16.f32','vcvtvs.u16.f32','vcvtvc.u16.f32','vcvthi.u16.f32','vcvtls.u16.f32','vcvtge.u16.f32','vcvtlt.u16.f32','vcvtgt.u16.f32','vcvtle.u16.f32',
+ 'vcvteq.u16.f64','vcvtne.u16.f64','vcvtcs.u16.f64','vcvths.u16.f64','vcvtcc.u16.f64','vcvtlo.u16.f64','vcvtmi.u16.f64','vcvtpl.u16.f64','vcvtvs.u16.f64','vcvtvc.u16.f64','vcvthi.u16.f64','vcvtls.u16.f64','vcvtge.u16.f64','vcvtlt.u16.f64','vcvtgt.u16.f64','vcvtle.u16.f64',
+ 'vcvteq.u32.f32','vcvtne.u32.f32','vcvtcs.u32.f32','vcvths.u32.f32','vcvtcc.u32.f32','vcvtlo.u32.f32','vcvtmi.u32.f32','vcvtpl.u32.f32','vcvtvs.u32.f32','vcvtvc.u32.f32','vcvthi.u32.f32','vcvtls.u32.f32','vcvtge.u32.f32','vcvtlt.u32.f32','vcvtgt.u32.f32','vcvtle.u32.f32',
+ 'vcvteq.u32.f64','vcvtne.u32.f64','vcvtcs.u32.f64','vcvths.u32.f64','vcvtcc.u32.f64','vcvtlo.u32.f64','vcvtmi.u32.f64','vcvtpl.u32.f64','vcvtvs.u32.f64','vcvtvc.u32.f64','vcvthi.u32.f64','vcvtls.u32.f64','vcvtge.u32.f64','vcvtlt.u32.f64','vcvtgt.u32.f64','vcvtle.u32.f64',
+ 'vcvteq.f16.f32','vcvtne.f16.f32','vcvtcs.f16.f32','vcvths.f16.f32','vcvtcc.f16.f32','vcvtlo.f16.f32','vcvtmi.f16.f32','vcvtpl.f16.f32','vcvtvs.f16.f32','vcvtvc.f16.f32','vcvthi.f16.f32','vcvtls.f16.f32','vcvtge.f16.f32','vcvtlt.f16.f32','vcvtgt.f16.f32','vcvtle.f16.f32',
+ 'vcvteq.f32.s32','vcvtne.f32.s32','vcvtcs.f32.s32','vcvths.f32.s32','vcvtcc.f32.s32','vcvtlo.f32.s32','vcvtmi.f32.s32','vcvtpl.f32.s32','vcvtvs.f32.s32','vcvtvc.f32.s32','vcvthi.f32.s32','vcvtls.f32.s32','vcvtge.f32.s32','vcvtlt.f32.s32','vcvtgt.f32.s32','vcvtle.f32.s32',
+ 'vcvteq.f32.u32','vcvtne.f32.u32','vcvtcs.f32.u32','vcvths.f32.u32','vcvtcc.f32.u32','vcvtlo.f32.u32','vcvtmi.f32.u32','vcvtpl.f32.u32','vcvtvs.f32.u32','vcvtvc.f32.u32','vcvthi.f32.u32','vcvtls.f32.u32','vcvtge.f32.u32','vcvtlt.f32.u32','vcvtgt.f32.u32','vcvtle.f32.u32',
+ 'vcvteq.f32.f16','vcvtne.f32.f16','vcvtcs.f32.f16','vcvths.f32.f16','vcvtcc.f32.f16','vcvtlo.f32.f16','vcvtmi.f32.f16','vcvtpl.f32.f16','vcvtvs.f32.f16','vcvtvc.f32.f16','vcvthi.f32.f16','vcvtls.f32.f16','vcvtge.f32.f16','vcvtlt.f32.f16','vcvtgt.f32.f16','vcvtle.f32.f16',
+ 'vcvteq.f32.f64','vcvtne.f32.f64','vcvtcs.f32.f64','vcvths.f32.f64','vcvtcc.f32.f64','vcvtlo.f32.f64','vcvtmi.f32.f64','vcvtpl.f32.f64','vcvtvs.f32.f64','vcvtvc.f32.f64','vcvthi.f32.f64','vcvtls.f32.f64','vcvtge.f32.f64','vcvtlt.f32.f64','vcvtgt.f32.f64','vcvtle.f32.f64',
+ 'vcvteq.f64.s32','vcvtne.f64.s32','vcvtcs.f64.s32','vcvths.f64.s32','vcvtcc.f64.s32','vcvtlo.f64.s32','vcvtmi.f64.s32','vcvtpl.f64.s32','vcvtvs.f64.s32','vcvtvc.f64.s32','vcvthi.f64.s32','vcvtls.f64.s32','vcvtge.f64.s32','vcvtlt.f64.s32','vcvtgt.f64.s32','vcvtle.f64.s32',
+ 'vcvteq.f64.u32','vcvtne.f64.u32','vcvtcs.f64.u32','vcvths.f64.u32','vcvtcc.f64.u32','vcvtlo.f64.u32','vcvtmi.f64.u32','vcvtpl.f64.u32','vcvtvs.f64.u32','vcvtvc.f64.u32','vcvthi.f64.u32','vcvtls.f64.u32','vcvtge.f64.u32','vcvtlt.f64.u32','vcvtgt.f64.u32','vcvtle.f64.u32',
+ 'vcvteq.f64.f32','vcvtne.f64.f32','vcvtcs.f64.f32','vcvths.f64.f32','vcvtcc.f64.f32','vcvtlo.f64.f32','vcvtmi.f64.f32','vcvtpl.f64.f32','vcvtvs.f64.f32','vcvtvc.f64.f32','vcvthi.f64.f32','vcvtls.f64.f32','vcvtge.f64.f32','vcvtlt.f64.f32','vcvtgt.f64.f32','vcvtle.f64.f32',
+
+ 'vcvtreq.s32.f32','vcvtrne.s32.f32','vcvtrcs.s32.f32','vcvtrhs.s32.f32','vcvtrcc.s32.f32','vcvtrlo.s32.f32','vcvtrmi.s32.f32','vcvtrpl.s32.f32','vcvtrvs.s32.f32','vcvtrvc.s32.f32','vcvtrhi.s32.f32','vcvtrls.s32.f32','vcvtrge.s32.f32','vcvtrlt.s32.f32','vcvtrgt.s32.f32','vcvtrle.s32.f32',
+ 'vcvtreq.s32.f64','vcvtrne.s32.f64','vcvtrcs.s32.f64','vcvtrhs.s32.f64','vcvtrcc.s32.f64','vcvtrlo.s32.f64','vcvtrmi.s32.f64','vcvtrpl.s32.f64','vcvtrvs.s32.f64','vcvtrvc.s32.f64','vcvtrhi.s32.f64','vcvtrls.s32.f64','vcvtrge.s32.f64','vcvtrlt.s32.f64','vcvtrgt.s32.f64','vcvtrle.s32.f64',
+ 'vcvtreq.u32.f32','vcvtrne.u32.f32','vcvtrcs.u32.f32','vcvtrhs.u32.f32','vcvtrcc.u32.f32','vcvtrlo.u32.f32','vcvtrmi.u32.f32','vcvtrpl.u32.f32','vcvtrvs.u32.f32','vcvtrvc.u32.f32','vcvtrhi.u32.f32','vcvtrls.u32.f32','vcvtrge.u32.f32','vcvtrlt.u32.f32','vcvtrgt.u32.f32','vcvtrle.u32.f32',
+ 'vcvtreq.u32.f64','vcvtrne.u32.f64','vcvtrcs.u32.f64','vcvtrhs.u32.f64','vcvtrcc.u32.f64','vcvtrlo.u32.f64','vcvtrmi.u32.f64','vcvtrpl.u32.f64','vcvtrvs.u32.f64','vcvtrvc.u32.f64','vcvtrhi.u32.f64','vcvtrls.u32.f64','vcvtrge.u32.f64','vcvtrlt.u32.f64','vcvtrgt.u32.f64','vcvtrle.u32.f64',
+
+ 'vcvtbeq.f16.f32','vcvtbne.f16.f32','vcvtbcs.f16.f32','vcvtbhs.f16.f32','vcvtbcc.f16.f32','vcvtblo.f16.f32','vcvtbmi.f16.f32','vcvtbpl.f16.f32','vcvtbvs.f16.f32','vcvtbvc.f16.f32','vcvtbhi.f16.f32','vcvtbls.f16.f32','vcvtbge.f16.f32','vcvtblt.f16.f32','vcvtbgt.f16.f32','vcvtble.f16.f32',
+ 'vcvtbeq.f32.f16','vcvtbne.f32.f16','vcvtbcs.f32.f16','vcvtbhs.f32.f16','vcvtbcc.f32.f16','vcvtblo.f32.f16','vcvtbmi.f32.f16','vcvtbpl.f32.f16','vcvtbvs.f32.f16','vcvtbvc.f32.f16','vcvtbhi.f32.f16','vcvtbls.f32.f16','vcvtbge.f32.f16','vcvtblt.f32.f16','vcvtbgt.f32.f16','vcvtble.f32.f16',
+
+ 'vcvtteq.f16.f32','vcvttne.f16.f32','vcvttcs.f16.f32','vcvtths.f16.f32','vcvttcc.f16.f32','vcvttlo.f16.f32','vcvttmi.f16.f32','vcvttpl.f16.f32','vcvttvs.f16.f32','vcvttvc.f16.f32','vcvtthi.f16.f32','vcvttls.f16.f32','vcvttge.f16.f32','vcvttlt.f16.f32','vcvttgt.f16.f32','vcvttle.f16.f32',
+ 'vcvtteq.f32.f16','vcvttne.f32.f16','vcvttcs.f32.f16','vcvtths.f32.f16','vcvttcc.f32.f16','vcvttlo.f32.f16','vcvttmi.f32.f16','vcvttpl.f32.f16','vcvttvs.f32.f16','vcvttvc.f32.f16','vcvtthi.f32.f16','vcvttls.f32.f16','vcvttge.f32.f16','vcvttlt.f32.f16','vcvttgt.f32.f16','vcvttle.f32.f16',
+
+ 'vdiveq.f32','vdivne.f32','vdivcs.f32','vdivhs.f32','vdivcc.f32','vdivlo.f32','vdivmi.f32','vdivpl.f32','vdivvs.f32','vdivvc.f32','vdivhi.f32','vdivls.f32','vdivge.f32','vdivlt.f32','vdivgt.f32','vdivle.f32',
+ 'vdiveq.f64','vdivne.f64','vdivcs.f64','vdivhs.f64','vdivcc.f64','vdivlo.f64','vdivmi.f64','vdivpl.f64','vdivvs.f64','vdivvc.f64','vdivhi.f64','vdivls.f64','vdivge.f64','vdivlt.f64','vdivgt.f64','vdivle.f64',
+
+ 'vmaxeq.f32','vmaxne.f32','vmaxcs.f32','vmaxhs.f32','vmaxcc.f32','vmaxlo.f32','vmaxmi.f32','vmaxpl.f32','vmaxvs.f32','vmaxvc.f32','vmaxhi.f32','vmaxls.f32','vmaxge.f32','vmaxlt.f32','vmaxgt.f32','vmaxle.f32',
+ 'vmineq.f32','vminne.f32','vmincs.f32','vminhs.f32','vmincc.f32','vminlo.f32','vminmi.f32','vminpl.f32','vminvs.f32','vminvc.f32','vminhi.f32','vminls.f32','vminge.f32','vminlt.f32','vmingt.f32','vminle.f32',
+
+ 'vmlaeq.f32','vmlane.f32','vmlacs.f32','vmlahs.f32','vmlacc.f32','vmlalo.f32','vmlami.f32','vmlapl.f32','vmlavs.f32','vmlavc.f32','vmlahi.f32','vmlals.f32','vmlage.f32','vmlalt.f32','vmlagt.f32','vmlale.f32',
+ 'vmlaeq.f64','vmlane.f64','vmlacs.f64','vmlahs.f64','vmlacc.f64','vmlalo.f64','vmlami.f64','vmlapl.f64','vmlavs.f64','vmlavc.f64','vmlahi.f64','vmlals.f64','vmlage.f64','vmlalt.f64','vmlagt.f64','vmlale.f64',
+
+ 'vmlseq.f32','vmlsne.f32','vmlscs.f32','vmlshs.f32','vmlscc.f32','vmlslo.f32','vmlsmi.f32','vmlspl.f32','vmlsvs.f32','vmlsvc.f32','vmlshi.f32','vmlsls.f32','vmlsge.f32','vmlslt.f32','vmlsgt.f32','vmlsle.f32',
+ 'vmlseq.f64','vmlsne.f64','vmlscs.f64','vmlshs.f64','vmlscc.f64','vmlslo.f64','vmlsmi.f64','vmlspl.f64','vmlsvs.f64','vmlsvc.f64','vmlshi.f64','vmlsls.f64','vmlsge.f64','vmlslt.f64','vmlsgt.f64','vmlsle.f64',
+
+ 'vmuleq.f32','vmulne.f32','vmulcs.f32','vmulhs.f32','vmulcc.f32','vmullo.f32','vmulmi.f32','vmulpl.f32','vmulvs.f32','vmulvc.f32','vmulhi.f32','vmulls.f32','vmulge.f32','vmullt.f32','vmulgt.f32','vmulle.f32',
+ 'vmuleq.f64','vmulne.f64','vmulcs.f64','vmulhs.f64','vmulcc.f64','vmullo.f64','vmulmi.f64','vmulpl.f64','vmulvs.f64','vmulvc.f64','vmulhi.f64','vmulls.f64','vmulge.f64','vmullt.f64','vmulgt.f64','vmulle.f64',
+
+ 'vnegeq.f32','vnegne.f32','vnegcs.f32','vneghs.f32','vnegcc.f32','vneglo.f32','vnegmi.f32','vnegpl.f32','vnegvs.f32','vnegvc.f32','vneghi.f32','vnegls.f32','vnegge.f32','vneglt.f32','vneggt.f32','vnegle.f32',
+ 'vnegeq.f64','vnegne.f64','vnegcs.f64','vneghs.f64','vnegcc.f64','vneglo.f64','vnegmi.f64','vnegpl.f64','vnegvs.f64','vnegvc.f64','vneghi.f64','vnegls.f64','vnegge.f64','vneglt.f64','vneggt.f64','vnegle.f64',
+
+ 'vnmlaeq.f32','vnmlane.f32','vnmlacs.f32','vnmlahs.f32','vnmlacc.f32','vnmlalo.f32','vnmlami.f32','vnmlapl.f32','vnmlavs.f32','vnmlavc.f32','vnmlahi.f32','vnmlals.f32','vnmlage.f32','vnmlalt.f32','vnmlagt.f32','vnmlale.f32',
+ 'vnmlaeq.f64','vnmlane.f64','vnmlacs.f64','vnmlahs.f64','vnmlacc.f64','vnmlalo.f64','vnmlami.f64','vnmlapl.f64','vnmlavs.f64','vnmlavc.f64','vnmlahi.f64','vnmlals.f64','vnmlage.f64','vnmlalt.f64','vnmlagt.f64','vnmlale.f64',
+
+ 'vnmlseq.f32','vnmlsne.f32','vnmlscs.f32','vnmlshs.f32','vnmlscc.f32','vnmlslo.f32','vnmlsmi.f32','vnmlspl.f32','vnmlsvs.f32','vnmlsvc.f32','vnmlshi.f32','vnmlsls.f32','vnmlsge.f32','vnmlslt.f32','vnmlsgt.f32','vnmlsle.f32',
+ 'vnmlseq.f64','vnmlsne.f64','vnmlscs.f64','vnmlshs.f64','vnmlscc.f64','vnmlslo.f64','vnmlsmi.f64','vnmlspl.f64','vnmlsvs.f64','vnmlsvc.f64','vnmlshi.f64','vnmlsls.f64','vnmlsge.f64','vnmlslt.f64','vnmlsgt.f64','vnmlsle.f64',
+
+ 'vnmuleq.f64','vnmulne.f64','vnmulcs.f64','vnmulhs.f64','vnmulcc.f64','vnmullo.f64','vnmulmi.f64','vnmulpl.f64','vnmulvs.f64','vnmulvc.f64','vnmulhi.f64','vnmulls.f64','vnmulge.f64','vnmullt.f64','vnmulgt.f64','vnmulle.f64',
+ 'vnmuleq.f32','vnmulne.f32','vnmulcs.f32','vnmulhs.f32','vnmulcc.f32','vnmullo.f32','vnmulmi.f32','vnmulpl.f32','vnmulvs.f32','vnmulvc.f32','vnmulhi.f32','vnmulls.f32','vnmulge.f32','vnmullt.f32','vnmulgt.f32','vnmulle.f32',
+
+ 'vpaddeq.f32','vpaddne.f32','vpaddcs.f32','vpaddhs.f32','vpaddcc.f32','vpaddlo.f32','vpaddmi.f32','vpaddpl.f32','vpaddvs.f32','vpaddvc.f32','vpaddhi.f32','vpaddls.f32','vpaddge.f32','vpaddlt.f32','vpaddgt.f32','vpaddle.f32',
+
+ 'vpmaxeq.f32','vpmaxne.f32','vpmaxcs.f32','vpmaxhs.f32','vpmaxcc.f32','vpmaxlo.f32','vpmaxmi.f32','vpmaxpl.f32','vpmaxvs.f32','vpmaxvc.f32','vpmaxhi.f32','vpmaxls.f32','vpmaxge.f32','vpmaxlt.f32','vpmaxgt.f32','vpmaxle.f32',
+ 'vpmineq.f32','vpminne.f32','vpmincs.f32','vpminhs.f32','vpmincc.f32','vpminlo.f32','vpminmi.f32','vpminpl.f32','vpminvs.f32','vpminvc.f32','vpminhi.f32','vpminls.f32','vpminge.f32','vpminlt.f32','vpmingt.f32','vpminle.f32',
+
+ 'vrecpeeq.u32','vrecpene.u32','vrecpecs.u32','vrecpehs.u32','vrecpecc.u32','vrecpelo.u32','vrecpemi.u32','vrecpepl.u32','vrecpevs.u32','vrecpevc.u32','vrecpehi.u32','vrecpels.u32','vrecpege.u32','vrecpelt.u32','vrecpegt.u32','vrecpele.u32',
+ 'vrecpeeq.f32','vrecpene.f32','vrecpecs.f32','vrecpehs.f32','vrecpecc.f32','vrecpelo.f32','vrecpemi.f32','vrecpepl.f32','vrecpevs.f32','vrecpevc.f32','vrecpehi.f32','vrecpels.f32','vrecpege.f32','vrecpelt.f32','vrecpegt.f32','vrecpele.f32',
+ 'vrecpseq.f32','vrecpsne.f32','vrecpscs.f32','vrecpshs.f32','vrecpscc.f32','vrecpslo.f32','vrecpsmi.f32','vrecpspl.f32','vrecpsvs.f32','vrecpsvc.f32','vrecpshi.f32','vrecpsls.f32','vrecpsge.f32','vrecpslt.f32','vrecpsgt.f32','vrecpsle.f32',
+
+ 'vrsqrteeq.u32','vrsqrtene.u32','vrsqrtecs.u32','vrsqrtehs.u32','vrsqrtecc.u32','vrsqrtelo.u32','vrsqrtemi.u32','vrsqrtepl.u32','vrsqrtevs.u32','vrsqrtevc.u32','vrsqrtehi.u32','vrsqrtels.u32','vrsqrtege.u32','vrsqrtelt.u32','vrsqrtegt.u32','vrsqrtele.u32',
+ 'vrsqrteeq.f32','vrsqrtene.f32','vrsqrtecs.f32','vrsqrtehs.f32','vrsqrtecc.f32','vrsqrtelo.f32','vrsqrtemi.f32','vrsqrtepl.f32','vrsqrtevs.f32','vrsqrtevc.f32','vrsqrtehi.f32','vrsqrtels.f32','vrsqrtege.f32','vrsqrtelt.f32','vrsqrtegt.f32','vrsqrtele.f32',
+ 'vrsqrtseq.f32','vrsqrtsne.f32','vrsqrtscs.f32','vrsqrtshs.f32','vrsqrtscc.f32','vrsqrtslo.f32','vrsqrtsmi.f32','vrsqrtspl.f32','vrsqrtsvs.f32','vrsqrtsvc.f32','vrsqrtshi.f32','vrsqrtsls.f32','vrsqrtsge.f32','vrsqrtslt.f32','vrsqrtsgt.f32','vrsqrtsle.f32',
+
+ 'vsqrteq.f32','vsqrtne.f32','vsqrtcs.f32','vsqrths.f32','vsqrtcc.f32','vsqrtlo.f32','vsqrtmi.f32','vsqrtpl.f32','vsqrtvs.f32','vsqrtvc.f32','vsqrthi.f32','vsqrtls.f32','vsqrtge.f32','vsqrtlt.f32','vsqrtgt.f32','vsqrtle.f32',
+ 'vsqrteq.f64','vsqrtne.f64','vsqrtcs.f64','vsqrths.f64','vsqrtcc.f64','vsqrtlo.f64','vsqrtmi.f64','vsqrtpl.f64','vsqrtvs.f64','vsqrtvc.f64','vsqrthi.f64','vsqrtls.f64','vsqrtge.f64','vsqrtlt.f64','vsqrtgt.f64','vsqrtle.f64',
+
+ 'vsubeq.f32','vsubne.f32','vsubcs.f32','vsubhs.f32','vsubcc.f32','vsublo.f32','vsubmi.f32','vsubpl.f32','vsubvs.f32','vsubvc.f32','vsubhi.f32','vsubls.f32','vsubge.f32','vsublt.f32','vsubgt.f32','vsuble.f32',
+ 'vsubeq.f64','vsubne.f64','vsubcs.f64','vsubhs.f64','vsubcc.f64','vsublo.f64','vsubmi.f64','vsubpl.f64','vsubvs.f64','vsubvc.f64','vsubhi.f64','vsubls.f64','vsubge.f64','vsublt.f64','vsubgt.f64','vsuble.f64'
+ ),
+ /* Registers */
+ 35 => array(
+ /* General-Purpose Registers */
+ 'r0','r1','r2','r3','r4','r5','r6','r7',
+ 'r8','r9','r10','r11','r12','r13','r14','r15',
+ /* Scratch Registers */
+ 'a1','a2','a3','a4',
+ /* Variable Registers */
+ 'v1','v2','v3','v4','v5','v6','v7','v8',
+ /* Other Synonims for General-Purpose Registers */
+ 'sb','sl','fp','ip','sp','lr','pc',
+ /* WMMX Data Registers */
+ 'wr0','wr1','wr2','wr3','wr4','wr5','wr6','wr7',
+ 'wr8','wr9','wr10','wr11','wr12','wr13','wr14','wr15',
+ /* WMMX Control Registers */
+ 'wcid','wcon','wcssf','wcasf',
+ /* WMMX-Mapped General-Purpose Registers */
+ 'wcgr0','wcgr1','wcgr2','wcgr3',
+ /* VFPv3 Registers */
+ 's0','s1','s2','s3','s4','s5','s6','s7',
+ 's8','s9','s10','s11','s12','s13','s14','s15',
+ 's16','s17','s18','s19','s20','s21','s22','s23',
+ 's24','s25','s26','s27','s28','s29','s30','s31',
+ /* VFPv3/NEON Registers */
+ 'd0','d1','d2','d3','d4','d5','d6','d7',
+ 'd8','d9','d10','d11','d12','d13','d14','d15',
+ 'd16','d17','d18','d19','d20','d21','d22','d23',
+ 'd24','d25','d26','d27','d28','d29','d30','d31',
+ /* NEON Registers */
+ 'q0','q1','q2','q3','q4','q5','q6','q7',
+ 'q8','q9','q10','q11','q12','q13','q14','q15'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '[', ']', '(', ')',
+ '+', '-', '*', '/', '%',
+ '.', ',', ';', ':'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ 14 => false,
+ 15 => false,
+ 16 => false,
+ 17 => false,
+ 18 => false,
+ 19 => false,
+ 20 => false,
+ 21 => false,
+ 22 => false,
+ 23 => false,
+ 24 => false,
+ 25 => false,
+ 26 => false,
+ 27 => false,
+ 28 => false,
+ 29 => false,
+ 30 => false,
+ 31 => false,
+ 32 => false,
+ 33 => false,
+ 34 => false,
+ 35 => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ /* Unconditional Data Processing Instructions */
+ 1 => 'color: #00007f; font-weight: normal; font-style: normal;',
+ /* Conditional Data Processing Instructions */
+ 2 => 'color: #00007f; font-weight: normal; font-style: italic;',
+ /* Unconditional Memory Access Instructions */
+ 3 => 'color: #00007f; font-weight: normal; font-style: normal;',
+ /* Conditional Memory Access Instructions */
+ 4 => 'color: #00007f; font-weight: normal; font-style: italic;',
+ /* Unconditional Flags Changing Instructions */
+ 5 => 'color: #00007f; font-weight: bold; font-style: normal;',
+ /* Conditional Flags Changing Instructions */
+ 6 => 'color: #00007f; font-weight: bold; font-style: italic;',
+ /* Unconditional Flow Control Instructions */
+ 7 => 'color: #0000ff; font-weight: normal; font-style: normal;',
+ /* Conditional Flow Control Instructions */
+ 8 => 'color: #0000ff; font-weight: normal; font-style: italic;',
+ /* Unconditional Syncronization Instructions */
+ 9 => 'color: #00007f; font-weight: normal; font-style: normal;',
+ /* Conditional Syncronization Instructions */
+ 10 => 'color: #00007f; font-weight: normal; font-style: italic;',
+ /* Unonditional ARMv6 SIMD */
+ 11 => 'color: #b00040; font-weight: normal; font-style: normal;',
+ /* Conditional ARMv6 SIMD */
+ 12 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Unconditional Coprocessor Instructions */
+ 13 => 'color: #00007f; font-weight: normal; font-style: normal;',
+ /* Conditional Coprocessor Instructions */
+ 14 => 'color: #00007f; font-weight: bold; font-style: italic;',
+ /* Unconditional System Instructions */
+ 15 => 'color: #00007f; font-weight: normal; font-style: normal;',
+ /* Conditional System Instructions */
+ 16 => 'color: #00007f; font-weight: bold; font-style: italic;',
+ /* Unconditional WMMX/WMMX2 SIMD Instructions */
+ 17 => 'color: #b00040; font-weight: normal; font-style: normal;',
+ /* Conditional WMMX/WMMX2 SIMD Instructions */
+ 18 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Unconditional VFPv3 & NEON SIMD Memory Access Instructions */
+ 19 => 'color: #b00040; font-weight: normal; font-style: normal;',
+ /* Unconditional NEON SIMD Logical Instructions */
+ 20 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Unconditional NEON SIMD ARM Registers Interop Instructions */
+ 21 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Unconditional NEON SIMD Bit/Byte-Level Instructions */
+ 22 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Unconditional NEON SIMD Universal Integer Instructions */
+ 23 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Unconditional NEON SIMD Signed Integer Instructions */
+ 24 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Unconditional NEON SIMD Unsigned Integer Instructions */
+ 25 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Unconditional VFPv3 & NEON SIMD Floating-Point Instructions */
+ 26 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Conditional VFPv3 & NEON SIMD Memory Access Instructions */
+ 27 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Conditional NEON SIMD Logical Instructions */
+ 28 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Conditional NEON SIMD ARM Registers Interop Instructions */
+ 29 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Conditional NEON SIMD Bit/Byte-Level Instructions */
+ 30 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Conditional NEON SIMD Universal Integer Instructions */
+ 31 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Conditional NEON SIMD Signed Integer Instructions */
+ 32 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Conditional NEON SIMD Unsigned Integer Instructions */
+ 33 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Conditional VFPv3 & NEON SIMD Floating-Point Instructions */
+ 34 => 'color: #b00040; font-weight: normal; font-style: italic;',
+ /* Registers */
+ 35 => 'color: #46aa03; font-weight: bold;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666; font-style: italic;',
+ 2 => 'color: #adadad; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #009900; font-weight: bold;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #7f007f;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #339933;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => '',
+ 10 => '',
+ 11 => '',
+ 12 => '',
+ 13 => '',
+ 14 => '',
+ 15 => '',
+ 16 => '',
+ 17 => '',
+ 18 => '',
+ 19 => '',
+ 20 => '',
+ 21 => '',
+ 22 => '',
+ 23 => '',
+ 24 => '',
+ 25 => '',
+ 26 => '',
+ 27 => '',
+ 28 => '',
+ 29 => '',
+ 30 => '',
+ 31 => '',
+ 32 => '',
+ 33 => '',
+ 34 => '',
+ 35 => ''
+ ),
+ 'NUMBERS' =>
+ GESHI_NUMBER_BIN_PREFIX_PERCENT |
+ GESHI_NUMBER_BIN_SUFFIX |
+ GESHI_NUMBER_HEX_PREFIX |
+ GESHI_NUMBER_HEX_SUFFIX |
+ GESHI_NUMBER_OCT_SUFFIX |
+ GESHI_NUMBER_INT_BASIC |
+ GESHI_NUMBER_FLT_NONSCI |
+ GESHI_NUMBER_FLT_NONSCI_F |
+ GESHI_NUMBER_FLT_SCI_ZERO,
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 8,
+ 'PARSER_CONTROL' => array(
+ 'KEYWORDS' => array(
+ 'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\#>|^])",
+ 'DISALLOWED_AFTER' => "(?![a-zA-Z0-9_<\|%])"
+ )
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/asm.php b/plugins/wp-syntax/geshi/geshi/asm.php
index aebfa358..dd0a7ec5 100644
--- a/plugins/wp-syntax/geshi/geshi/asm.php
+++ b/plugins/wp-syntax/geshi/geshi/asm.php
@@ -3,15 +3,56 @@
* asm.php
* -------
* Author: Tux (tux@inmail.cz)
- * Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Copyright: (c) 2004 Tux (http://tux.a4.cz/),
+ * 2004-2009 Nigel McNie (http://qbnz.com/highlighter),
+ * 2009-2011 Benny Baumann (http://qbnz.com/highlighter),
+ * 2011 Dennis Yurichev (dennis@conus.info),
+ * 2011 Marat Dukhan (mdukhan3.at.gatech.dot.edu)
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/27
*
* x86 Assembler language file for GeSHi.
- * Words are from SciTe configuration file (based on NASM syntax)
+ * Based on the following documents:
+ * - "Intel64 and IA-32 Architectures Programmer's Reference Manual
+ * Volume 2 (2A & 2B): Instructions Set Reference, A-Z",
+ * Order Number 25383-039US, May 2011
+ * - "Intel Advanced Vector Extensions Programming Reference",
+ * Order Number 319433-011, June 2011
+ * - "AMD64 Architecture Programmer's Manual Volume 3:
+ * General-Purpose and System Instructions", Publication No. 24594,
+ * Revision 3.15, November 2009
+ * - "AMD64 Architecture Programmer's Manual Volume 4:
+ * 128-Bit and 256-Bit Media Instructions", Publication No. 26568,
+ * Revision 3.12, May 2011
+ * - "AMD64 Architecture Programmer's Manual Volume 5:
+ * 64-Bit Media and x87 Floating-Point Instructions",
+ * Publication No. 26569, Revision 3.11, December 2009
+ * - "AMD64 Technology Lightweight Profiling Specification",
+ * Publication No. 43724, Revision 3.08, August 2010
+ * - "Application Note 108: Cyrix Extended MMX Instruction Set"
+ * - "VIA Padlock Programming Guide", 3rd May 2005
+ * - http://en.wikipedia.org/wiki/X86_instruction_listings
+ * - NASM 2.10rc8 Online Documenation at
+ * http://www.nasm.us/xdoc/2.10rc8/html/nasmdoc0.html
+ * Color scheme is taken from SciTE. Previous versions of this file
+ * also used words from SciTE configuration file (based on NASM syntax)
*
* CHANGES
* -------
+ * 2011/10/07
+ * - Rearranged instructions and registers into groups
+ * - Updated to support the following extensions
+ * - CMOV, BMI1, BMI2, TBM, FSGSBASE
+ * - LZCNT, TZCNT, POPCNT, MOVBE, CRC32
+ * - MMX, MMX+, EMMX
+ * - 3dnow!, 3dnow!+, 3dnow! Geode, 3dnow! Prefetch
+ * - SSE, SSE2, SSE3, SSSE3, SSE4A, SSE4.1, SSE4.2
+ * - AVX, AVX2, XOP, FMA3, FMA4, CVT16
+ * - VMX, SVM
+ * - AES, PCLMULQDQ, Padlock, RDRAND
+ * - Updated NASM macros and directives
+ * 2010/07/01 (1.0.8.11)
+ * - Added MMX/SSE/new x86-64 registers, MMX/SSE (up to 4.2) instructions
* 2008/05/23 (1.0.7.22)
* - Added description of extra language features (SF#1970248)
* 2004/11/27 (1.0.2)
@@ -55,26 +96,71 @@ $language_data = array (
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
- /*CPU*/
+ /* General-Purpose */
1 => array(
- 'aaa','aad','aam','aas','adc','add','and','call','cbw','clc','cld','cli','cmc','cmp',
- 'cmps','cmpsb','cmpsw','cwd','daa','das','dec','div','esc','hlt','idiv','imul','in','inc',
- 'int','into','iret','ja','jae','jb','jbe','jc','jcxz','je','jg','jge','jl','jle','jmp',
- 'jna','jnae','jnb','jnbe','jnc','jne','jng','jnge','jnl','jnle','jno','jnp','jns','jnz',
- 'jo','jp','jpe','jpo','js','jz','lahf','lds','lea','les','lods','lodsb','lodsw','loop',
- 'loope','loopew','loopne','loopnew','loopnz','loopnzw','loopw','loopz','loopzw','mov',
- 'movs','movsb','movsw','mul','neg','nop','not','or','out','pop','popf','push','pushf',
- 'rcl','rcr','ret','retf','retn','rol','ror','sahf','sal','sar','sbb','scas','scasb','scasw',
- 'shl','shr','stc','std','sti','stos','stosb','stosw','sub','test','wait','xchg','xlat',
- 'xlatb','xor','bound','enter','ins','insb','insw','leave','outs','outsb','outsw','popa','pusha','pushw',
- 'arpl','lar','lsl','sgdt','sidt','sldt','smsw','str','verr','verw','clts','lgdt','lidt','lldt','lmsw','ltr',
- 'bsf','bsr','bt','btc','btr','bts','cdq','cmpsd','cwde','insd','iretd','iretdf','iretf',
- 'jecxz','lfs','lgs','lodsd','loopd','looped','loopned','loopnzd','loopzd','lss','movsd',
- 'movsx','movzx','outsd','popad','popfd','pushad','pushd','pushfd','scasd','seta','setae',
- 'setb','setbe','setc','sete','setg','setge','setl','setle','setna','setnae','setnb','setnbe',
- 'setnc','setne','setng','setnge','setnl','setnle','setno','setnp','setns','setnz','seto','setp',
- 'setpe','setpo','sets','setz','shld','shrd','stosd','bswap','cmpxchg','invd','invlpg','wbinvd','xadd','lock',
- 'rep','repe','repne','repnz','repz'
+ /* BCD instructions */
+ 'aaa','aad','aam','aas','daa','das',
+ /* Control flow instructions */
+ 'ja','jae','jb','jbe','jc','je','jg','jge','jl','jle','jmp','jna',
+ 'jnae','jnb','jnbe','jnc','jne','jng','jnge','jnl','jnle','jno','jnp','jns','jnz',
+ 'jo','jp','jpe','jpo','js','jz','jcxz','jecxz','jrcxz','loop','loope','loopne',
+ 'call','ret','enter','leave','syscall','sysenter','int','into',
+ /* Predicate instructions */
+ 'seta','setae','setb','setbe','setc','sete','setg','setge','setl','setle','setna',
+ 'setnae','setnb','setnbe','setnc','setne','setng','setnge','setnl','setnle','setno',
+ 'setnp','setns','setnz','seto','setp','setpe','setpo','sets','setz','salc',
+ /* Conditional move instructions */
+ 'cmovo','cmovno','cmovb','cmovc','cmovnae','cmovae','cmovnb','cmovnc','cmove','cmovz',
+ 'cmovne','cmovnz','cmovbe','cmovna','cmova','cmovnbe','cmovs','cmovns','cmovp','cmovpe',
+ 'cmovnp','cmovpo','cmovl','cmovnge','cmovge','cmovnl','cmovle','cmovng','cmovg','cmovnle',
+ /* ALU instructions */
+ 'add','sub','adc','sbb','neg','cmp','inc','dec','and','or','xor','not','test',
+ 'shl','shr','sal','sar','shld','shrd','rol','ror','rcl','rcr',
+ 'cbw','cwd','cwde','cdq','cdqe','cqo','bsf','bsr','bt','btc','btr','bts',
+ 'idiv','imul','div','mul','bswap','nop',
+ /* Memory instructions */
+ 'lea','mov','movsx','movsxd','movzx','xlatb','bound','xchg','xadd','cmpxchg','cmpxchg8b','cmpxchg16b',
+ /* Stack instructions */
+ 'push','pop','pusha','popa','pushad','popad','pushf','popf','pushfd','popfd','pushfq','popfq',
+ /* EFLAGS manipulations instructions */
+ 'clc','cld','stc','std','cmc','lahf','sahf',
+ /* Prefix instructions */
+ 'lock','rep','repe','repz','repne','repnz',
+ /* String instructions */
+ 'cmps','cmpsb','cmpsw',/*'cmpsd',*/ 'cmpsq', /*CMPSD conflicts with the SSE2 instructions of the same name*/
+ 'movs','movsb','movsw',/*'movsd',*/ 'movsq', /*MOVSD conflicts with the SSE2 instructions of the same name*/
+ 'scas','scasb','scasw','scasd','scasq',
+ 'stos','stosb','stosw','stosd','stosq',
+ 'lods','lodsb','lodsw','lodsd','lodsq',
+ /* Information instructions */
+ 'cpuid','rdtsc','rdtscp','rdpmc','xgetbv',
+ 'sgdt','sidt','sldt','smsw','str','lar',
+ /* LWP instructions */
+ 'llwpcb','slwpcb','lwpval','lwpins',
+ /* Instructions from miscellaneous extensions */
+ 'crc32','popcnt','lzcnt','tzcnt','movbe','pclmulqdq','rdrand',
+ /* FSGSBASE instructions */
+ 'rdfsbase','rdgsbase','wrfsbase','wrgsbase',
+ /* BMI1 instructions */
+ 'andn','bextr','blsi','blsmk','blsr',
+ /* BMI2 instructions */
+ 'bzhi','mulx','pdep','pext','rorx','sarx','shlx','shrx',
+ /* TBM instructions */
+ 'blcfill','blci','blcic','blcmsk','blcs','blsfill','blsic','t1mskc','tzmsk',
+ /* Legacy instructions */
+ 'arpl','ud2','lds','les','lfs','lgs','lss','lsl','verr','verw',
+ /* Privileged instructions */
+ 'cli','sti','clts','hlt','rsm','in','insb','insw','insd',
+ 'out','outsb','outsw','outsd','clflush','invd','invlpg','invpcid','wbinvd',
+ 'iret','iretd','iretq','sysexit','sysret','lidt','lgdt','lldt','lmsw','ltr',
+ 'monitor','mwait','rdmsr','wrmsr','swapgs',
+ 'fxsave','fxsave64','fxrstor','fxrstor64',
+ 'xsave','xsaveopt','xrstor','xsetbv','getsec',
+ /* VMX instructions */
+ 'invept','invvpid','vmcall','vmclear','vmlaunch','vmresume',
+ 'vmptrld','vmptrst','vmread','vmwrite','vmxoff','vmxon',
+ /* SVM (AMD-V) instructions */
+ 'invlpga','skinit','clgi','stgi','vmload','vmsave','vmmcall','vmrun'
),
/*FPU*/
2 => array(
@@ -87,56 +173,350 @@ $language_data = array (
'fsavew','fscale','fsqrt','fst','fstcw','fstenv','fstenvw','fstp','fstsw','fsub','fsubp',
'fsubr','fsubrp','ftst','fwait','fxam','fxch','fxtract','fyl2x','fyl2xp1',
'fsetpm','fcos','fldenvd','fnsaved','fnstenvd','fprem1','frstord','fsaved','fsin','fsincos',
- 'fstenvd','fucom','fucomp','fucompp'
+ 'fstenvd','fucom','fucomp','fucompp','ffreep',
+ /* FCMOV instructions */
+ 'fcomi','fcomip','fucomi','fucomip',
+ 'fcmovb','fcmove','fcmovbe','fcmovu','fcmovnb','fcmovne','fcmovnbe','fcmovnu',
+ /* SSE3 instructions */
+ 'fisttp'
),
- /*registers*/
+ /*SIMD*/
3 => array(
- 'ah','al','ax','bh','bl','bp','bx','ch','cl','cr0','cr2','cr3','cs','cx','dh','di','dl',
- 'dr0','dr1','dr2','dr3','dr6','dr7','ds','dx','eax','ebp','ebx','ecx','edi','edx',
- 'es','esi','esp','fs','gs','si','sp','ss','st','tr3','tr4','tr5','tr6','tr7'
+ /* MMX instructions */
+ 'movd','movq',
+ 'paddb','paddw','paddd','paddsb','paddsw','paddusb','paddusw',
+ 'psubb','psubw','psubd','psubsb','psubsw','psubusb','psubusw',
+ 'pand','pandn','por','pxor',
+ 'pcmpeqb','pcmpeqd','pcmpeqw','pcmpgtb','pcmpgtd','pcmpgtw',
+ 'pmaddwd','pmulhw','pmullw',
+ 'psllw','pslld','psllq','psrlw','psrld','psrlq','psraw','psrad',
+ 'packuswb','packsswb','packssdw',
+ 'punpcklbw','punpcklwd','punpckldq','punpckhbw','punpckhwd','punpckhdq',
+ 'emms',
+ /* MMX+ instructions */
+ 'pavgb','pavgw',
+ 'pextrw','pinsrw','pmovmskb',
+ 'pmaxsw','pmaxub','pminsw','pminub',
+ 'pmulhuw','psadbw','pshufw',
+ 'prefetchnta','prefetcht0','prefetcht1','prefetcht2',
+ 'maskmovq','movntq','sfence',
+ /* EMMX instructions (only available on Cyrix MediaGXm) */
+ 'paddsiw','psubsiw',
+ /*'pmulhrw',*/'pmachriw','pmulhriw', /* PMULHRW conflicts with the 3dnow! instruction of the same name */
+ 'pmagw','pdistib','paveb',
+ 'pmvzb','pmvnzb','pmvlzb','pmvgezb',
+ /* 3dnow! instructions! */
+ 'pfacc','pfadd','pfsub','pfsubr','pfmul',
+ 'pfcmpeq','pfcmpge','pfcmpgt',
+ 'pfmax','pfmin',
+ 'pfrcp','pfrcpit1','pfrcpit2','pfrsqit1','pfrsqrt',
+ 'pi2fd','pf2id',
+ 'pavgusb','pmulhrw',
+ 'femms',
+ /* 3dnow!+ instructions */
+ 'pfnacc','pfpnacc','pi2fw','pf2iw','pswapd',
+ /* 3dnow! Geode instructions */
+ 'pfrsqrtv','pfrcpv',
+ /* 3dnow! Prefetch instructions */
+ 'prefetch','prefetchw',
+ /* SSE instructions */
+ 'addss','addps','subss','subps',
+ 'mulss','mulps','divss','divps','sqrtss','sqrtps',
+ 'rcpss','rcpps','rsqrtss','rsqrtps',
+ 'maxss','maxps','minss','minps',
+ 'cmpss','comiss','ucomiss','cmpps',
+ 'cmpeqss','cmpltss','cmpless','cmpunordss','cmpneqss','cmpnltss','cmpnless','cmpordss',
+ 'cmpeqps','cmpltps','cmpleps','cmpunordps','cmpneqps','cmpnltps','cmpnleps','cmpordps',
+ 'andnps','andps','orps','xorps',
+ 'cvtsi2ss','cvtss2si','cvttss2si',
+ 'cvtpi2ps','cvtps2pi','cvttps2pi',
+ 'movss','movlps','movhps','movlhps','movhlps','movaps','movups','movntps','movmskps',
+ 'shufps','unpckhps','unpcklps',
+ 'ldmxcsr','stmxcsr',
+ /* SSE2 instructions */
+ 'addpd','addsd','subpd','subsd',
+ 'mulsd','mulpd','divsd','divpd','sqrtsd','sqrtpd',
+ 'maxsd','maxpd','minsd','minpd',
+ 'cmpsd','comisd','ucomisd','cmppd',
+ 'cmpeqsd','cmpltsd','cmplesd','cmpunordsd','cmpneqsd','cmpnltsd','cmpnlesd','cmpordsd',
+ 'cmpeqpd','cmpltpd','cmplepd','cmpunordpd','cmpneqpd','cmpnltpd','cmpnlepd','cmpordpd',
+ 'andnpd','andpd','orpd','xorpd',
+ 'cvtsd2ss','cvtpd2ps','cvtss2sd','cvtps2pd',
+ 'cvtdq2ps','cvtps2dq','cvttps2dq',
+ 'cvtdq2pd','cvtpd2dq','cvttpd2dq',
+ 'cvtsi2sd','cvtsd2si','cvttsd2si',
+ 'cvtpi2pd','cvtpd2pi','cvttpd2pi',
+ 'movsd','movlpd','movhpd','movapd','movupd','movntpd','movmskpd',
+ 'shufpd','unpckhpd','unpcklpd',
+ 'movnti','movdqa','movdqu','movntdq','maskmovdqu',
+ 'movdq2q','movq2dq',
+ 'paddq','psubq','pmuludq',
+ 'pslldq','psrldq',
+ 'punpcklqdq','punpckhqdq',
+ 'pshufhw','pshuflw','pshufd',
+ 'lfence','mfence',
+ /* SSE3 instructions */
+ 'addsubps','addsubpd',
+ 'haddps','haddpd','hsubps','hsubpd',
+ 'movsldup','movshdup','movddup',
+ 'lddqu',
+ /* SSSE3 instructions */
+ 'psignb','psignw','psignd',
+ 'pabsb','pabsw','pabsd',
+ 'palignr','pshufb',
+ 'pmulhrsw','pmaddubsw',
+ 'phaddw','phaddd','phaddsw',
+ 'phsubw','phsubd','phsubsw',
+ /* SSE4A instructions */
+ 'extrq','insertq','movntsd','movntss',
+ /* SSE4.1 instructions */
+ 'mpsadbw','phminposuw',
+ 'pmuldq','pmulld',
+ 'dpps','dppd',
+ 'blendps','blendpd','blendvps','blendvpd','pblendvb','pblendw',
+ 'pmaxsb','pmaxuw','pmaxsd','pmaxud','pminsb','pminuw','pminsd','pminud',
+ 'roundps','roundss','roundpd','roundsd',
+ 'insertps','pinsrb','pinsrd','pinsrq',
+ 'extractps','pextrb','pextrd','pextrq',
+ 'pmovsxbw','pmovsxbd','pmovsxbq','pmovsxwd','pmovsxwq','pmovsxdq',
+ 'pmovzxbw','pmovzxbd','pmovzxbq','pmovzxwd','pmovzxwq','pmovzxdq',
+ 'ptest',
+ 'pcmpeqq',
+ 'packusdw',
+ 'movntdqa',
+ /* SSE4.2 instructions */
+ 'pcmpgtq',
+ 'pcmpestri','pcmpestrm','pcmpistri','pcmpistrm',
+ /* AES instructions */
+ 'aesenc','aesenclast','aesdec','aesdeclast','aeskeygenassist','aesimc',
+ /* VIA Padlock instructions */
+ 'xcryptcbc','xcryptcfb','xcryptctr','xcryptecb','xcryptofb',
+ 'xsha1','xsha256','montmul','xstore',
+ /* AVX instructions */
+ 'vaddss','vaddps','vaddsd','vaddpd','vsubss','vsubps','vsubsd','vsubpd',
+ 'vaddsubps','vaddsubpd',
+ 'vhaddps','vhaddpd','vhsubps','vhsubpd',
+ 'vmulss','vmulps','vmulsd','vmulpd',
+ 'vmaxss','vmaxps','vmaxsd','vmaxpd','vminss','vminps','vminsd','vminpd',
+ 'vandps','vandpd','vandnps','vandnpd','vorps','vorpd','vxorps','vxorpd',
+ 'vblendps','vblendpd','vblendvps','vblendvpd',
+ 'vcmpss','vcomiss','vucomiss','vcmpsd','vcomisd','vucomisd','vcmpps','vcmppd',
+ 'vcmpeqss','vcmpltss','vcmpless','vcmpunordss','vcmpneqss','vcmpnltss','vcmpnless','vcmpordss',
+ 'vcmpeq_uqss','vcmpngess','vcmpngtss','vcmpfalsess','vcmpneq_oqss','vcmpgess','vcmpgtss','vcmptruess',
+ 'vcmpeq_osss','vcmplt_oqss','vcmple_oqss','vcmpunord_sss','vcmpneq_usss','vcmpnlt_uqss','vcmpnle_uqss','vcmpord_sss',
+ 'vcmpeq_usss','vcmpnge_uqss','vcmpngt_uqss','vcmpfalse_osss','vcmpneq_osss','vcmpge_oqss','vcmpgt_oqss','vcmptrue_usss',
+ 'vcmpeqps','vcmpltps','vcmpleps','vcmpunordps','vcmpneqps','vcmpnltps','vcmpnleps','vcmpordps',
+ 'vcmpeq_uqps','vcmpngeps','vcmpngtps','vcmpfalseps','vcmpneq_oqps','vcmpgeps','vcmpgtps','vcmptrueps',
+ 'vcmpeq_osps','vcmplt_oqps','vcmple_oqps','vcmpunord_sps','vcmpneq_usps','vcmpnlt_uqps','vcmpnle_uqps','vcmpord_sps',
+ 'vcmpeq_usps','vcmpnge_uqps','vcmpngt_uqps','vcmpfalse_osps','vcmpneq_osps','vcmpge_oqps','vcmpgt_oqps','vcmptrue_usps',
+ 'vcmpeqsd','vcmpltsd','vcmplesd','vcmpunordsd','vcmpneqsd','vcmpnltsd','vcmpnlesd','vcmpordsd',
+ 'vcmpeq_uqsd','vcmpngesd','vcmpngtsd','vcmpfalsesd','vcmpneq_oqsd','vcmpgesd','vcmpgtsd','vcmptruesd',
+ 'vcmpeq_ossd','vcmplt_oqsd','vcmple_oqsd','vcmpunord_ssd','vcmpneq_ussd','vcmpnlt_uqsd','vcmpnle_uqsd','vcmpord_ssd',
+ 'vcmpeq_ussd','vcmpnge_uqsd','vcmpngt_uqsd','vcmpfalse_ossd','vcmpneq_ossd','vcmpge_oqsd','vcmpgt_oqsd','vcmptrue_ussd',
+ 'vcmpeqpd','vcmpltpd','vcmplepd','vcmpunordpd','vcmpneqpd','vcmpnltpd','vcmpnlepd','vcmpordpd',
+ 'vcmpeq_uqpd','vcmpngepd','vcmpngtpd','vcmpfalsepd','vcmpneq_oqpd','vcmpgepd','vcmpgtpd','vcmptruepd',
+ 'vcmpeq_ospd','vcmplt_oqpd','vcmple_oqpd','vcmpunord_spd','vcmpneq_uspd','vcmpnlt_uqpd','vcmpnle_uqpd','vcmpord_spd',
+ 'vcmpeq_uspd','vcmpnge_uqpd','vcmpngt_uqpd','vcmpfalse_ospd','vcmpneq_ospd','vcmpge_oqpd','vcmpgt_oqpd','vcmptrue_uspd',
+ 'vcvtsd2ss','vcvtpd2ps','vcvtss2sd','vcvtps2pd',
+ 'vcvtsi2ss','vcvtss2si','vcvttss2si',
+ 'vcvtpi2ps','vcvtps2pi','vcvttps2pi',
+ 'vcvtdq2ps','vcvtps2dq','vcvttps2dq',
+ 'vcvtdq2pd','vcvtpd2dq','vcvttpd2dq',
+ 'vcvtsi2sd','vcvtsd2si','vcvttsd2si',
+ 'vcvtpi2pd','vcvtpd2pi','vcvttpd2pi',
+ 'vdivss','vdivps','vdivsd','vdivpd','vsqrtss','vsqrtps','vsqrtsd','vsqrtpd',
+ 'vdpps','vdppd',
+ 'vmaskmovps','vmaskmovpd',
+ 'vmovss','vmovsd','vmovaps','vmovapd','vmovups','vmovupd','vmovntps','vmovntpd',
+ 'vmovhlps','vmovlhps','vmovlps','vmovlpd','vmovhps','vmovhpd',
+ 'vmovsldup','vmovshdup','vmovddup',
+ 'vmovmskps','vmovmskpd',
+ 'vroundss','vroundps','vroundsd','vroundpd',
+ 'vrcpss','vrcpps','vrsqrtss','vrsqrtps',
+ 'vunpcklps','vunpckhps','vunpcklpd','vunpckhpd',
+ 'vbroadcastss','vbroadcastsd','vbroadcastf128',
+ 'vextractps','vinsertps','vextractf128','vinsertf128',
+ 'vshufps','vshufpd','vpermilps','vpermilpd','vperm2f128',
+ 'vtestps','vtestpd',
+ 'vpaddb','vpaddusb','vpaddsb','vpaddw','vpaddusw','vpaddsw','vpaddd','vpaddq',
+ 'vpsubb','vpsubusb','vpsubsb','vpsubw','vpsubusw','vpsubsw','vpsubd','vpsubq',
+ 'vphaddw','vphaddsw','vphaddd','vphsubw','vphsubsw','vphsubd',
+ 'vpsllw','vpslld','vpsllq','vpsrlw','vpsrld','vpsrlq','vpsraw','vpsrad',
+ 'vpand','vpandn','vpor','vpxor',
+ 'vpblendwb','vpblendw',
+ 'vpsignb','vpsignw','vpsignd',
+ 'vpavgb','vpavgw',
+ 'vpabsb','vpabsw','vpabsd',
+ 'vmovd','vmovq','vmovdqa','vmovdqu','vlddqu','vmovntdq','vmovntdqa','vmaskmovdqu',
+ 'vpmovsxbw','vpmovsxbd','vpmovsxbq','vpmovsxwd','vpmovsxwq','vpmovsxdq',
+ 'vpmovzxbw','vpmovzxbd','vpmovzxbq','vpmovzxwd','vpmovzxwq','vpmovzxdq',
+ 'vpackuswb','vpacksswb','vpackusdw','vpackssdw',
+ 'vpcmpeqb','vpcmpeqw','vpcmpeqd','vpcmpeqq','vpcmpgtb','vpcmpgtw','vpcmpgtd','vpcmpgtq',
+ 'vpmaddubsw','vpmaddwd',
+ 'vpmullw','vpmulhuw','vpmulhw','vpmulhrsw','vpmulld','vpmuludq','vpmuldq',
+ 'vpmaxub','vpmaxsb','vpmaxuw','vpmaxsw','vpmaxud','vpmaxsd',
+ 'vpminub','vpminsb','vpminuw','vpminsw','vpminud','vpminsd',
+ 'vpmovmskb','vptest',
+ 'vpunpcklbw','vpunpcklwd','vpunpckldq','vpunpcklqdq',
+ 'vpunpckhbw','vpunpckhwd','vpunpckhdq','vpunpckhqdq',
+ 'vpslldq','vpsrldq','vpalignr',
+ 'vpshufb','vpshuflw','vpshufhw','vpshufd',
+ 'vpextrb','vpextrw','vpextrd','vpextrq','vpinsrb','vpinsrw','vpinsrd','vpinsrq',
+ 'vpsadbw','vmpsadbw','vphminposuw',
+ 'vpcmpestri','vpcmpestrm','vpcmpistri','vpcmpistrm',
+ 'vpclmulqdq','vaesenc','vaesenclast','vaesdec','vaesdeclast','vaeskeygenassist','vaesimc',
+ 'vldmxcsr','vstmxcsr','vzeroall','vzeroupper',
+ /* AVX2 instructions */
+ 'vbroadcasti128','vpbroadcastb','vpbroadcastw','vpbroadcastd','vpbroadcastq',
+ 'vpblendd',
+ 'vpermd','vpermq','vperm2i128',
+ 'vextracti128','vinserti128',
+ 'vpmaskmovd','vpmaskmovq',
+ 'vpsllvd','vpsllvq','vpsravd','vpsrlvd',
+ 'vpgatherdd','vpgatherqd','vgatherdq','vgatherqq',
+ 'vpermps','vpermpd',
+ 'vgatherdpd','vgatherqpd','vgatherdps','vgatherqps',
+ /* XOP instructions */
+ 'vfrczss','vfrczps','vfrczsd','vfrczpd',
+ 'vpermil2ps','vperlil2pd',
+ 'vpcomub','vpcomb','vpcomuw','vpcomw','vpcomud','vpcomd','vpcomuq','vpcomq',
+ 'vphaddubw','vphaddbw','vphaddubd','vphaddbd','vphaddubq','vphaddbq',
+ 'vphadduwd','vphaddwd','vphadduwq','vphaddwq','vphaddudq','vphadddq',
+ 'vphsubbw','vphsubwd','vphsubdq',
+ 'vpmacsdd','vpmacssdd','vpmacsdql','vpmacssdql','vpmacsdqh','vpmacssdqh',
+ 'vpmacsww','vpmacssww','vpmacswd','vpmacsswd',
+ 'vpmadcswd','vpmadcsswd',
+ 'vpcmov','vpperm',
+ 'vprotb','vprotw','vprotd','vprotq',
+ 'vpshab','vpshaw','vpshad','vpshaq',
+ 'vpshlb','vpshlw','vpshld','vpshlq',
+ /* CVT16 instructions */
+ 'vcvtph2ps','vcvtps2ph',
+ /* FMA4 instructions */
+ 'vfmaddss','vfmaddps','vfmaddsd','vfmaddpd',
+ 'vfmsubss','vfmsubps','vfmsubsd','vfmsubpd',
+ 'vnfmaddss','vnfmaddps','vnfmaddsd','vnfmaddpd',
+ 'vnfmsubss','vnfmsubps','vnfmsubsd','vnfmsubpd',
+ 'vfmaddsubps','vfmaddsubpd','vfmsubaddps','vfmsubaddpd',
+ /* FMA3 instructions */
+ 'vfmadd132ss','vfmadd213ss','vfmadd231ss',
+ 'vfmadd132ps','vfmadd213ps','vfmadd231ps',
+ 'vfmadd132sd','vfmadd213sd','vfmadd231sd',
+ 'vfmadd132pd','vfmadd213pd','vfmadd231pd',
+ 'vfmaddsub132ps','vfmaddsub213ps','vfmaddsub231ps',
+ 'vfmaddsub132pd','vfmaddsub213pd','vfmaddsub231pd',
+ 'vfmsubadd132ps','vfmsubadd213ps','vfmsubadd231ps',
+ 'vfmsubadd132pd','vfmsubadd213pd','vfmsubadd231pd',
+ 'vfmsub132ss','vfmsub213ss','vfmsub231ss',
+ 'vfmsub132ps','vfmsub213ps','vfmsub231ps',
+ 'vfmsub132sd','vfmsub213sd','vfmsub231sd',
+ 'vfmsub132pd','vfmsub213pd','vfmsub231pd',
+ 'vfnmadd132ss','vfnmadd213ss','vfnmadd231ss',
+ 'vfnmadd132ps','vfnmadd213ps','vfnmadd231ps',
+ 'vfnmadd132sd','vfnmadd213sd','vfnmadd231sd',
+ 'vfnmadd132pd','vfnmadd213pd','vfnmadd231pd',
+ 'vfnmsub132ss','vfnmsub213ss','vfnmsub231ss',
+ 'vfnmsub132ps','vfnmsub213ps','vfnmsub231ps',
+ 'vfnmsub132sd','vfnmsub213sd','vfnmsub231sd',
+ 'vfnmsub132pd','vfnmsub213pd','vfnmsub231pd'
),
- /*Directive*/
+ /*registers*/
4 => array(
- '186','286','286c','286p','287','386','386c','386p','387','486','486p',
- '8086','8087','alpha','break','code','const','continue','cref','data','data?',
- 'dosseg','else','elseif','endif','endw','err','err1','err2','errb',
- 'errdef','errdif','errdifi','erre','erridn','erridni','errnb','errndef',
- 'errnz','exit','fardata','fardata?','if','lall','lfcond','list','listall',
- 'listif','listmacro','listmacroall',' model','no87','nocref','nolist',
- 'nolistif','nolistmacro','radix','repeat','sall','seq','sfcond','stack',
- 'startup','tfcond','type','until','untilcxz','while','xall','xcref',
- 'xlist','alias','align','assume','catstr','comm','comment','db','dd','df','dq',
- 'dt','dup','dw','echo','elseif1','elseif2','elseifb','elseifdef','elseifdif',
- 'elseifdifi','elseife','elseifidn','elseifidni','elseifnb','elseifndef','end',
- 'endm','endp','ends','eq',' equ','even','exitm','extern','externdef','extrn','for',
- 'forc','ge','goto','group','high','highword','if1','if2','ifb','ifdef','ifdif',
- 'ifdifi','ife',' ifidn','ifidni','ifnb','ifndef','include','includelib','instr','invoke',
- 'irp','irpc','label','le','length','lengthof','local','low','lowword','lroffset',
- 'macro','mask','mod','msfloat','name','ne','offset','opattr','option','org','%out',
- 'page','popcontext','private','proc','proto','ptr','public','purge','pushcontext','record',
- 'rept','seg','segment','short','size','sizeof','sizestr','struc','struct',
- 'substr','subtitle','subttl','textequ','this','title','typedef','union','width',
- '.model', '.stack', '.code', '.data'
+ /* General-Purpose Registers */
+ 'al','ah','bl','bh','cl','ch','dl','dh','sil','dil','bpl','spl',
+ 'r8b','r9b','r10b','r11b','r12b','r13b','r14b','r15b',
+ 'ax','bx','cx','dx','si','di','bp','sp',
+ 'r8w','r9w','r10w','r11w','r12w','r13w','r14w','r15w',
+ 'eax','ebx','ecx','edx','esi','edi','ebp','esp',
+ 'r8d','r9d','r10d','r11d','r12d','r13d','r14d','r15d',
+ 'rax','rcx','rdx','rbx','rsp','rbp','rsi','rdi',
+ 'r8','r9','r10','r11','r12','r13','r14','r15',
+ /* Debug Registers */
+ 'dr0','dr1','dr2','dr3','dr6','dr7',
+ /* Control Registers */
+ 'cr0','cr2','cr3','cr4','cr8',
+ /* Test Registers (Supported on Intel 486 only) */
+ 'tr3','tr4','tr5','tr6','tr7',
+ /* Segment Registers */
+ 'cs','ds','es','fs','gs','ss',
+ /* FPU Registers */
+ 'st','st0','st1','st2','st3','st4','st5','st6','st7',
+ /* MMX Registers */
+ 'mm0','mm1','mm2','mm3','mm4','mm5','mm6','mm7',
+ /* SSE Registers */
+ 'xmm0','xmm1','xmm2','xmm3','xmm4','xmm5','xmm6','xmm7',
+ 'xmm8','xmm9','xmm10','xmm11','xmm12','xmm13','xmm14','xmm15',
+ /* AVX Registers */
+ 'ymm0','ymm1','ymm2','ymm3','ymm4','ymm5','ymm6','ymm7',
+ 'ymm8','ymm9','ymm10','ymm11','ymm12','ymm13','ymm14','ymm15'
),
- /*Operands*/
+ /*Directive*/
5 => array(
- '@b','@f','addr','basic','byte','c','carry?','dword',
- 'far','far16','fortran','fword','near','near16','overflow?','parity?','pascal','qword',
- 'real4',' real8','real10','sbyte','sdword','sign?','stdcall','sword','syscall','tbyte',
- 'vararg','word','zero?','flat','near32','far32',
- 'abs','all','assumes','at','casemap','common','compact',
- 'cpu','dotname','emulator','epilogue','error','export','expr16','expr32','farstack',
- 'forceframe','huge','language','large','listing','ljmp','loadds','m510','medium','memory',
- 'nearstack','nodotname','noemulator','nokeyword','noljmp','nom510','none','nonunique',
- 'nooldmacros','nooldstructs','noreadonly','noscoped','nosignextend','nothing',
- 'notpublic','oldmacros','oldstructs','os_dos','para','prologue',
- 'readonly','req','scoped','setif2','smallstack','tiny','use16','use32','uses'
+ 'db','dw','dd','dq','dt','do','dy',
+ 'resb','resw','resd','resq','rest','reso','resy','incbin','equ','times','safeseh',
+ '__utf16__','__utf32__',
+ 'default','cpu','float','start','imagebase','osabi',
+ '..start','..imagebase','..gotpc','..gotoff','..gottpoff','..got','..plt','..sym','..tlsie',
+ 'section','segment','__sect__','group','absolute',
+ '.bss','.comment','.data','.lbss','.ldata','.lrodata','.rdata','.rodata','.tbss','.tdata','.text',
+ 'alloc','bss','code','exec','data','noalloc','nobits','noexec','nowrite','progbits','rdata','tls','write',
+ 'private','public','common','stack','overlay','class',
+ 'extern','global','import','export',
+ '%define','%idefine','%xdefine','%ixdefine','%assign','%undef',
+ '%defstr','%idefstr','%deftok','%ideftok',
+ '%strcat','%strlen','%substr',
+ '%macro','%imacro','%rmacro','%exitmacro','%endmacro','%unmacro',
+ '%if','%ifn','%elif','%elifn','%else','%endif',
+ '%ifdef','%ifndef','%elifdef','%elifndef',
+ '%ifmacro','%ifnmacro','%elifmacro','%elifnmacro',
+ '%ifctx','%ifnctx','%elifctx','%elifnctx',
+ '%ifidn','%ifnidn','%elifidn','%elifnidn',
+ '%ifidni','%ifnidni','%elifidni','%elifnidni',
+ '%ifid','%ifnid','%elifid','%elifnid',
+ '%ifnum','%ifnnum','%elifnum','%elifnnum',
+ '%ifstr','%ifnstr','%elifstr','%elifnstr',
+ '%iftoken','%ifntoken','%eliftoken','%elifntoken',
+ '%ifempty','%ifnempty','%elifempty','%elifnempty',
+ '%ifenv','%ifnenv','%elifenv','%elifnenv',
+ '%rep','%exitrep','%endrep',
+ '%while','%exitwhile','%endwhile',
+ '%include','%pathsearch','%depend','%use',
+ '%push','%pop','%repl','%arg','%local','%stacksize','flat','flat64','large','small',
+ '%error','%warning','%fatal',
+ '%00','.nolist','%rotate','%line','%!','%final','%clear',
+ 'struc','endstruc','istruc','at','iend',
+ 'align','alignb','sectalign',
+ 'bits','use16','use32','use64',
+ '__nasm_major__','__nasm_minor__','__nasm_subminor__','___nasm_patchlevel__',
+ '__nasm_version_id__','__nasm_ver__',
+ '__file__','__line__','__pass__','__bits__','__output_format__',
+ '__date__','__time__','__date_num__','__time_num__','__posix_time__',
+ '__utc_date__','__utc_time__','__utc_date_num__','__utc_time_num__',
+ '__float_daz__','__float_round__','__float__',
+ /* Keywords from standard packages */
+ '__use_altreg__',
+ '__use_smartalign__','smartalign','__alignmode__',
+ '__use_fp__','__infinity__','__nan__','__qnan__','__snan__',
+ '__float8__','__float16__','__float32__','__float64__','__float80m__','__float80e__','__float128l__','__float128h__'
+ ),
+ /*Operands*/
+ 6 => array(
+ 'a16','a32','a64','o16','o32','o64','strict',
+ 'byte','word','dword','qword','tword','oword','yword','nosplit',
+ '%0','%1','%2','%3','%4','%5','%6','%7','%8','%9',
+ 'abs','rel',
+ 'seg','wrt'
)
),
'SYMBOLS' => array(
- '[', ']', '(', ')',
- '+', '-', '*', '/', '%',
- '.', ',', ';', ':'
+ 1 => array(
+ '[', ']', '(', ')',
+ '+', '-', '*', '/', '%',
+ '.', ',', ';', ':'
+ ),
+ 2 => array(
+ '$','$$','%+','%?','%??'
+ )
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
@@ -144,19 +524,21 @@ $language_data = array (
2 => false,
3 => false,
4 => false,
- 5 => false
+ 5 => false,
+ 6 => false
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #00007f; font-weight: bold;',
- 2 => 'color: #0000ff; font-weight: bold;',
- 3 => 'color: #00007f;',
- 4 => 'color: #000000; font-weight: bold;',
- 5 => 'color: #000000; font-weight: bold;'
+ 2 => 'color: #0000ff;',
+ 3 => 'color: #b00040;',
+ 4 => 'color: #46aa03; font-weight: bold;',
+ 5 => 'color: #0000ff; font-weight: bold;',
+ 6 => 'color: #0000ff; font-weight: bold;'
),
'COMMENTS' => array(
1 => 'color: #666666; font-style: italic;',
- 2 => 'color: #adadad; font-style: italic;',
+ 2 => 'color: #adadad; font-style: italic;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
@@ -168,16 +550,15 @@ $language_data = array (
0 => 'color: #7f007f;'
),
'NUMBERS' => array(
- 0 => 'color: #0000ff;'
+ 0 => 'color: #ff0000;'
),
'METHODS' => array(
),
'SYMBOLS' => array(
- 0 => 'color: #339933;'
+ 1 => 'color: #339933;',
+ 2 => 'color: #0000ff; font-weight: bold;'
),
'REGEXPS' => array(
-// 0 => 'color: #0000ff;',
-// 1 => 'color: #0000ff;'
),
'SCRIPT' => array(
)
@@ -187,7 +568,8 @@ $language_data = array (
2 => '',
3 => '',
4 => '',
- 5 => ''
+ 5 => '',
+ 6 => ''
),
'NUMBERS' =>
GESHI_NUMBER_BIN_PREFIX_PERCENT |
@@ -203,10 +585,6 @@ $language_data = array (
'OBJECT_SPLITTERS' => array(
),
'REGEXPS' => array(
- //Hex numbers
-// 0 => /* */ "(?<=([\\s\\(\\)\\[\\],;.:+\\-\\/*]))(?:[0-9][0-9a-fA-F]{0,31}[hH]|0x[0-9a-fA-F]{1,32})(?=([\\s\\(\\)\\[\\],;.:+\\-\\/*]))",
- //Binary numbers
-// 1 => "(?<=([\\s\\(\\)\\[\\],;.:+\\-\\/*]))[01]{1,64}[bB](?=([\\s\\(\\)\\[\\],;.:+\\-\\/*]))"
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
@@ -222,4 +600,4 @@ $language_data = array (
)
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/asp.php b/plugins/wp-syntax/geshi/geshi/asp.php
index 5f48f11b..0096a169 100644
--- a/plugins/wp-syntax/geshi/geshi/asp.php
+++ b/plugins/wp-syntax/geshi/geshi/asp.php
@@ -4,7 +4,7 @@
* --------
* Author: Amit Gupta (http://blog.igeek.info/)
* Copyright: (c) 2004 Amit Gupta (http://blog.igeek.info/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/13
*
* ASP language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/asymptote.php b/plugins/wp-syntax/geshi/geshi/asymptote.php
new file mode 100644
index 00000000..8683588e
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/asymptote.php
@@ -0,0 +1,194 @@
+<?php
+/*************************************************************************************
+ * asymptote.php
+ * -------------
+ * Author: Manuel Yguel (manuel.yguel.robotics@gmail.com)
+ * Copyright: (c) 2012 Manuel Yguel (http://manuelyguel.eu)
+ * Release Version: 1.0.8.11
+ * Date Started: 2012/05/24
+ *
+ * asymptote language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2012/05/24 (1.0.0.0)
+ * - First Release
+ *
+ * TODO (updated 2012/05/24)
+ * -------------------------
+ * * Split to several files - php4, php5 etc
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * ************************************************************************************/
+
+$language_data = array(
+ 'LANG_NAME' => 'asymptote',
+ 'COMMENT_SINGLE' => array(1 => '//'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_REGEXP' => array(
+ //Multiline-continued single-line comments
+ 1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+ //Multiline-continued preprocessor define
+ 2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m'
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ 'ESCAPE_REGEXP' => array(
+ //Simple Single Char Escapes
+ 1 => "#\\\\[\\\\abfnrtv\'\"?\n]#i",
+ //Hexadecimal Char Specs
+ 2 => "#\\\\x[\da-fA-F]{2}#",
+ //Hexadecimal Char Specs
+ 3 => "#\\\\u[\da-fA-F]{4}#",
+ //Hexadecimal Char Specs
+ 4 => "#\\\\U[\da-fA-F]{8}#",
+ //Octal Char Specs
+ 5 => "#\\\\[0-7]{1,3}#"
+ ),
+ 'NUMBERS' =>
+ GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B |
+ GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI |
+ GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'and','controls','tension','atleast','curl','if','else','while','for','do','return','break','continue','struct','typedef','new','access','import','unravel','from','include','quote','static','public','private','restricted','this','explicit','true','false','null','cycle','newframe','operator'
+ ),
+ 2 => array(
+ 'Braid','FitResult','Label','Legend','Segment','Solution','TreeNode','abscissa','arc','arrowhead','binarytree','binarytreeNode','block','bool','bool3','bounds','bqe','circle','conic','coord','coordsys','cputime','ellipse','file','filltype','frame','grid3','guide','horner','hsv','hyperbola','indexedTransform','int','inversion','key','light','line','linefit','marginT','marker','mass','object','pair','parabola','path','path3','pen','picture','point','position','projection','real','revolution','scaleT','scientific','segment','side','slice','solution','splitface','string','surface','tensionSpecifier','ticklocate','ticksgridT','tickvalues','transform','transformation','tree','triangle','trilinear','triple','vector','vertex','void'),
+ 3 => array(
+ 'AND','Arc','ArcArrow','ArcArrows','Arrow','Arrows','Automatic','AvantGarde','BBox','BWRainbow','BWRainbow2','Bar','Bars','BeginArcArrow','BeginArrow','BeginBar','BeginDotMargin','BeginMargin','BeginPenMargin','Blank','Bookman','Bottom','BottomTop','Bounds','Break','Broken','BrokenLog','CLZ','CTZ','Ceil','Circle','CircleBarIntervalMarker','Cos','Courier','CrossIntervalMarker','DOSendl','DOSnewl','DefaultFormat','DefaultLogFormat','Degrees','Dir','DotMargin','DotMargins','Dotted','Draw','Drawline','Embed','EndArcArrow','EndArrow','EndBar','EndDotMargin','EndMargin','EndPenMargin','Fill','FillDraw','Floor','Format','Full','Gaussian','Gaussrand','Gaussrandpair',
+ 'Gradient','Grayscale','Helvetica','Hermite','HookHead','InOutTicks','InTicks','Jn','Label','Landscape','Left','LeftRight','LeftTicks','Legend','Linear','Link','Log','LogFormat','Margin','Margins','Mark','MidArcArrow','MidArrow','NOT','NewCenturySchoolBook','NoBox','NoMargin','NoModifier','NoTicks','NoTicks3','NoZero','NoZeroFormat','None','OR','OmitFormat','OmitTick','OmitTickInterval','OmitTickIntervals','OutTicks','Ox','Oy','Palatino','PaletteTicks','Pen','PenMargin','PenMargins','Pentype','Portrait','RadialShade','RadialShadeDraw','Rainbow','Range','Relative','Right','RightTicks','Rotate','Round','SQR','Scale','ScaleX','ScaleY','ScaleZ','Seascape','Segment','Shift','Sin','Slant','Spline','StickIntervalMarker','Straight','Symbol','Tan','TeXify','Ticks','Ticks3','TildeIntervalMarker','TimesRoman','Top','TrueMargin','UnFill','UpsideDown','Wheel','X','XEquals','XOR','XY','XYEquals','XYZero','XYgrid','XZEquals','XZZero','XZero','XZgrid','Y','YEquals','YXgrid','YZ','YZEquals','YZZero','YZero','YZgrid','Yn','Z','ZX','ZXgrid','ZYgrid','ZapfChancery','ZapfDingbats','_begingroup3','_cputime','_draw','_eval','_image','_labelpath','_projection','_strokepath','_texpath','aCos','aSin','aTan','abort','abs','accel','acos','acosh','acot','acsc','activatequote','add',
+ 'addArrow','addMargins','addSaveFunction','addpenarc','addpenline','adjust','alias','align','all','altitude','angabscissa','angle','angpoint','animate','annotate','anticomplementary','antipedal','apply','approximate','arc','arcarrowsize','arccircle','arcdir','arcfromcenter','arcfromfocus','arclength','arcnodesnumber','arcpoint','arcsubtended','arcsubtendedcenter','arctime','arctopath','array','arrow','arrow2','arrowbase','arrowbasepoints','arrowsize','asec','asin','asinh','ask','assert','asy','asycode','asydir','asyfigure','asyfilecode','asyinclude','asywrite','atan','atan2','atanh','atbreakpoint','atexit','attach','attract','atupdate','autoformat','autoscale','autoscale3','axes','axes3','axialshade','axis','axiscoverage','azimuth','babel','background','bangles','bar','barmarksize','barsize','basealign','baseline','bbox','beep','begin','beginclip','begingroup','beginpoint','between','bevel','bezier','bezierP','bezierPP','bezierPPP','bezulate','bibliography','bibliographystyle','binarytree','binarytreeNode','binomial','binput','bins','bisector','bisectorpoint','bispline','blend','blockconnector','boutput','box','bqe','breakpoint','breakpoints','brick','buildRestoreDefaults','buildRestoreThunk','buildcycle','bulletcolor','byte','calculateScaling','canonical','canonicalcartesiansystem','cartesiansystem','case1','case2','case3','case4','cbrt','cd','ceil','center','centerToFocus',
+ 'centroid','cevian','change2','changecoordsys','checkSegment','checkconditionlength','checker','checkincreasing','checklengths','checkposition','checktriangle','choose','circle','circlebarframe','circlemarkradius','circlenodesnumber','circumcenter','circumcircle','clamped','clear','clip','clipdraw','close','cmyk','code','colatitude','collect','collinear','color','colorless','colors','colorspace','comma','compassmark','complement','complementary','concat','concurrent','cone','conic','conicnodesnumber','conictype','conj','connect','connected','connectedindex','containmentTree','contains','contour','contour3','contouredges','controlSpecifier','convert','coordinates','coordsys','copy','copyPairOrTriple','cos','cosh','cot','countIntersections','cputime','crop','cropcode','cross',
+ 'crossframe','crosshatch','crossmarksize','csc','cubicroots','curabscissa','curlSpecifier','curpoint','currentarrow','currentexitfunction','currentmomarrow','currentpolarconicroutine','curve','cut','cutafter','cutbefore','cyclic','cylinder','deactivatequote','debugger','deconstruct','defaultdir','defaultformat','defaultpen','defined','degenerate','degrees','delete','deletepreamble','determinant','diagonal','diamond','diffdiv','dir','dirSpecifier','dirtime','display','distance',
+ 'divisors','do_overpaint','dot','dotframe','dotsize','downcase','draw','drawAll','drawDoubleLine','drawFermion','drawGhost','drawGluon','drawMomArrow','drawPRCcylinder','drawPRCdisk','drawPRCsphere','drawPRCtube','drawPhoton','drawScalar','drawVertex','drawVertexBox','drawVertexBoxO','drawVertexBoxX','drawVertexO','drawVertexOX','drawVertexTriangle','drawVertexTriangleO','drawVertexX','drawarrow','drawarrow2','drawline','drawpixel','drawtick','duplicate','elle','ellipse','ellipsenodesnumber','embed','embed3','empty','enclose','end','endScript','endclip','endgroup','endgroup3','endl','endpoint','endpoints','eof','eol','equation','equations','erase','erasestep','erf','erfc','error','errorbar','errorbars','eval','excenter','excircle','exit','exitXasyMode','exitfunction','exp','expfactors','expi','expm1','exradius','extend','extension','extouch','fabs','factorial','fermat','fft','fhorner','figure','file','filecode','fill','filldraw','filloutside','fillrule','filltype','find','finite','finiteDifferenceJacobian','firstcut','firstframe','fit','fit2','fixedscaling','floor','flush','fmdefaults','fmod','focusToCenter','font','fontcommand','fontsize','foot','format','frac','frequency','fromCenter','fromFocus','fspline','functionshade','gamma','generate_random_backtrace','generateticks','gergonne','getc','getint','getpair','getreal','getstring','gettriple','gluon','gouraudshade','graph','graphic','gray','grestore','grid','grid3','gsave','halfbox','hatch','hdiffdiv','hermite','hex','histogram','history','hline','hprojection',
+ 'hsv','hyperbola','hyperbolanodesnumber','hyperlink','hypot','identity','image','incenter','incentral','incircle','increasing','incrementposition','indexedTransform','indexedfigure','initXasyMode','initdefaults','input','inradius','insert','inside','integrate','interactive','interior','interp','interpolate','intersect','intersection','intersectionpoint','intersectionpoints','intersections','intouch','inverse','inversion','invisible','is3D','isCCW','isDuplicate','isogonal','isogonalconjugate','isotomic','isotomicconjugate','isparabola','italic','item','jobname','key','kurtosis','kurtosisexcess','label','labelaxis','labelmargin','labelpath','labels','labeltick','labelx','labelx3','labely','labely3','labelz','labelz3','lastcut','latex','latitude','latticeshade','layer','layout','ldexp','leastsquares','legend','legenditem','length','lexorder','lift','light','limits','line','linear','linecap','lineinversion','linejoin','linemargin','lineskip','linetype','linewidth','link','list','lm_enorm','lm_evaluate_default','lm_lmdif','lm_lmpar','lm_minimize','lm_print_default','lm_print_quiet','lm_qrfac','lm_qrsolv','locale','locate',
+ 'locatefile','location','log','log10','log1p','logaxiscoverage','longitude','lookup','makeNode','makedraw','makepen','map','margin','markangle','markangleradius','markanglespace','markarc','marker','markinterval','marknodes','markrightangle','markuniform','mass','masscenter','massformat','math','max','max3','maxAfterTransform','maxbezier','maxbound','maxcoords','maxlength','maxratio','maxtimes','mean','medial','median','midpoint','min','min3','minAfterTransform','minbezier','minbound','minipage','minratio','mintimes','miterlimit','mktemp','momArrowPath','momarrowsize','monotonic','multifigure','nativeformat','natural','needshipout','newl','newpage','newslide','newton','newtree','nextframe','nextnormal','nextpage','nib','nodabscissa','none','norm','normalvideo','notaknot','nowarn','numberpage','nurb','object','offset','onpath','opacity','opposite','orientation','origin','orthic','orthocentercenter','outformat','outline','outname','outprefix','output','overloadedMessage','overwrite','pack','pad','pairs','palette','parabola','parabolanodesnumber','parallel','parallelogram','partialsum','path','path3','pattern','pause','pdf','pedal','periodic','perp','perpendicular','perpendicularmark','phantom','phi1','phi2','phi3','photon','piecewisestraight','point','polar','polarconicroutine','polargraph','polygon','postcontrol','postscript','pow10','ppoint','prc','prc0','precision','precontrol','prepend','printBytecode','print_random_addresses','project','projection','purge','pwhermite','quadrant','quadraticroots','quantize','quarticroots','quotient','radialshade','radians','radicalcenter','radicalline','radius','rand','randompath','rd','readline','realmult','realquarticroots','rectangle','rectangular','rectify','reflect','relabscissa','relative','relativedistance','reldir','relpoint','reltime','remainder','remark','removeDuplicates','rename','replace','report','resetdefaultpen','restore','restoredefaults','reverse','reversevideo','rf','rfind','rgb','rgba','rgbint','rms',
+ 'rotate','rotateO','rotation','round','roundbox','roundedpath','roundrectangle','same','samecoordsys','sameside','sample','save','savedefaults','saveline','scale','scale3','scaleO','scaleT','scaleless','scientific','search','searchindex','searchtree','sec','secondaryX','secondaryY','seconds','section','sector','seek','seekeof','segment','sequence','setcontour','setpens','sgn','sgnd','sharpangle','sharpdegrees','shift','shiftless','shipout','shipout3','show','side','simeq','simpson','sin','sinh','size','size3','skewness','skip','slant','sleep','slope','slopefield','solve','solveBVP','sort','sourceline','sphere','split','sqrt','square','srand','standardizecoordsys','startScript','stdev','step','stickframe','stickmarksize','stickmarkspace','stop','straight','straightness','string','stripdirectory','stripextension','stripfile','stripsuffix','strokepath','subdivide','subitem','subpath','substr','sum','surface','symmedial','symmedian','system',
+ 'tab','tableau','tan','tangent','tangential','tangents','tanh','tell','tensionSpecifier','tensorshade','tex','texcolor','texify','texpath','texpreamble','texreset','texshipout','texsize','textpath','thick','thin','tick','tickMax','tickMax3','tickMin','tickMin3','ticklabelshift','ticklocate','tildeframe','tildemarksize','tile','tiling','time','times','title','titlepage','topbox','transform','transformation','transpose','trembleFuzz','triangle','triangleAbc','triangleabc','triangulate','tricoef','tridiagonal','trilinear','trim','truepoint','tube','uncycle','unfill','uniform','unique','unit','unitrand','unitsize','unityroot','unstraighten','upcase','updatefunction','uperiodic','upscale','uptodate','usepackage','usersetting','usetypescript','usleep','value','variance','variancebiased','vbox','vector','vectorfield','verbatim','view','vline','vperiodic','vprojection','warn','warning','windingnumber','write','xaxis','xaxis3','xaxis3At','xaxisAt','xequals','xinput','xlimits','xoutput','xpart','xscale','xscaleO','xtick','xtick3','xtrans','yaxis','yaxis3','yaxis3At','yaxisAt','yequals','ylimits','ypart','yscale','yscaleO','ytick','ytick3','ytrans','zaxis3','zaxis3At','zero','zero3','zlimits','zpart','ztick','ztick3','ztrans'
+ ),
+ 4 => array(
+ 'AliceBlue','Align','Allow','AntiqueWhite','Apricot','Aqua','Aquamarine','Aspect','Azure','BeginPoint','Beige','Bisque','Bittersweet','Black','BlanchedAlmond','Blue','BlueGreen','BlueViolet','Both','Break','BrickRed','Brown','BurlyWood','BurntOrange','CCW','CW','CadetBlue','CarnationPink','Center','Centered','Cerulean','Chartreuse','Chocolate','Coeff','Coral','CornflowerBlue','Cornsilk','Crimson','Crop','Cyan','Dandelion','DarkBlue','DarkCyan','DarkGoldenrod','DarkGray','DarkGreen','DarkKhaki','DarkMagenta','DarkOliveGreen','DarkOrange','DarkOrchid','DarkRed','DarkSalmon','DarkSeaGreen','DarkSlateBlue','DarkSlateGray','DarkTurquoise','DarkViolet','DeepPink','DeepSkyBlue','DefaultHead','DimGray','DodgerBlue','Dotted','Down','Draw','E','ENE','EPS','ESE','E_Euler','E_PC','E_RK2','E_RK3BS','Emerald','EndPoint','Euler','Fill','FillDraw','FireBrick','FloralWhite','ForestGreen','Fuchsia','Gainsboro','GhostWhite','Gold','Goldenrod','Gray','Green','GreenYellow','Honeydew','HookHead','Horizontal','HotPink','I','IgnoreAspect','IndianRed','Indigo','Ivory','JOIN_IN','JOIN_OUT','JungleGreen','Khaki','LM_DWARF','LM_MACHEP','LM_SQRT_DWARF','LM_SQRT_GIANT','LM_USERTOL','Label','Lavender','LavenderBlush','LawnGreen','Left','LeftJustified','LeftSide','LemonChiffon','LightBlue','LightCoral','LightCyan','LightGoldenrodYellow',
+ 'LightGreen','LightGrey','LightPink','LightSalmon','LightSeaGreen','LightSkyBlue','LightSlateGray','LightSteelBlue','LightYellow','Lime','LimeGreen','Linear','Linen','Log','Logarithmic','Magenta','Mahogany','Mark','MarkFill','Maroon','Max','MediumAquamarine','MediumBlue','MediumOrchid','MediumPurple','MediumSeaGreen','MediumSlateBlue','MediumSpringGreen','MediumTurquoise','MediumVioletRed','Melon','MidPoint','MidnightBlue','Min','MintCream','MistyRose','Moccasin','Move','MoveQuiet','Mulberry','N','NE','NNE','NNW','NW','NavajoWhite','Navy','NavyBlue','NoAlign','NoCrop','NoFill','NoSide','OldLace','Olive','OliveDrab','OliveGreen','Orange','OrangeRed','Orchid','Ox','Oy','PC','PaleGoldenrod','PaleGreen','PaleTurquoise','PaleVioletRed','PapayaWhip','Peach','PeachPuff','Periwinkle','Peru','PineGreen','Pink','Plum','PowderBlue','ProcessBlue','Purple','RK2','RK3','RK3BS','RK4','RK5','RK5DP','RK5F','RawSienna','Red','RedOrange','RedViolet','Rhodamine','Right','RightJustified','RightSide','RosyBrown','RoyalBlue','RoyalPurple','RubineRed','S','SE','SSE','SSW','SW','SaddleBrown','Salmon','SandyBrown','SeaGreen','Seashell','Sepia','Sienna','Silver','SimpleHead','SkyBlue','SlateBlue','SlateGray','Snow','SpringGreen','SteelBlue','Suppress','SuppressQuiet','Tan','TeXHead','Teal','TealBlue','Thistle','Ticksize','Tomato',
+ 'Turquoise','UnFill','Up','VERSION','Value','Vertical','Violet','VioletRed','W','WNW','WSW','Wheat','White','WhiteSmoke','WildStrawberry','XYAlign','YAlign','Yellow','YellowGreen','YellowOrange','addpenarc','addpenline','align','allowstepping','angularsystem','animationdelay','appendsuffix','arcarrowangle','arcarrowfactor','arrow2sizelimit','arrowangle','arrowbarb','arrowdir','arrowfactor','arrowhookfactor','arrowlength','arrowsizelimit','arrowtexfactor','authorpen','axis','axiscoverage','axislabelfactor','background','backgroundcolor','backgroundpen','barfactor','barmarksizefactor','basealign','baselinetemplate','beveljoin','bigvertexpen','bigvertexsize','black','blue','bm','bottom','bp','brown','bullet','byfoci','byvertices','camerafactor','chartreuse','circlemarkradiusfactor','circlenodesnumberfactor','circleprecision','circlescale','cm','codefile','codepen','codeskip','colorPen','coloredNodes','coloredSegments',
+ 'conditionlength','conicnodesfactor','count','cputimeformat','crossmarksizefactor','currentcoordsys','currentlight','currentpatterns','currentpen','currentpicture','currentposition','currentprojection','curvilinearsystem','cuttings','cyan','darkblue','darkbrown','darkcyan','darkgray','darkgreen','darkgrey','darkmagenta','darkolive','darkred','dashdotted','dashed','datepen','dateskip','debuggerlines','debugging','deepblue','deepcyan','deepgray','deepgreen','deepgrey','deepmagenta','deepred','default','defaultControl','defaultS','defaultbackpen','defaultcoordsys','defaultexcursion','defaultfilename','defaultformat','defaultmassformat','defaultpen','diagnostics','differentlengths','dot','dotfactor','dotframe','dotted','doublelinepen','doublelinespacing','down','duplicateFuzz','edge','ellipsenodesnumberfactor','eps','epsgeo','epsilon','evenodd','expansionfactor','extendcap','exterior','fermionpen','figureborder','figuremattpen','file3','firstnode','firststep','foregroundcolor','fuchsia','fuzz','gapfactor','ghostpen','gluonamplitude','gluonpen','gluonratio','gray','green','grey','hatchepsilon','havepagenumber','heavyblue','heavycyan','heavygray','heavygreen','heavygrey','heavymagenta','heavyred','hline','hwratio','hyperbola','hyperbolanodesnumberfactor','identity4','ignore','inXasyMode','inch','inches','includegraphicscommand','inf','infinity','institutionpen','intMax','intMin','interior','invert','invisible','itempen','itemskip','itemstep','labelmargin','landscape','lastnode','left','legendhskip','legendlinelength',
+ 'legendmargin','legendmarkersize','legendmaxrelativewidth','legendvskip','lightblue','lightcyan','lightgray','lightgreen','lightgrey','lightmagenta','lightolive','lightred','lightyellow','line','linemargin','lm_infmsg','lm_shortmsg','longdashdotted','longdashed','magenta','magneticRadius','mantissaBits','markangleradius','markangleradiusfactor','markanglespace','markanglespacefactor','mediumblue','mediumcyan','mediumgray','mediumgreen','mediumgrey','mediummagenta','mediumred','mediumyellow','middle','minDistDefault','minblockheight','minblockwidth','mincirclediameter','minipagemargin','minipagewidth','minvertexangle','miterjoin','mm','momarrowfactor','momarrowlength','momarrowmargin','momarrowoffset','momarrowpen','monoPen','morepoints','nCircle','newbulletcolor','ngraph','nil','nmesh','nobasealign','nodeMarginDefault','nodesystem','nomarker','nopoint','noprimary','nullpath','nullpen','numarray','ocgindex','oldbulletcolor','olive','orange','origin','overpaint','page','pageheight','pagemargin','pagenumberalign','pagenumberpen','pagenumberposition','pagewidth','paleblue','palecyan','palegray','palegreen','palegrey',
+ 'palemagenta','palered','paleyellow','parabolanodesnumberfactor','perpfactor','phi','photonamplitude','photonpen','photonratio','pi','pink','plain','plain_bounds','plain_scaling','plus','preamblenodes','pt','purple','r3','r4a','r4b','randMax','realDigits','realEpsilon','realMax','realMin','red','relativesystem','reverse','right','roundcap','roundjoin','royalblue','salmon','saveFunctions','scalarpen','sequencereal','settings','shipped','signedtrailingzero','solid','springgreen','sqrtEpsilon','squarecap','squarepen','startposition','stdin','stdout','stepfactor','stepfraction','steppagenumberpen','stepping','stickframe','stickmarksizefactor','stickmarkspacefactor','swap','textpen','ticksize','tildeframe','tildemarksizefactor','tinv','titlealign','titlepagepen','titlepageposition','titlepen','titleskip','top','trailingzero','treeLevelStep','treeMinNodeWidth','treeNodeStep','trembleAngle','trembleFrequency','trembleRandom','undefined','unitcircle','unitsquare','up','urlpen','urlskip','version','vertexpen','vertexsize','viewportmargin','viewportsize','vline','white','wye','xformStack','yellow','ylabelwidth','zerotickfuzz','zerowinding'
+ )
+ ),
+ 'SYMBOLS' => array(
+ 0 => array(
+ '(', ')', '{', '}', '[', ']'
+ ),
+ 1 => array('<', '>','='),
+ 2 => array('+', '-', '*', '/', '%'),
+ 3 => array('!', '^', '&', '|'),
+ 4 => array('?', ':', ';'),
+ 5 => array('..')
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #b1b100;',
+ 2 => 'color: #000000; font-weight: bold;',
+ 3 => 'color: #990000;',
+ 4 => 'color: #009900; font-weight: bold;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666;',
+ 2 => 'color: #339900;',
+ 'MULTI' => 'color: #ff0000; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;',
+ 1 => 'color: #000099; font-weight: bold;',
+ 2 => 'color: #660099; font-weight: bold;',
+ 3 => 'color: #660099; font-weight: bold;',
+ 4 => 'color: #660099; font-weight: bold;',
+ 5 => 'color: #006699; font-weight: bold;',
+ 'HARD' => '',
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #008000;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #FF0000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #0000dd;',
+ GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;',
+ GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+ GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+ GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;',
+ GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+ GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;',
+ GESHI_NUMBER_FLT_NONSCI => 'color:#800080;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #007788;',
+ 2 => 'color: #007788;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #008000;',
+ 1 => 'color: #000080;',
+ 2 => 'color: #000040;',
+ 3 => 'color: #000040;',
+ 4 => 'color: #008080;',
+ 5 => 'color: #009080;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.',
+ 2 => '::'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4,
+ 'PARSER_CONTROL' => array(
+ 'KEYWORDS' => array(
+ 'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\#])",
+ 'DISALLOWED_AFTER' => "(?![a-zA-Z0-9_\|%\\-])"
+ )
+ )
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/autoconf.php b/plugins/wp-syntax/geshi/geshi/autoconf.php
index 3f35e8a5..7a0f1ee9 100644
--- a/plugins/wp-syntax/geshi/geshi/autoconf.php
+++ b/plugins/wp-syntax/geshi/geshi/autoconf.php
@@ -4,7 +4,7 @@
* -----
* Author: Mihai Vasilian (grayasm@gmail.com)
* Copyright: (c) 2010 Mihai Vasilian
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/01/25
*
* autoconf language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/autohotkey.php b/plugins/wp-syntax/geshi/geshi/autohotkey.php
index de2ad790..970684da 100644
--- a/plugins/wp-syntax/geshi/geshi/autohotkey.php
+++ b/plugins/wp-syntax/geshi/geshi/autohotkey.php
@@ -4,7 +4,7 @@
* --------
* Author: Naveen Garg (naveen.garg@gmail.com)
* Copyright: (c) 2009 Naveen Garg and GeSHi
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/06/11
*
* Autohotkey language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/autoit.php b/plugins/wp-syntax/geshi/geshi/autoit.php
index b51bd27a..ab401b4c 100644
--- a/plugins/wp-syntax/geshi/geshi/autoit.php
+++ b/plugins/wp-syntax/geshi/geshi/autoit.php
@@ -4,7 +4,7 @@
* --------
* Author: big_daddy (robert.i.anthony@gmail.com)
* Copyright: (c) 2006 and to GESHi ;)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/01/26
*
* AutoIT language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/avisynth.php b/plugins/wp-syntax/geshi/geshi/avisynth.php
index af11e985..88f66288 100644
--- a/plugins/wp-syntax/geshi/geshi/avisynth.php
+++ b/plugins/wp-syntax/geshi/geshi/avisynth.php
@@ -4,7 +4,7 @@
* --------
* Author: Ryan Jones (sciguyryan@gmail.com)
* Copyright: (c) 2008 Ryan Jones
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/10/08
*
* AviSynth language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/awk.php b/plugins/wp-syntax/geshi/geshi/awk.php
index 38d7de17..1ec239b7 100644
--- a/plugins/wp-syntax/geshi/geshi/awk.php
+++ b/plugins/wp-syntax/geshi/geshi/awk.php
@@ -4,7 +4,7 @@
* -------
* Author: George Pollard (porges@porg.es)
* Copyright: (c) 2009 George Pollard
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/01/28
*
* Awk language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/bascomavr.php b/plugins/wp-syntax/geshi/geshi/bascomavr.php
new file mode 100644
index 00000000..864f74e8
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/bascomavr.php
@@ -0,0 +1,185 @@
+<?php
+/*************************************************************************************
+ * bascomavr.php
+ * ---------------------------------
+ * Author: aquaticus.info
+ * Copyright: (c) 2008 aquaticus.info
+ * Release Version: 1.0.8.11
+ * Date Started: 2008/01/09
+ *
+ * BASCOM AVR language file for GeSHi.
+ *
+ * You can find the BASCOM AVR Website at (www.mcselec.com/bascom-avr.htm)
+ *
+ * CHANGES
+ * -------
+ * 2008/01/09 (1.0.8.10)
+ * - First Release
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'BASCOM AVR',
+ 'COMMENT_SINGLE' => array(1 => "'"),
+ 'COMMENT_MULTI' => array(),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"'),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 1 => array(
+ // Navy Blue Bold Keywords
+ '1WRESET' , '1WREAD' , '1WWRITE' , '1WSEARCHFIRST' , '1WSEARCHNEXT' ,'1WVERIFY' , '1WIRECOUNT',
+ 'CONFIG' , 'ACI' , 'ADC' , 'BCCARD' , 'CLOCK' , 'COM1' ,
+ 'COM2' , 'PS2EMU' , 'ATEMU' , 'I2CSLAVE' ,
+ 'INPUT', 'OUTPUT', 'GRAPHLCD' , 'KEYBOARD' , 'TIMER0' , 'TIMER1' ,
+ 'LCDBUS' , 'LCDMODE' , '1WIRE' , 'LCD' , 'SERIALOUT' ,
+ 'SERIALIN' , 'SPI' , 'LCDPIN' , 'SDA' , 'SCL' ,
+ 'WATCHDOG' , 'PORT' , 'COUNTER0', 'COUNTER1' , 'TCPIP' , 'TWISLAVE' ,
+ 'X10' , 'XRAM' , 'USB',
+ 'BCD' , 'GRAY2BIN' , 'BIN2GRAY' , 'BIN' , 'MAKEBCD' , 'MAKEDEC' , 'MAKEINT' , 'FORMAT' , 'FUSING' , 'BINVAL' ,
+ 'CRC8' , 'CRC16' , 'CRC16UNI' , 'CRC32' , 'HIGH' , 'HIGHW' , 'LOW',
+ 'DATE' , 'TIME' , 'DATE$' , 'TIME$' , 'DAYOFWEEK' , 'DAYOFYEAR' , 'SECOFDAY' , 'SECELAPSED' , 'SYSDAY' , 'SYSSEC' , 'SYSSECELAPSED',
+ 'WAIT' , 'WAITMS' , 'WAITUS' , 'DELAY',
+ 'BSAVE' , 'BLOAD' , 'GET' , 'VER' , 'DISKFREE' , 'DIR' , 'DriveReset' , 'DriveInit' , 'LINE' , 'INITFILESYSTEM' ,
+ 'EOF' , 'WRITE' , 'FLUSH' , 'FREEFILE' , 'FILEATTR' , 'FILEDATE' , 'FILETIME' , 'FILEDATETIME' , 'FILELEN' , 'SEEK' ,
+ 'KILL' , 'DriveGetIdentity' , 'DriveWriteSector' , 'DriveReadSector' , 'LOC' , 'LOF' , 'PUT' , 'OPEN' , 'CLOSE',
+ 'GLCDCMD' , 'GLCDDATA' , 'SETFONT' , 'PSET' , 'SHOWPIC' , 'SHOWPICE' , 'CIRCLE' , 'BOX',
+ 'I2CINIT' , 'I2CRECEIVE' , 'I2CSEND' , 'I2CSTART','I2CSTOP','I2CRBYTE','I2CWBYTE',
+ 'ALIAS' , 'BITWAIT' , 'TOGGLE' , 'RESET' , 'SET' , 'SHIFTIN' , 'SHIFTOUT' , 'DEBOUNCE' , 'PULSEIN' , 'PULSEOUT',
+ 'IDLE' , 'POWERDOWN' , 'POWERSAVE' , 'ON', 'INTERRUPT' , 'ENABLE' , 'DISABLE' , 'START' , 'VERSION' , 'CLOCKDIVISION' , 'CRYSTAL' , 'STOP',
+ 'ADR' , 'ADR2' , 'WRITEEEPROM' , 'CPEEK' , 'CPEEKH' , 'PEEK' , 'POKE' , 'OUT' , 'READEEPROM' , 'DATA' , 'INP' , 'READ' , 'RESTORE' , 'LOOKDOWN' , 'LOOKUP' , 'LOOKUPSTR' , 'LOAD' , 'LOADADR' , 'LOADLABEL' , 'LOADWORDADR' , 'MEMCOPY',
+ 'RC5SEND' , 'RC6SEND' , 'GETRC5' , 'SONYSEND',
+ 'BAUD' , 'BAUD1', 'BUFSPACE' , 'CLEAR', 'ECHO' , 'WAITKEY' , 'ISCHARWAITING' , 'INKEY' , 'INPUTBIN' , 'INPUTHEX' , 'PRINT', 'PRINT1','PRINT0', 'PRINTBIN' , 'SERIN' , 'SEROUT' , 'SPC' , 'MAKEMODBUS',
+ 'SPIIN' , 'SPIINIT' , 'SPIMOVE' , 'SPIOUT', 'SINGLE',
+ 'ASC' , 'UCASE' , 'LCASE' , 'TRIM' , 'SPLIT' , 'LTRIM' , 'INSTR' , 'SPACE' , 'RTRIM' , 'LEFT' , 'LEN' , 'MID' , 'RIGHT' , 'VAL' , 'STR' , 'CHR' , 'CHECKSUM' , 'HEX' , 'HEXVAL',
+ 'BASE64DEC' , 'BASE64ENC' , 'IP2STR' , 'UDPREAD' , 'UDPWRITE' , 'UDPWRITESTR' , 'TCPWRITE' , 'TCPWRITESTR' , 'TCPREAD' , 'GETDSTIP' , 'GETDSTPORT' , 'SOCKETSTAT' , 'SOCKETCONNECT' , 'SOCKETLISTEN' , 'GETSOCKET' , 'CLOSESOCKET' ,
+ 'SETTCP' , 'GETTCPREGS' , 'SETTCPREGS' , 'SETIPPROTOCOL' , 'TCPCHECKSUM',
+ 'HOME' , 'CURSOR' , 'UPPERLINE' , 'THIRDLINE' , 'INITLCD' , 'LOWERLINE' , 'LCDAT' , 'FOURTHLINE' , 'DISPLAY' , 'LCDCONTRAST' , 'LOCATE' , 'SHIFTCURSOR' , 'DEFLCDCHAR' , 'SHIFTLCD' , 'CLS',
+ 'ACOS' , 'ASIN' , 'ATN' , 'ATN2' , 'EXP' , 'RAD2DEG' , 'FRAC' , 'TAN' , 'TANH' , 'COS' , 'COSH' , 'LOG' , 'LOG10' , 'ROUND' , 'ABS' , 'INT' , 'MAX' , 'MIN' , 'SQR' , 'SGN' , 'POWER' , 'SIN' , 'SINH' , 'FIX' , 'INCR' , 'DECR' , 'DEG2RAD',
+ 'DBG' , 'DEBUG', 'DTMFOUT' , 'ENCODER' , 'GETADC' , 'GETKBD' , 'GETATKBD' , 'GETRC' , 'VALUE' , 'POPALL' , 'PS2MOUSEXY' , 'PUSHALL' ,
+ 'RETURN' , 'RND' , 'ROTATE' , 'SENDSCAN' , 'SENDSCANKBD' , 'SHIFT' , 'SOUND' , 'STCHECK' , 'SWAP' , 'VARPTR' , 'X10DETECT' , 'X10SEND' , 'READMAGCARD' , 'REM' , 'BITS' , 'BYVAL' , 'CALL' , 'READHITAG',
+ 'Buffered', 'Size', 'Dummy', 'Parity', 'None', 'Stopbits', 'Databits', 'Clockpol', 'Synchrone', 'Prescaler', 'Reference', 'int0', 'int1', 'Interrupts',
+ 'Auto', 'avcc', 'ack', 'nack', 'Pin', 'Db4', 'Db3', 'Db2', 'Db1', 'Db7', 'Db6', 'Db5', 'Db0', 'e', 'rs', 'twi',
+ ),
+ 2 => array(
+ // Red Lowercase Keywords
+ '$ASM' , '$BAUD' , '$BAUD1' , '$BGF' , '$BOOT' , '$CRYSTAL' , '$DATA' , '$DBG' , '$DEFAULT' , '$EEPLEAVE' , '$EEPROM' ,
+ '$EEPROMHEX' , '$EXTERNAL' , '$HWSTACK' , '$INC' , '$INCLUDE' , '$INITMICRO' , '$LCD' , '$LCDRS' , '$LCDPUTCTRL' ,
+ '$LCDPUTDATA' , '$LCDVFO' , '$LIB' , '$LOADER' , '$LOADERSIZE' , '$MAP' , '$NOCOMPILE' , '$NOINIT' , '$NORAMCLEAR' ,
+ '$PROG' , '$PROGRAMMER' , '$REGFILE' , '$RESOURCE' , '$ROMSTART', '$SERIALINPUT', '$SERIALINPUT1' , '$SERIALINPUT2LCD' ,
+ '$SERIALOUTPUT' , '$SERIALOUTPUT1' , '$SIM' , '$SWSTACK' , '$TIMEOUT' , '$TINY' , '$WAITSTATE' , '$XRAMSIZE' , '$XRAMSTART', '$XA',
+ '#IF' , '#ELSE' , '#ENDIF', '$framesize'
+ ),
+ 3 => array(
+ // Blue Lowercase Keywords
+ 'IF', 'THEN', 'ELSE', 'END', 'WHILE', 'WEND', 'DO', 'LOOP', 'SELECT', 'CASE', 'FOR', 'NEXT',
+ 'GOSUB' , 'GOTO' , 'LOCAL' , 'SUB' , 'DEFBIT', 'DEFBYTE', 'DEFINT', 'DEFWORD', 'DEFLNG', 'DEFSNG', 'DEFDBL',
+ 'CONST', 'DECLARE', 'FUNCTION', 'DIM', 'EXIT', 'LONG', 'INTEGER', 'BYTE', 'AS', 'STRING', 'WORD'
+ ),
+ 4 => array(
+ //light blue
+ 'PINA.0', 'PINA.1', 'PINA.2', 'PINA.3', 'PINA.4', 'PINA.5', 'PINA.6', 'PINA.7',
+ 'PINB.0', 'PINB.1', 'PINB.2', 'PINB.3', 'PINB.4', 'PINB.5', 'PINB.6', 'PINB.7',
+ 'PINC.0', 'PINC.1', 'PINC.2', 'PINC.3', 'PINC.4', 'PINC.5', 'PINC.6', 'PINC.7',
+ 'PIND.0', 'PIND.1', 'PIND.2', 'PIND.3', 'PIND.4', 'PIND.5', 'PIND.6', 'PIND.7',
+ 'PINE.0', 'PINE.1', 'PINE.2', 'PINE.3', 'PINE.4', 'PINE.5', 'PINE.6', 'PINE.7',
+ 'PINF.0', 'PINF.1', 'PINF.2', 'PINF.3', 'PINF.4', 'PINF.5', 'PINF.6', 'PINF.7',
+
+ 'PORTA.0', 'PORTA.1', 'PORTA.2', 'PORTA.3', 'PORTA.4', 'PORTA.5', 'PORTA.6', 'PORTA.7',
+ 'PORTB.0', 'PORTB.1', 'PORTB.2', 'PORTB.3', 'PORTB.4', 'PORTB.5', 'PORTB.6', 'PORTB.7',
+ 'PORTC.0', 'PORTC.1', 'PORTC.2', 'PORTC.3', 'PORTC.4', 'PORTC.5', 'PORTC.6', 'PORTC.7',
+ 'PORTD.0', 'PORTD.1', 'PORTD.2', 'PORTD.3', 'PORTD.4', 'PORTD.5', 'PORTD.6', 'PORTD.7',
+ 'PORTE.0', 'PORTE.1', 'PORTE.2', 'PORTE.3', 'PORTE.4', 'PORTE.5', 'PORTE.6', 'PORTE.7',
+ 'PORTF.0', 'PORTF.1', 'PORTF.2', 'PORTF.3', 'PORTF.4', 'PORTF.5', 'PORTF.6', 'PORTF.7',
+
+ 'DDRA.0', 'DDRA.1', 'DDRA.2', 'DDRA.3', 'DDRA.4', 'DDRA.5', 'DDRA.6', 'DDRA.7',
+ 'DDRB.0', 'DDRB.1', 'DDRB.2', 'DDRB.3', 'DDRB.4', 'DDRB.5', 'DDRB.6', 'DDRB.7',
+ 'DDRC.0', 'DDRC.1', 'DDRC.2', 'DDRC.3', 'DDRC.4', 'DDRC.5', 'DDRC.6', 'DDRC.7',
+ 'DDRD.0', 'DDRD.1', 'DDRD.2', 'DDRD.3', 'DDRD.4', 'DDRD.5', 'DDRD.6', 'DDRD.7',
+ 'DDRE.0', 'DDRE.1', 'DDRE.2', 'DDRE.3', 'DDRE.4', 'DDRE.5', 'DDRE.6', 'DDRE.7',
+ 'DDRF.0', 'DDRF.1', 'DDRF.2', 'DDRF.3', 'DDRF.4', 'DDRF.5', 'DDRF.6', 'DDRF.7',
+
+ 'DDRA','DDRB','DDRC','DDRD','DDRE','DDRF',
+ 'PORTA','PORTB','PORTC','PORTD','PORTE','PORTF',
+ 'PINA','PINB','PINC','PIND','PINE','PINF',
+ )
+ ),
+ 'SYMBOLS' => array(
+ '=', '<', '>', '>=', '<=', '+', '-', '*', '/', '%', '(', ')', '{', '}', '[', ']', ';', ':', '$', '&H'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #000080; font-weight: bold;',
+ 2 => 'color: #FF0000;',
+ 3 => 'color: #0000FF;',
+ 4 => 'color: #0080FF;',
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #657CC4; font-style: italic;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #000080;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #008000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #000080; font-weight: bold;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #0000FF;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ ),
+ 'SCRIPT' => array(
+ ),
+ 'REGEXPS' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/bash.php b/plugins/wp-syntax/geshi/geshi/bash.php
index 658111a0..c69f0054 100644
--- a/plugins/wp-syntax/geshi/geshi/bash.php
+++ b/plugins/wp-syntax/geshi/geshi/bash.php
@@ -4,7 +4,7 @@
* --------
* Author: Andreas Gohr (andi@splitbrain.org)
* Copyright: (c) 2004 Andreas Gohr, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/20
*
* BASH language file for GeSHi.
@@ -65,7 +65,10 @@ $language_data = array (
//BASH-style Heredoc
2 => '/<<-?\s*?(\'?)([a-zA-Z0-9]+)\1\\n.*\\n\\2(?![a-zA-Z0-9])/siU',
//Escaped String Starters
- 3 => "/\\\\['\"]/siU"
+ 3 => "/\\\\['\"]/siU",
+ // Single-Line Shell usage: Hide the prompt at the beginning
+ /* 4 => "/\A(?!#!)\s*(?>[\w:@\\/\\-\\._~]*[$#]\s?)?(?=[^\n]+\n?\Z)|^(?!#!)(\w+@)?[\w\\-\\.]+(:~?)[\w\\/\\-\\._]*?[$#]\s?/ms" */
+ 4 => "/\A(?!#!)(?:(?>[\w:@\\/\\-\\._~]*)[$#]\s?)(?=(?>[^\n]+)\n?\Z)|^(?!#!)(?:\w+@)?(?>[\w\\-\\.]+)(?>:~?[\w\\/\\-\\._]*?)?[$#]\s?/sm"
),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"'),
@@ -90,10 +93,44 @@ $language_data = array (
'if', 'in', 'select', 'set', 'then', 'until', 'while', 'time'
),
2 => array(
- 'aclocal', 'aconnect', 'aplay', 'apm', 'apmsleep', 'apropos',
- 'apt-cache', 'apt-file', 'apt-get', 'apt-key', 'apt-src', 'aptitude',
- 'ar', 'arch', 'arecord', 'as', 'as86', 'ash', 'autoconf',
- 'autoheader', 'automake', 'awk',
+ 'aclocal', 'aconnect', 'apachectl', 'apache2ctl', 'aplay', 'apm',
+ 'apmsleep', 'apropos', 'apt-cache', 'apt-cdrom', 'apt-config',
+ 'apt-file', 'apt-ftparchive', 'apt-get', 'apt-key', 'apt-listbugs',
+ 'apt-listchanges', 'apt-mark', 'apt-mirror', 'apt-sortpkgs',
+ 'apt-src', 'apticron', 'aptitude', 'aptsh', 'apxs', 'apxs2', 'ar',
+ 'arch', 'arecord', 'as', 'as86', 'ash', 'autoconf', 'autoheader',
+ 'automake', 'awk',
+
+ 'apachectl start', 'apachectl stop', 'apachectl restart',
+ 'apachectl graceful', 'apachectl graceful-stop',
+ 'apachectl configtest', 'apachectl status', 'apachectl fullstatus',
+ 'apachectl help', 'apache2ctl start', 'apache2ctl stop',
+ 'apache2ctl restart', 'apache2ctl graceful',
+ 'apache2ctl graceful-stop', 'apache2ctl configtest',
+ 'apache2ctl status', 'apache2ctl fullstatus', 'apache2ctl help',
+
+ 'apt-cache add', 'apt-cache depends', 'apt-cache dotty',
+ 'apt-cache dump', 'apt-cache dumpavail', 'apt-cache gencaches',
+ 'apt-cache pkgnames', 'apt-cache policy', 'apt-cache rdepends',
+ 'apt-cache search', 'apt-cache show', 'apt-cache showauto',
+ 'apt-cache showpkg', 'apt-cache showsrc', 'apt-cache stats',
+ 'apt-cache unmet', 'apt-cache xvcg', 'apt-cdrom add',
+ 'apt-cdrom ident', 'apt-config dump', 'apt-config shell',
+ 'apt-file find', 'apt-file list', 'apt-file purge',
+ 'apt-file search', 'apt-file shot', 'apt-file update',
+ 'apt-get autoclean', 'apt-get autoremove', 'apt-get build-dep',
+ 'apt-get check', 'apt-get clean', 'apt-get dist-upgrade',
+ 'apt-get dselect-upgrade', 'apt-get install', 'apt-get markauto',
+ 'apt-get purge', 'apt-get remove', 'apt-get source',
+ 'apt-get unmarkauto', 'apt-get update', 'apt-get upgrade',
+ 'apt-key add', 'apt-key adv', 'apt-key del', 'apt-key export',
+ 'apt-key exportall', 'apt-key finger', 'apt-key list',
+ 'apt-key net-update', 'apt-key update', 'apt-listbugs apt',
+ 'apt-listbugs list', 'apt-listbugs rss', 'apt-src build',
+ 'apt-src clean', 'apt-src import', 'apt-src install',
+ 'apt-src list', 'apt-src location', 'apt-src name',
+ 'apt-src remove', 'apt-src update', 'apt-src upgrade',
+ 'apt-src version',
'basename', 'bash', 'bc', 'bison', 'bunzip2', 'bzcat',
'bzcmp', 'bzdiff', 'bzegrep', 'bzfgrep', 'bzgrep',
@@ -104,6 +141,14 @@ $language_data = array (
'chown', 'chroot', 'chsh', 'chvt', 'clear', 'cmp', 'comm', 'co',
'col', 'cp', 'cpio', 'cpp', 'csh', 'cut', 'cvs', 'cvs-pserver',
+ 'cvs add', 'cvs admin', 'cvs annotate', 'cvs checkout',
+ 'cvs commit', 'cvs diff', 'cvs edit', 'cvs editors', 'cvs export',
+ 'cvs history', 'cvs import', 'cvs init', 'cvs log', 'cvs login',
+ 'cvs logout', 'cvs ls', 'cvs pserver', 'cvs rannotate',
+ 'cvs rdiff', 'cvs release', 'cvs remove', 'cvs rlog', 'cvs rls',
+ 'cvs rtag', 'cvs server', 'cvs status', 'cvs tag', 'cvs unedit',
+ 'cvs update', 'cvs version', 'cvs watch', 'cvs watchers',
+
'dash', 'date', 'dc', 'dch', 'dcop', 'dd', 'ddate', 'ddd',
'deallocvt', 'debconf', 'defoma', 'depmod', 'df', 'dh',
'dialog', 'diff', 'diff3', 'dig', 'dir', 'dircolors', 'directomatic',
@@ -112,15 +157,55 @@ $language_data = array (
'ed', 'egrep', 'env', 'expr',
- 'false', 'fbset', 'ffmpeg', 'fgconsole','fgrep', 'file', 'find',
- 'flex', 'flex++', 'fmt', 'free', 'ftp', 'funzip', 'fuser',
+ 'false', 'fbset', 'fdisk', 'ffmpeg', 'fgconsole','fgrep', 'file',
+ 'find', 'flex', 'flex++', 'fmt', 'free', 'ftp', 'funzip', 'fuser',
'g++', 'gawk', 'gc','gcc', 'gdb', 'getent', 'getkeycodes',
'getopt', 'gettext', 'gettextize', 'gimp', 'gimp-remote',
'gimptool', 'gmake', 'gocr', 'grep', 'groups', 'gs', 'gunzip',
'gzexe', 'gzip',
- 'git', 'gitaction', 'git-add', 'git-add--interactive', 'git-am',
+ 'git', 'git add', 'git add--interactive', 'git am', 'git annotate',
+ 'git apply', 'git archive', 'git bisect', 'git bisect--helper',
+ 'git blame', 'git branch', 'git bundle', 'git cat-file',
+ 'git check-attr', 'git checkout', 'git checkout-index',
+ 'git check-ref-format', 'git cherry', 'git cherry-pick',
+ 'git clean', 'git clone', 'git commit', 'git commit-tree',
+ 'git config', 'git count-objects', 'git daemon', 'git describe',
+ 'git diff', 'git diff-files', 'git diff-index', 'git difftool',
+ 'git difftool--helper', 'git diff-tree', 'git fast-export',
+ 'git fast-import', 'git fetch', 'git fetch-pack',
+ 'git filter-branch', 'git fmt-merge-msg', 'git for-each-ref',
+ 'git format-patch', 'git fsck', 'git fsck-objects', 'git gc',
+ 'git get-tar-commit-id', 'git grep', 'git hash-object', 'git help',
+ 'git http-backend', 'git http-fetch', 'git http-push',
+ 'git imap-send', 'git index-pack', 'git init', 'git init-db',
+ 'git instaweb', 'git log', 'git lost-found', 'git ls-files',
+ 'git ls-remote', 'git ls-tree', 'git mailinfo', 'git mailsplit',
+ 'git merge', 'git merge-base', 'git merge-file', 'git merge-index',
+ 'git merge-octopus', 'git merge-one-file', 'git merge-ours',
+ 'git merge-recursive', 'git merge-resolve', 'git merge-subtree',
+ 'git mergetool', 'git merge-tree', 'git mktag', 'git mktree',
+ 'git mv', 'git name-rev', 'git notes', 'git pack-objects',
+ 'git pack-redundant', 'git pack-refs', 'git patch-id',
+ 'git peek-remote', 'git prune', 'git prune-packed', 'git pull',
+ 'git push', 'git quiltimport', 'git read-tree', 'git rebase',
+ 'git rebase--interactive', 'git receive-pack', 'git reflog',
+ 'git relink', 'git remote', 'git remote-ftp', 'git remote-ftps',
+ 'git remote-http', 'git remote-https', 'git remote-testgit',
+ 'git repack', 'git replace', 'git repo-config', 'git request-pull',
+ 'git rerere', 'git reset', 'git revert', 'git rev-list',
+ 'git rev-parse', 'git rm', 'git send-pack', 'git shell',
+ 'git shortlog', 'git show', 'git show-branch', 'git show-index',
+ 'git show-ref', 'git stage', 'git stash', 'git status',
+ 'git stripspace', 'git submodule', 'git symbolic-ref', 'git tag',
+ 'git tar-tree', 'git unpack-file', 'git unpack-objects',
+ 'git update-index', 'git update-ref', 'git update-server-info',
+ 'git upload-archive', 'git upload-pack', 'git var',
+ 'git verify-pack', 'git verify-tag', 'git web--browse',
+ 'git whatchanged', 'git write-tree',
+
+ 'gitaction', 'git-add', 'git-add--interactive', 'git-am',
'git-annotate', 'git-apply', 'git-archive', 'git-bisect',
'git-bisect--helper', 'git-blame', 'git-branch', 'git-bundle',
'git-cat-file', 'git-check-attr', 'git-checkout',
@@ -166,6 +251,9 @@ $language_data = array (
'id', 'ifconfig', 'ifdown', 'ifup', 'igawk', 'install',
+ 'ip', 'ip addr', 'ip addrlabel', 'ip link', 'ip maddr', 'ip mroute',
+ 'ip neigh', 'ip route', 'ip rule', 'ip tunnel', 'ip xfrm',
+
'join',
'kbd_mode','kbdrate', 'kdialog', 'kfile', 'kill', 'killall',
@@ -200,6 +288,20 @@ $language_data = array (
'svnadmin', 'svndumpfilter', 'svnlook', 'svnmerge', 'svnmucc',
'svnserve', 'svnshell', 'svnsync', 'svnversion', 'svnwrap', 'sync',
+ 'svn add', 'svn ann', 'svn annotate', 'svn blame', 'svn cat',
+ 'svn changelist', 'svn checkout', 'svn ci', 'svn cl', 'svn cleanup',
+ 'svn co', 'svn commit', 'svn copy', 'svn cp', 'svn del',
+ 'svn delete', 'svn di', 'svn diff', 'svn export', 'svn h',
+ 'svn help', 'svn import', 'svn info', 'svn list', 'svn lock',
+ 'svn log', 'svn ls', 'svn merge', 'svn mergeinfo', 'svn mkdir',
+ 'svn move', 'svn mv', 'svn pd', 'svn pdel', 'svn pe', 'svn pedit',
+ 'svn pg', 'svn pget', 'svn pl', 'svn plist', 'svn praise',
+ 'svn propdel', 'svn propedit', 'svn propget', 'svn proplist',
+ 'svn propset', 'svn ps', 'svn pset', 'svn remove', 'svn ren',
+ 'svn rename', 'svn resolve', 'svn resolved', 'svn revert', 'svn rm',
+ 'svn st', 'svn stat', 'svn status', 'svn sw', 'svn switch',
+ 'svn unlock', 'svn up', 'svn update',
+
'tac', 'tail', 'tar', 'tee', 'tempfile', 'touch', 'tr', 'tree',
'true',
@@ -216,7 +318,14 @@ $language_data = array (
'xargs', 'xhost', 'xmodmap', 'xset',
- 'yacc', 'yes', 'ypdomainname',
+ 'yacc', 'yes', 'ypdomainname', 'yum',
+
+ 'yum check-update', 'yum clean', 'yum deplist', 'yum erase',
+ 'yum groupinfo', 'yum groupinstall', 'yum grouplist',
+ 'yum groupremove', 'yum groupupdate', 'yum info', 'yum install',
+ 'yum list', 'yum localinstall', 'yum localupdate', 'yum makecache',
+ 'yum provides', 'yum remove', 'yum resolvedep', 'yum search',
+ 'yum shell', 'yum update', 'yum upgrade', 'yum whatprovides',
'zcat', 'zcmp', 'zdiff', 'zdump', 'zegrep', 'zfgrep', 'zforce',
'zgrep', 'zip', 'zipgrep', 'zipinfo', 'zless', 'zmore', 'znew',
@@ -252,7 +361,8 @@ $language_data = array (
0 => 'color: #666666; font-style: italic;',
1 => 'color: #800000;',
2 => 'color: #cc0000; font-style: italic;',
- 3 => 'color: #000000; font-weight: bold;'
+ 3 => 'color: #000000; font-weight: bold;',
+ 4 => 'color: #666666;'
),
'ESCAPE_CHAR' => array(
1 => 'color: #000099; font-weight: bold;',
@@ -318,10 +428,13 @@ $language_data = array (
'DISALLOWED_BEFORE' => '$'
),
'KEYWORDS' => array(
- 'DISALLOWED_BEFORE' => "(?<![\.\-a-zA-Z0-9_\$\#])",
- 'DISALLOWED_AFTER' => "(?![\.\-a-zA-Z0-9_%=\\/])"
+ 'DISALLOWED_BEFORE' => "(?<![\.\-a-zA-Z0-9_\$\#:])",
+ 'DISALLOWED_AFTER' => "(?![\.\-a-zA-Z0-9_%=\\/:])",
+ 2 => array(
+ 'SPACE_AS_WHITESPACE' => false
+ )
+ )
)
- )
);
?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/basic4gl.php b/plugins/wp-syntax/geshi/geshi/basic4gl.php
index ee25ca78..35c92740 100644
--- a/plugins/wp-syntax/geshi/geshi/basic4gl.php
+++ b/plugins/wp-syntax/geshi/geshi/basic4gl.php
@@ -4,7 +4,7 @@
* ---------------------------------
* Author: Matthew Webb (bmatthew1@blueyonder.co.uk)
* Copyright: (c) 2004 Matthew Webb (http://matthew-4gl.wikispaces.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/09/15
*
* Basic4GL language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/bf.php b/plugins/wp-syntax/geshi/geshi/bf.php
index dd831216..c06ca5bf 100644
--- a/plugins/wp-syntax/geshi/geshi/bf.php
+++ b/plugins/wp-syntax/geshi/geshi/bf.php
@@ -4,7 +4,7 @@
* ----------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/10/31
*
* Brainfuck language file for GeSHi.
@@ -63,7 +63,7 @@ $language_data = array (
1 => 'color: #666666; font-style: italic;'
),
'BRACKETS' => array(
- 0 => 'color: #66cc66;'
+ 0 => 'color: #660000;'
),
'STRINGS' => array(
0 => 'color: #ff0000;'
@@ -76,8 +76,8 @@ $language_data = array (
0 => 'color: #006600;',
1 => 'color: #660000;',
2 => 'color: #000066;',
- 3 => 'color: #660066;',
- 4 => 'color: #666600;'
+ 3 => 'color: #666600;',
+ 4 => 'color: #660066;'
),
'ESCAPE_CHAR' => array(
),
@@ -102,8 +102,9 @@ $language_data = array (
'PARSER_CONTROL' => array(
'ENABLE_FLAGS' => array(
'STRINGS' => GESHI_NEVER,
- 'NUMBERS' => GESHI_NEVER
- ),
+ 'NUMBERS' => GESHI_NEVER,
+ 'BRACKETS' => GESHI_NEVER
+ ),
'KEYWORDS' => array(
'DISALLOW_BEFORE' => '',
'DISALLOW_AFTER' => ''
@@ -111,4 +112,4 @@ $language_data = array (
)
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/bibtex.php b/plugins/wp-syntax/geshi/geshi/bibtex.php
index 9a6af63b..51cb4ceb 100644
--- a/plugins/wp-syntax/geshi/geshi/bibtex.php
+++ b/plugins/wp-syntax/geshi/geshi/bibtex.php
@@ -4,7 +4,7 @@
* -----
* Author: Quinn Taylor (quinntaylor@mac.com)
* Copyright: (c) 2009 Quinn Taylor (quinntaylor@mac.com), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/04/29
*
* BibTeX language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/blitzbasic.php b/plugins/wp-syntax/geshi/geshi/blitzbasic.php
index e431d3af..1d3c08d0 100644
--- a/plugins/wp-syntax/geshi/geshi/blitzbasic.php
+++ b/plugins/wp-syntax/geshi/geshi/blitzbasic.php
@@ -4,7 +4,7 @@
* --------------
* Author: P�draig O`Connel (info@moonsword.info)
* Copyright: (c) 2005 P�draig O`Connel (http://moonsword.info)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 16.10.2005
*
* BlitzBasic language file for GeSHi.
@@ -56,7 +56,7 @@ $language_data = array (
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
1 => array(
- 'If','EndIf','ElseIf','Else If','Else','While','Wend','Return','Next','Include','End Type','End Select','End If','End Function','End','Select',
+ 'If','EndIf','ElseIf','Else','While','Wend','Return','Next','Include','End Type','End Select','End If','End Function','End','Select',
'Type','Forever','For','Or','And','AppTitle','Case','Goto','Gosub','Step','Stop','Int','Last','False','Then','To','True','Until','Float',
'String','Before','Not'
),
diff --git a/plugins/wp-syntax/geshi/geshi/bnf.php b/plugins/wp-syntax/geshi/geshi/bnf.php
index 13341f75..ca15cf9e 100644
--- a/plugins/wp-syntax/geshi/geshi/bnf.php
+++ b/plugins/wp-syntax/geshi/geshi/bnf.php
@@ -4,7 +4,7 @@
* --------
* Author: Rowan Rodrik van der Molen (rowan@bigsmoke.us)
* Copyright: (c) 2006 Rowan Rodrik van der Molen (http://www.bigsmoke.us/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/09/28
*
* BNF (Backus-Naur form) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/boo.php b/plugins/wp-syntax/geshi/geshi/boo.php
index 37c63048..b68d442f 100644
--- a/plugins/wp-syntax/geshi/geshi/boo.php
+++ b/plugins/wp-syntax/geshi/geshi/boo.php
@@ -4,7 +4,7 @@
* --------
* Author: Marcus Griep (neoeinstein+GeSHi@gmail.com)
* Copyright: (c) 2007 Marcus Griep (http://www.xpdm.us)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/09/10
*
* Boo language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/c.php b/plugins/wp-syntax/geshi/geshi/c.php
index 1cdc24f1..35d5b019 100644
--- a/plugins/wp-syntax/geshi/geshi/c.php
+++ b/plugins/wp-syntax/geshi/geshi/c.php
@@ -7,7 +7,7 @@
* - Jack Lloyd (lloyd@randombit.net)
* - Michael Mol (mikemol@gmail.com)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* C language file for GeSHi.
@@ -92,7 +92,85 @@ $language_data = array (
'null', 'false', 'break', 'true', 'function', 'enum', 'extern', 'inline'
),
3 => array(
- 'printf', 'cout'
+ // assert.h
+ 'assert',
+
+ //complex.h
+ 'cabs', 'cacos', 'cacosh', 'carg', 'casin', 'casinh', 'catan',
+ 'catanh', 'ccos', 'ccosh', 'cexp', 'cimag', 'cis', 'clog', 'conj',
+ 'cpow', 'cproj', 'creal', 'csin', 'csinh', 'csqrt', 'ctan', 'ctanh',
+
+ //ctype.h
+ 'digittoint', 'isalnum', 'isalpha', 'isascii', 'isblank', 'iscntrl',
+ 'isdigit', 'isgraph', 'islower', 'isprint', 'ispunct', 'isspace',
+ 'isupper', 'isxdigit', 'toascii', 'tolower', 'toupper',
+
+ //inttypes.h
+ 'imaxabs', 'imaxdiv', 'strtoimax', 'strtoumax', 'wcstoimax',
+ 'wcstoumax',
+
+ //locale.h
+ 'localeconv', 'setlocale',
+
+ //math.h
+ 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'exp',
+ 'fabs', 'floor', 'frexp', 'ldexp', 'log', 'log10', 'modf', 'pow',
+ 'sin', 'sinh', 'sqrt', 'tan', 'tanh',
+
+ //setjmp.h
+ 'longjmp', 'setjmp',
+
+ //signal.h
+ 'raise',
+
+ //stdarg.h
+ 'va_arg', 'va_copy', 'va_end', 'va_start',
+
+ //stddef.h
+ 'offsetof',
+
+ //stdio.h
+ 'clearerr', 'fclose', 'fdopen', 'feof', 'ferror', 'fflush', 'fgetc',
+ 'fgetpos', 'fgets', 'fopen', 'fprintf', 'fputc', 'fputchar',
+ 'fputs', 'fread', 'freopen', 'fscanf', 'fseek', 'fsetpos', 'ftell',
+ 'fwrite', 'getc', 'getch', 'getchar', 'gets', 'perror', 'printf',
+ 'putc', 'putchar', 'puts', 'remove', 'rename', 'rewind', 'scanf',
+ 'setbuf', 'setvbuf', 'snprintf', 'sprintf', 'sscanf', 'tmpfile',
+ 'tmpnam', 'ungetc', 'vfprintf', 'vfscanf', 'vprintf', 'vscanf',
+ 'vsprintf', 'vsscanf',
+
+ //stdlib.h
+ 'abort', 'abs', 'atexit', 'atof', 'atoi', 'atol', 'bsearch',
+ 'calloc', 'div', 'exit', 'free', 'getenv', 'itoa', 'labs', 'ldiv',
+ 'ltoa', 'malloc', 'qsort', 'rand', 'realloc', 'srand', 'strtod',
+ 'strtol', 'strtoul', 'system',
+
+ //string.h
+ 'memchr', 'memcmp', 'memcpy', 'memmove', 'memset', 'strcat',
+ 'strchr', 'strcmp', 'strcoll', 'strcpy', 'strcspn', 'strerror',
+ 'strlen', 'strncat', 'strncmp', 'strncpy', 'strpbrk', 'strrchr',
+ 'strspn', 'strstr', 'strtok', 'strxfrm',
+
+ //time.h
+ 'asctime', 'clock', 'ctime', 'difftime', 'gmtime', 'localtime',
+ 'mktime', 'strftime', 'time',
+
+ //wchar.h
+ 'btowc', 'fgetwc', 'fgetws', 'fputwc', 'fputws', 'fwide',
+ 'fwprintf', 'fwscanf', 'getwc', 'getwchar', 'mbrlen', 'mbrtowc',
+ 'mbsinit', 'mbsrtowcs', 'putwc', 'putwchar', 'swprintf', 'swscanf',
+ 'ungetwc', 'vfwprintf', 'vswprintf', 'vwprintf', 'wcrtomb',
+ 'wcscat', 'wcschr', 'wcscmp', 'wcscoll', 'wcscpy', 'wcscspn',
+ 'wcsftime', 'wcslen', 'wcsncat', 'wcsncmp', 'wcsncpy', 'wcspbrk',
+ 'wcsrchr', 'wcsrtombs', 'wcsspn', 'wcsstr', 'wcstod', 'wcstok',
+ 'wcstol', 'wcstoul', 'wcsxfrm', 'wctob', 'wmemchr', 'wmemcmp',
+ 'wmemcpy', 'wmemmove', 'wmemset', 'wprintf', 'wscanf',
+
+ //wctype.h
+ 'iswalnum', 'iswalpha', 'iswcntrl', 'iswctype', 'iswdigit',
+ 'iswgraph', 'iswlower', 'iswprint', 'iswpunct', 'iswspace',
+ 'iswupper', 'iswxdigit', 'towctrans', 'towlower', 'towupper',
+ 'wctrans', 'wctype'
),
4 => array(
'auto', 'char', 'const', 'double', 'float', 'int', 'long',
@@ -111,7 +189,8 @@ $language_data = array (
'int8_t', 'int16_t', 'int32_t', 'int64_t',
'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t',
- 'intmax_t', 'uintmax_t', 'intptr_t', 'uintptr_t'
+ 'intmax_t', 'uintmax_t', 'intptr_t', 'uintptr_t',
+ 'size_t', 'off_t'
),
),
'SYMBOLS' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/c_loadrunner.php b/plugins/wp-syntax/geshi/geshi/c_loadrunner.php
new file mode 100644
index 00000000..42b3d772
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/c_loadrunner.php
@@ -0,0 +1,323 @@
+<?php
+/*************************************************************************************
+ * c_loadrunner.php
+ * ---------------------------------
+ * Author: Stuart Moncrieff (stuart at myloadtest dot com)
+ * Copyright: (c) 2010 Stuart Moncrieff (http://www.myloadtest.com/loadrunner-syntax-highlighter/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2010-07-25
+ *
+ * C (for LoadRunner) language file for GeSHi.
+ *
+ * Based on LoadRunner 9.52.
+ *
+ * CHANGES
+ * -------
+ * 2010-08-01 (1.0.8.9)
+ * - Added highlighting support for LoadRunner {parameters}.
+ * 2010-07-25 (1.0.8.8)
+ * - First Release. Syntax highlighting support for lr_, web_, and sapgui_ functions only.
+ *
+ * TODO (updated 2010-07-25)
+ * -------------------------
+ * - Add support for other vuser types: MMS, FTP, etc.
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * ************************************************************************************/
+
+$language_data = array (
+ // The First Indices
+ 'LANG_NAME' => 'C (LoadRunner)',
+ 'COMMENT_SINGLE' => array(1 => '//'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ // Escape characters within strings (like \\) are not highlighted differently in LoadRunner, so
+ // I am using GeSHi escape characters (or regular expressions) to highlight LoadRunner {parameters}.
+ // LoadRunner {parameters} must begin with a letter and contain only alphanumeric characters and '_'
+ 'ESCAPE_REGEXP' => array(
+ 0 => "#\{[a-zA-Z]{1}[a-zA-Z_]{0,}\}#",
+ ),
+
+ // Keywords
+ 'KEYWORDS' => array(
+ // Keywords from http://en.wikipedia.org/wiki/C_syntax
+ 1 => array(
+ 'auto', 'break', 'case', 'char', 'const', 'continue', 'default',
+ 'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto',
+ 'if', 'inline', 'int', 'long', 'register', 'restrict', 'return',
+ 'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
+ 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while',
+ '_Bool', '_Complex', '_Imaginary'
+ ),
+ // C preprocessor directives from http://en.wikipedia.org/wiki/C_preprocessor
+ 2 => array(
+ '#define', '#if', '#ifdef', '#ifndef', '#include', '#else', '#elif', '#endif', '#pragma', '#undef'
+ ),
+ // Functions from lrun.h
+ 3 => array(
+ 'lr_start_transaction', 'lr_start_sub_transaction', 'lr_start_transaction_instance', 'lr_end_transaction',
+ 'lr_end_sub_transaction', 'lr_end_transaction_instance', 'lr_stop_transaction', 'lr_stop_transaction_instance',
+ 'lr_resume_transaction', 'lr_resume_transaction_instance', 'lr_wasted_time', 'lr_set_transaction', 'lr_user_data_point',
+ 'lr_user_data_point_instance', 'lr_user_data_point_ex', 'lr_user_data_point_instance_ex', 'lr_get_transaction_duration',
+ 'lr_get_trans_instance_duration', 'lr_get_transaction_think_time', 'lr_get_trans_instance_think_time',
+ 'lr_get_transaction_wasted_time', 'lr_get_trans_instance_wasted_time', 'lr_get_transaction_status',
+ 'lr_get_trans_instance_status', 'lr_set_transaction_status', 'lr_set_transaction_status_by_name',
+ 'lr_set_transaction_instance_status', 'lr_start_timer', 'lr_end_timer', 'lr_rendezvous', 'lr_rendezvous_ex',
+ 'lr_get_vuser_ip', 'lr_whoami', 'lr_get_host_name', 'lr_get_master_host_name', 'lr_get_attrib_long',
+ 'lr_get_attrib_string', 'lr_get_attrib_double', 'lr_paramarr_idx', 'lr_paramarr_random', 'lr_paramarr_len',
+ 'lr_param_unique', 'lr_param_sprintf', 'lr_load_dll', 'lr_continue_on_error', 'lr_decrypt', 'lr_abort', 'lr_exit',
+ 'lr_peek_events', 'lr_think_time', 'lr_debug_message', 'lr_log_message', 'lr_message', 'lr_error_message',
+ 'lr_output_message', 'lr_vuser_status_message', 'lr_fail_trans_with_error', 'lr_next_row', 'lr_advance_param',
+ 'lr_eval_string', 'lr_eval_string_ext', 'lr_eval_string_ext_free', 'lr_param_increment', 'lr_save_var',
+ 'lr_save_string', 'lr_save_int', 'lr_save_datetime', 'lr_save_searched_string', 'lr_set_debug_message',
+ 'lr_get_debug_message', 'lr_enable_ip_spoofing', 'lr_disable_ip_spoofing', 'lr_convert_string_encoding'
+ ),
+ // Constants from lrun.h
+ 4 => array(
+ 'DP_FLAGS_NO_LOG', 'DP_FLAGS_STANDARD_LOG', 'DP_FLAGS_EXTENDED_LOG', 'merc_timer_handle_t', 'LR_EXIT_VUSER',
+ 'LR_EXIT_ACTION_AND_CONTINUE', 'LR_EXIT_ITERATION_AND_CONTINUE', 'LR_EXIT_VUSER_AFTER_ITERATION',
+ 'LR_EXIT_VUSER_AFTER_ACTION', 'LR_EXIT_MAIN_ITERATION_AND_CONTINUE', 'LR_MSG_CLASS_DISABLE_LOG',
+ 'LR_MSG_CLASS_STANDARD_LOG', 'LR_MSG_CLASS_RETURNED_DATA', 'LR_MSG_CLASS_PARAMETERS', 'LR_MSG_CLASS_ADVANCED_TRACE',
+ 'LR_MSG_CLASS_EXTENDED_LOG', 'LR_MSG_CLASS_SENT_DATA', 'LR_MSG_CLASS_JIT_LOG_ON_ERROR', 'LR_SWITCH_OFF', 'LR_SWITCH_ON',
+ 'LR_SWITCH_DEFAULT', 'ONE_DAY', 'ONE_HOUR', 'ONE_MIN', 'DATE_NOW', 'TIME_NOW', 'LR_MSG_CLASS_BRIEF_LOG',
+ 'LR_MSG_CLASS_RESULT_DATA', 'LR_MSG_CLASS_FULL_TRACE', 'LR_MSG_CLASS_AUTO_LOG', 'LR_MSG_OFF', 'LR_MSG_ON',
+ 'LR_MSG_DEFAULT'
+ ),
+ // Functions from web_api.h
+ 5 => array(
+ 'web_reg_add_cookie', 'web_report_data_point', 'web_text_link', 'web_element', 'web_image_link', 'web_static_image',
+ 'web_image_submit', 'web_button', 'web_edit_field', 'web_radio_group', 'web_check_box', 'web_list', 'web_text_area',
+ 'web_map_area', 'web_eval_java_script', 'web_reg_dialog', 'web_reg_cross_step_download', 'web_browser',
+ 'web_set_rts_key', 'web_save_param_length', 'web_save_timestamp_param', 'web_load_cache', 'web_dump_cache',
+ 'web_add_cookie_ex'
+ ),
+ // Constants from web_api.h
+ 6 => array(
+ 'DESCRIPTION', 'ACTION', 'VERIFICATION', 'LR_NOT_FOUND', 'HTTP_INFO_TOTAL_REQUEST_STAT',
+ 'HTTP_INFO_TOTAL_RESPONSE_STAT', 'LRW_OPT_STOP_VUSER_ON_ERROR', 'LRW_OPT_DISPLAY_IMAGE_BODY'
+ ),
+ // Functions from as_web.h
+ 7 => array(
+ 'web_add_filter', 'web_add_auto_filter', 'web_add_auto_header', 'web_add_header', 'web_add_cookie',
+ 'web_cleanup_auto_headers', 'web_cleanup_cookies', 'web_concurrent_end', 'web_concurrent_start', 'web_create_html_param',
+ 'web_create_html_param_ex', 'web_custom_request', 'web_disable_keep_alive', 'web_enable_keep_alive', 'web_find',
+ 'web_get_int_property', 'web_image', 'web_image_check', 'web_link', 'web_global_verification', 'web_reg_find',
+ 'web_reg_save_param', 'web_convert_param', 'web_remove_auto_filter', 'web_remove_auto_header', 'web_revert_auto_header',
+ 'web_remove_cookie', 'web_save_header', 'web_set_certificate', 'web_set_certificate_ex', 'web_set_connections_limit',
+ 'web_set_max_html_param_len', 'web_set_max_retries', 'web_set_proxy', 'web_set_proxy_bypass', 'web_set_secure_proxy',
+ 'web_set_sockets_option', 'web_set_option', 'web_set_timeout', 'web_set_user', 'web_sjis_to_euc_param',
+ 'web_submit_data', 'web_submit_form', 'web_url', 'web_set_proxy_bypass_local', 'web_cache_cleanup',
+ 'web_create_html_query', 'web_create_radio_button_param', 'web_switch_net_layer'
+ ),
+ // Constants from as_web.h
+ 8 => array(
+ 'ENDFORM', 'LAST', 'ENDITEM', 'EXTRARES', 'ITEMDATA', 'STARTHIDDENS', 'ENDHIDDENS', 'CONNECT', 'RECEIVE', 'RESOLVE',
+ 'STEP', 'REQUEST', 'RESPONSE', 'STARTQUERY', 'ENDQUERY', 'INPROPS', 'OUTPROPS', 'ENDPROPS', 'RAW_BODY_START',
+ 'RAW_BODY_END', 'HTTP_INFO_RETURN_CODE', 'HTTP_INFO_DOWNLOAD_SIZE', 'HTTP_INFO_DOWNLOAD_TIME',
+ 'LRW_NET_SOCKET_OPT_LOAD_VERIFY_FILE', 'LRW_NET_SOCKET_OPT_DEFAULT_VERIFY_PATH', 'LRW_NET_SOCKET_OPT_SSL_VERSION',
+ 'LRW_NET_SOCKET_OPT_SSL_CIPHER_LIST', 'LRW_NET_SOCKET_OPT_SO_REUSE_ADDRESS', 'LRW_NET_SOCKET_OPT_USER_IP_ADDRESS',
+ 'LRW_NET_SOCKET_OPT_IP_ADDRESS_BY_INDEX', 'LRW_NET_SOCKET_OPT_HELP', 'LRW_NET_SOCKET_OPT_PRINT_USER_IP_ADDRESS_LIST',
+ 'LRW_OPT_HTML_CHAR_REF_BACKWARD_COMPATIBILITY', 'LRW_OPT_VALUE_YES', 'LRW_OPT_VALUE_NO'
+ ),
+ // Functions from as_sapgui.h
+ 9 => array(
+ 'sapgui_open_connection', 'sapgui_open_connection_ex', 'sapgui_logon', 'sapgui_create_session',
+ 'sapgui_create_new_session', 'sapgui_call_method', 'sapgui_call_method_ex', 'sapgui_set_property',
+ 'sapgui_get_property', 'sapgui_set_collection_property', 'sapgui_active_object_from_parent_method',
+ 'sapgui_active_object_from_parent_property', 'sapgui_call_method_of_active_object',
+ 'sapgui_call_method_of_active_object_ex', 'sapgui_set_property_of_active_object', 'sapgui_get_property_of_active_object',
+ 'sapgui_select_active_connection', 'sapgui_select_active_session', 'sapgui_select_active_window ',
+ 'sapgui_status_bar_get_text', 'sapgui_status_bar_get_param', 'sapgui_status_bar_get_type', 'sapgui_get_status_bar_text',
+ 'sapgui_get_active_window_title', 'sapgui_is_object_available', 'sapgui_is_tab_selected', 'sapgui_is_object_changeable',
+ 'sapgui_set_ok_code', 'sapgui_send_vkey', 'sapgui_resize_window', 'sapgui_window_resize', 'sapgui_window_maximize',
+ 'sapgui_window_close', 'sapgui_window_restore', 'sapgui_window_scroll_to_row', 'sapgui_press_button',
+ 'sapgui_select_radio_button', 'sapgui_set_password', 'sapgui_set_text', 'sapgui_select_menu', 'sapgui_select_tab',
+ 'sapgui_set_checkbox', 'sapgui_set_focus', 'sapgui_select_combobox_entry', 'sapgui_get_ok_code',
+ 'sapgui_is_radio_button_selected', 'sapgui_get_text', 'sapgui_is_checkbox_selected', 'sapgui_table_set_focus',
+ 'sapgui_table_press_button', 'sapgui_table_select_radio_button', 'sapgui_table_set_password', 'sapgui_table_set_text',
+ 'sapgui_table_set_checkbox', 'sapgui_table_select_combobox_entry', 'sapgui_table_set_row_selected',
+ 'sapgui_table_set_column_selected', 'sapgui_table_set_column_width', 'sapgui_table_reorder', 'sapgui_table_fill_data',
+ 'sapgui_table_get_text', 'sapgui_table_is_radio_button_selected', 'sapgui_table_is_checkbox_selected',
+ 'sapgui_table_is_row_selected', 'sapgui_table_is_column_selected', 'sapgui_table_get_column_width',
+ 'sapgui_grid_clear_selection', 'sapgui_grid_select_all', 'sapgui_grid_selection_changed',
+ 'sapgui_grid_press_column_header', 'sapgui_grid_select_cell', 'sapgui_grid_select_rows', 'sapgui_grid_select_column',
+ 'sapgui_grid_deselect_column', 'sapgui_grid_select_columns', 'sapgui_grid_select_cells', 'sapgui_grid_select_cell_row',
+ 'sapgui_grid_select_cell_column', 'sapgui_grid_set_column_order', 'sapgui_grid_set_column_width',
+ 'sapgui_grid_scroll_to_row', 'sapgui_grid_double_click', 'sapgui_grid_click', 'sapgui_grid_press_button',
+ 'sapgui_grid_press_total_row', 'sapgui_grid_set_cell_data', 'sapgui_grid_set_checkbox',
+ 'sapgui_grid_double_click_current_cell', 'sapgui_grid_click_current_cell', 'sapgui_grid_press_button_current_cell',
+ 'sapgui_grid_press_total_row_current_cell', 'sapgui_grid_press_F1', 'sapgui_grid_press_F4', 'sapgui_grid_press_ENTER',
+ 'sapgui_grid_press_toolbar_button', 'sapgui_grid_press_toolbar_context_button', 'sapgui_grid_open_context_menu',
+ 'sapgui_grid_select_context_menu', 'sapgui_grid_select_toolbar_menu', 'sapgui_grid_fill_data',
+ 'sapgui_grid_get_current_cell_row', 'sapgui_grid_get_current_cell_column', 'sapgui_grid_get_rows_count',
+ 'sapgui_grid_get_columns_count', 'sapgui_grid_get_cell_data', 'sapgui_grid_is_checkbox_selected',
+ 'sapgui_tree_scroll_to_node', 'sapgui_tree_set_hierarchy_header_width', 'sapgui_tree_set_selected_node',
+ 'sapgui_tree_double_click_node', 'sapgui_tree_press_key', 'sapgui_tree_press_button', 'sapgui_tree_set_checkbox',
+ 'sapgui_tree_double_click_item', 'sapgui_tree_click_link', 'sapgui_tree_open_default_context_menu',
+ 'sapgui_tree_open_node_context_menu', 'sapgui_tree_open_header_context_menu', 'sapgui_tree_open_item_context_menu',
+ 'sapgui_tree_select_context_menu', 'sapgui_tree_select_item', 'sapgui_tree_select_node', 'sapgui_tree_unselect_node',
+ 'sapgui_tree_unselect_all', 'sapgui_tree_select_column', 'sapgui_tree_unselect_column', 'sapgui_tree_set_column_order',
+ 'sapgui_tree_collapse_node', 'sapgui_tree_expand_node', 'sapgui_tree_scroll_to_item', 'sapgui_tree_set_column_width',
+ 'sapgui_tree_press_header', 'sapgui_tree_is_checkbox_selected', 'sapgui_tree_get_node_text', 'sapgui_tree_get_item_text',
+ 'sapgui_calendar_scroll_to_date', 'sapgui_calendar_focus_date', 'sapgui_calendar_select_interval',
+ 'sapgui_apogrid_select_all', 'sapgui_apogrid_clear_selection', 'sapgui_apogrid_select_cell',
+ 'sapgui_apogrid_deselect_cell', 'sapgui_apogrid_select_row', 'sapgui_apogrid_deselect_row',
+ 'sapgui_apogrid_select_column', 'sapgui_apogrid_deselect_column', 'sapgui_apogrid_scroll_to_row',
+ 'sapgui_apogrid_scroll_to_column', 'sapgui_apogrid_double_click', 'sapgui_apogrid_set_cell_data',
+ 'sapgui_apogrid_get_cell_data', 'sapgui_apogrid_is_cell_changeable', 'sapgui_apogrid_get_cell_format',
+ 'sapgui_apogrid_get_cell_tooltip', 'sapgui_apogrid_press_ENTER', 'sapgui_apogrid_open_cell_context_menu',
+ 'sapgui_apogrid_select_context_menu_item', 'sapgui_text_edit_scroll_to_line', 'sapgui_text_edit_set_selection_indexes',
+ 'sapgui_text_edit_set_unprotected_text_part', 'sapgui_text_edit_get_first_visible_line',
+ 'sapgui_text_edit_get_selection_index_start', 'sapgui_text_edit_get_selection_index_end',
+ 'sapgui_text_edit_get_number_of_unprotected_text_parts', 'sapgui_text_edit_double_click',
+ 'sapgui_text_edit_single_file_dropped', 'sapgui_text_edit_multiple_files_dropped', 'sapgui_text_edit_press_F1',
+ 'sapgui_text_edit_press_F4', 'sapgui_text_edit_open_context_menu', 'sapgui_text_edit_select_context_menu',
+ 'sapgui_text_edit_modified_status_changed', 'sapgui_htmlviewer_send_event', 'sapgui_htmlviewer_dom_get_property',
+ 'sapgui_toolbar_press_button', 'sapgui_toolbar_press_context_button', 'sapgui_toolbar_select_menu_item',
+ 'sapgui_toolbar_select_menu_item_by_text', 'sapgui_toolbar_select_context_menu_item',
+ 'sapgui_toolbar_select_context_menu_item_by_text'
+ ),
+ // Constants from as_sapgui.h
+ 10 => array(
+ 'BEGIN_OPTIONAL', 'END_OPTIONAL', 'al-keys', 'ENTER', 'HELP', 'F2', 'BACK', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9',
+ 'F10', 'F11', 'ESC', 'SHIFT_F1', 'SHIFT_F2', 'SHIFT_F3', 'SHIFT_F4', 'SHIFT_F5', 'SHIFT_F6', 'SHIFT_F7', 'SHIFT_F8',
+ 'SHIFT_F9', 'SHIFT_F10', 'SHIFT_F11', 'SHIFT_F12', 'CTRL_F1', 'CTRL_F2', 'CTRL_F3', 'CTRL_F4', 'CTRL_F5', 'CTRL_F6',
+ 'CTRL_F7', 'CTRL_F8', 'CTRL_F9', 'CTRL_F10', 'CTRL_F11', 'CTRL_F12', 'CTRL_SHIFT_F1', 'CTRL_SHIFT_F2', 'CTRL_SHIFT_F3',
+ 'CTRL_SHIFT_F4', 'CTRL_SHIFT_F5', 'CTRL_SHIFT_F6', 'CTRL_SHIFT_F7', 'CTRL_SHIFT_F8', 'CTRL_SHIFT_F9', 'CTRL_SHIFT_F10',
+ 'CTRL_SHIFT_F11', 'CTRL_SHIFT_F12', 'CANCEL', 'CTRL_F', 'CTRL_PAGE_UP', 'PAGE_UP', 'PAGE_DOWN', 'CTRL_PAGE_DOWN',
+ 'CTRL_G', 'CTRL_P'
+ ),
+ ),
+
+ // Symbols and Case Sensitivity
+ // Symbols from: http://en.wikipedia.org/wiki/C_syntax
+ 'SYMBOLS' => array(
+ '(', ')', '{', '}', '[', ']',
+ '+', '-', '*', '/', '%',
+ '=', '<', '>', '!', '^', '&', '|', '?', ':', ';', ','
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true, // Standard C reserved keywords
+ 2 => true, // C preprocessor directives
+ 3 => true, // Functions from lrun.h
+ 4 => true, // Constants from lrun.h
+ 5 => true, // Functions from web_api.h
+ 6 => true, // Constants from web_api.h
+ 7 => true, // Functions from as_web.h
+ 8 => true, // Constants from as_web.h
+ 9 => true, // Functions from as_sapgui.h
+ 10 => true, // Constants from as_sapgui.h
+ ),
+
+ // Styles
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ // Functions are brown, constants and reserved words are blue
+ 1 => 'color: #0000ff;', // Standard C reserved keywords
+ 2 => 'color: #0000ff;', // C preprocessor directives
+ 3 => 'color: #8a0000;', // Functions from lrun.h
+ 4 => 'color: #0000ff;', // Constants from lrun.h
+ 5 => 'color: #8a0000;', // Functions from web_api.h
+ 6 => 'color: #0000ff;', // Constants from web_api.h
+ 7 => 'color: #8a0000;', // Functions from as_web.h
+ 8 => 'color: #0000ff;', // Constants from as_web.h
+ 9 => 'color: #8a0000;', // Functions from as_sapgui.h
+ 10 => 'color: #0000ff;', // Constants from as_sapgui.h
+ ),
+ 'COMMENTS' => array(
+ // Comments are grey
+ 1 => 'color: #9b9b9b;',
+ 'MULTI' => 'color: #9b9b9b;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ // GeSHi cannot define a separate style for ESCAPE_REGEXP. The style for ESCAPE_CHAR also applies to ESCAPE_REGEXP.
+ // This is used for LoadRunner {parameters}
+ // {parameters} are pink
+ 0 => 'color: #c000c0;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #000000;'
+ ),
+ 'STRINGS' => array(
+ // Strings are green
+ 0 => 'color: #008080;'
+ ),
+ 'NUMBERS' => array(
+ // Numbers are green
+ 0 => 'color: #008080;',
+ GESHI_NUMBER_BIN_PREFIX_0B => 'color: #008080;',
+ GESHI_NUMBER_OCT_PREFIX => 'color: #008080;',
+ GESHI_NUMBER_HEX_PREFIX => 'color: #008080;',
+ GESHI_NUMBER_FLT_SCI_SHORT => 'color:#008080;',
+ GESHI_NUMBER_FLT_SCI_ZERO => 'color:#008080;',
+ GESHI_NUMBER_FLT_NONSCI_F => 'color:#008080;',
+ GESHI_NUMBER_FLT_NONSCI => 'color:#008080;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #000000;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #000000;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+
+ // URLs for Functions
+ 'URLS' => array(
+ 1 => '', // Standard C reserved keywords
+ 2 => '', // C preprocessor directives
+ 3 => '', // Functions from lrun.h
+ 4 => '', // Constants from lrun.h
+ 5 => '', // Functions from web_api.h
+ 6 => '', // Constants from web_api.h
+ 7 => '', // Functions from as_web.h
+ 8 => '', // Constants from as_web.h
+ 9 => '', // Functions from as_sapgui.h
+ 10 => '', // Constants from as_sapgui.h
+ ),
+
+ // Object Orientation
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+
+ // Regular Expressions
+ // Note that REGEXPS are not applied within strings.
+ 'REGEXPS' => array(
+ ),
+
+ // Contextual Highlighting and Strict Mode
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+
+ // Tabs
+ // Note that if you are using <pre> tags for your code, then the browser chooses how many spaces your tabs will translate to.
+ 'TAB_WIDTH' => 4
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/c_mac.php b/plugins/wp-syntax/geshi/geshi/c_mac.php
index 3e735190..41c21ce5 100644
--- a/plugins/wp-syntax/geshi/geshi/c_mac.php
+++ b/plugins/wp-syntax/geshi/geshi/c_mac.php
@@ -4,7 +4,7 @@
* ---------
* Author: M. Uli Kusterer (witness.of.teachtext@gmx.net)
* Copyright: (c) 2004 M. Uli Kusterer, Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* C for Macs language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/caddcl.php b/plugins/wp-syntax/geshi/geshi/caddcl.php
index c09c84a7..8b8b2f24 100644
--- a/plugins/wp-syntax/geshi/geshi/caddcl.php
+++ b/plugins/wp-syntax/geshi/geshi/caddcl.php
@@ -4,7 +4,7 @@
* ----------
* Author: Roberto Rossi (rsoftware@altervista.org)
* Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/30
*
* CAD DCL (Dialog Control Language) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/cadlisp.php b/plugins/wp-syntax/geshi/geshi/cadlisp.php
index d56e5711..3fa7ead0 100644
--- a/plugins/wp-syntax/geshi/geshi/cadlisp.php
+++ b/plugins/wp-syntax/geshi/geshi/cadlisp.php
@@ -4,7 +4,7 @@
* -----------
* Author: Roberto Rossi (rsoftware@altervista.org)
* Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/blog)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/30
*
* AutoCAD/IntelliCAD Lisp language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/cfdg.php b/plugins/wp-syntax/geshi/geshi/cfdg.php
index 27ade0cf..e40963f0 100644
--- a/plugins/wp-syntax/geshi/geshi/cfdg.php
+++ b/plugins/wp-syntax/geshi/geshi/cfdg.php
@@ -4,7 +4,7 @@
* --------
* Author: John Horigan <john@glyphic.com>
* Copyright: (c) 2006 John Horigan http://www.ozonehouse.com/john/
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/03/11
*
* CFDG language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/cfm.php b/plugins/wp-syntax/geshi/geshi/cfm.php
index 80a7f72e..2d165bd6 100644
--- a/plugins/wp-syntax/geshi/geshi/cfm.php
+++ b/plugins/wp-syntax/geshi/geshi/cfm.php
@@ -4,7 +4,7 @@
* -------
* Author: Diego
* Copyright: (c) 2006 Diego
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/02/25
*
* ColdFusion language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/chaiscript.php b/plugins/wp-syntax/geshi/geshi/chaiscript.php
index a4dc4318..f9d0a868 100644
--- a/plugins/wp-syntax/geshi/geshi/chaiscript.php
+++ b/plugins/wp-syntax/geshi/geshi/chaiscript.php
@@ -6,7 +6,7 @@
* Copyright: (c) 2010 Jason Turner (lefticus@gmail.com),
* (c) 2009 Jonathan Turner,
* (c) 2004 Ben Keen (ben.keen@gmail.com), Benny Baumann (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/07/03
*
* ChaiScript language file for GeSHi.
@@ -52,7 +52,7 @@ $language_data = array (
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
- 'break', 'else', 'else if', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally',
+ 'break', 'else', 'elseif', 'eval', 'for', 'if', 'return', 'while', 'try', 'catch', 'finally',
),
2 => array(
'def', 'false', 'fun', 'true', 'var', 'attr',
diff --git a/plugins/wp-syntax/geshi/geshi/cil.php b/plugins/wp-syntax/geshi/geshi/cil.php
index 58bd42bc..9872e755 100644
--- a/plugins/wp-syntax/geshi/geshi/cil.php
+++ b/plugins/wp-syntax/geshi/geshi/cil.php
@@ -4,7 +4,7 @@
* --------
* Author: Marcus Griep (neoeinstein+GeSHi@gmail.com)
* Copyright: (c) 2007 Marcus Griep (http://www.xpdm.us)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/10/24
*
* CIL (Common Intermediate Language) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/clojure.php b/plugins/wp-syntax/geshi/geshi/clojure.php
index 4494fb2b..0ad4e4ad 100644
--- a/plugins/wp-syntax/geshi/geshi/clojure.php
+++ b/plugins/wp-syntax/geshi/geshi/clojure.php
@@ -4,7 +4,7 @@
* --------
* Author: Jess Johnson (jess@grok-code.com)
* Copyright: (c) 2009 Jess Johnson (http://grok-code.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/09/20
*
* Clojure language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/cmake.php b/plugins/wp-syntax/geshi/geshi/cmake.php
index 00143bf8..67277aa9 100644
--- a/plugins/wp-syntax/geshi/geshi/cmake.php
+++ b/plugins/wp-syntax/geshi/geshi/cmake.php
@@ -4,7 +4,7 @@
* -------
* Author: Daniel Nelson (danieln@eng.utah.edu)
* Copyright: (c) 2009 Daniel Nelson
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/04/06
*
* CMake language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/cobol.php b/plugins/wp-syntax/geshi/geshi/cobol.php
index 9263370a..b07be48a 100644
--- a/plugins/wp-syntax/geshi/geshi/cobol.php
+++ b/plugins/wp-syntax/geshi/geshi/cobol.php
@@ -4,7 +4,7 @@
* ----------
* Author: BenBE (BenBE@omorphia.org)
* Copyright: (c) 2007-2008 BenBE (http://www.omorphia.de/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/07/02
*
* COBOL language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/coffeescript.php b/plugins/wp-syntax/geshi/geshi/coffeescript.php
new file mode 100644
index 00000000..194aecd0
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/coffeescript.php
@@ -0,0 +1,146 @@
+<?php
+/*************************************************************************************
+ * coffeescript.php
+ * ----------
+ * Author: Trevor Burnham (trevorburnham@gmail.com)
+ * Copyright: (c) 2010 Trevor Burnham (http://iterative.ly)
+ * Release Version: 1.0.8.11
+ * Date Started: 2010/06/08
+ *
+ * CoffeeScript language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2010/06/08 (1.0.8.9)
+ * - First Release
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'CoffeeScript',
+ 'COMMENT_SINGLE' => array(1 => '#'),
+ 'COMMENT_MULTI' => array('###' => '###'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ //Longest quotemarks ALWAYS first
+ 'QUOTEMARKS' => array('"""', "'''", '"', "'"),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+
+ /*
+ ** Set 1: control keywords
+ */
+ 1 => array(
+ 'break', 'by', 'catch', 'continue', 'else', 'finally', 'for', 'in', 'of', 'if',
+ 'return', 'switch', 'then', 'throw', 'try', 'unless', 'when', 'while', 'until'
+ ),
+
+ /*
+ ** Set 2: logic keywords
+ */
+ 2 => array(
+ 'and', 'or', 'is', 'isnt', 'not'
+ ),
+
+ /*
+ ** Set 3: other keywords
+ */
+ 3 => array(
+ 'instanceof', 'new', 'delete', 'typeof',
+ 'class', 'super', 'this', 'extends'
+ ),
+
+ /*
+ ** Set 4: constants
+ */
+ 4 => array(
+ 'true', 'false', 'on', 'off', 'yes', 'no',
+ 'Infinity', 'NaN', 'undefined', 'null'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '[', ']', '{', '}', '*', '&', '|', '%', '!', ',', ';', '<', '>', '?', '`',
+ '+', '-', '*', '/', '->', '=>', '<<', '>>', '@', ':', '^'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #ff7700;font-weight:bold;',
+ 2 => 'color: #008000;',
+ 3 => 'color: #dc143c;',
+ 4 => 'color: #0000cd;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #808080; font-style: italic;',
+ 'MULTI' => 'color: #808080; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: black;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #483d8b;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #ff4500;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: black;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+ 'SCRIPT_DELIMITERS' => array(
+ 0 => array(
+ '<script type="text/coffeescript">' => '</script>'
+ )
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ 0 => true
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/cpp-qt.php b/plugins/wp-syntax/geshi/geshi/cpp-qt.php
index 07f0cf28..36626c90 100644
--- a/plugins/wp-syntax/geshi/geshi/cpp-qt.php
+++ b/plugins/wp-syntax/geshi/geshi/cpp-qt.php
@@ -4,10 +4,10 @@
* -------
* Author: Iulian M
* Copyright: (c) 2006 Iulian M
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/09/27
*
- * C++ (with QT extensions) language file for GeSHi.
+ * C++ (with Qt extensions) language file for GeSHi.
*
* CHANGES
* -------
@@ -41,7 +41,7 @@
************************************************************************************/
$language_data = array (
- 'LANG_NAME' => 'C++ (QT)',
+ 'LANG_NAME' => 'C++ (Qt)',
'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
'COMMENT_MULTI' => array('/*' => '*/'),
'COMMENT_REGEXP' => array(
@@ -55,7 +55,7 @@ $language_data = array (
'ESCAPE_CHAR' => '',
'ESCAPE_REGEXP' => array(
//Simple Single Char Escapes
- 1 => "#\\\\[\\\\abfnrtv\'\"?\n]#i",
+ 1 => "#\\\\[abfnrtv\\\'\"?\n]#i",
//Hexadecimal Char Specs
2 => "#\\\\x[\da-fA-F]{2}#",
//Hexadecimal Char Specs
diff --git a/plugins/wp-syntax/geshi/geshi/cpp.php b/plugins/wp-syntax/geshi/geshi/cpp.php
index 48b77269..42ab311c 100644
--- a/plugins/wp-syntax/geshi/geshi/cpp.php
+++ b/plugins/wp-syntax/geshi/geshi/cpp.php
@@ -7,7 +7,7 @@
* - M. Uli Kusterer (witness.of.teachtext@gmx.net)
* - Jack Lloyd (lloyd@randombit.net)
* Copyright: (c) 2004 Dennis Bayer, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/09/27
*
* C++ language file for GeSHi.
@@ -63,7 +63,7 @@ $language_data = array (
'ESCAPE_CHAR' => '',
'ESCAPE_REGEXP' => array(
//Simple Single Char Escapes
- 1 => "#\\\\[\\\\abfnrtv\'\"?\n]#i",
+ 1 => "#\\\\[abfnrtv\\\'\"?\n]#i",
//Hexadecimal Char Specs
2 => "#\\\\x[\da-fA-F]{2}#",
//Hexadecimal Char Specs
diff --git a/plugins/wp-syntax/geshi/geshi/csharp.php b/plugins/wp-syntax/geshi/geshi/csharp.php
index 1c7eea06..26024e91 100644
--- a/plugins/wp-syntax/geshi/geshi/csharp.php
+++ b/plugins/wp-syntax/geshi/geshi/csharp.php
@@ -5,13 +5,15 @@
* Author: Alan Juden (alan@judenware.org)
* Revised by: Michael Mol (mikemol@gmail.com)
* Copyright: (c) 2004 Alan Juden, Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* C# language file for GeSHi.
*
* CHANGES
* -------
+ * 2012/06/18 (1.0.8.11)
+ * - Added missing keywords (Christian Stelzmann)
* 2009/04/03 (1.0.8.6)
* - Added missing keywords identified by Rosetta Code users.
* 2008/05/25 (1.0.7.22)
@@ -60,14 +62,15 @@ $language_data = array (
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
- 'as', 'auto', 'base', 'break', 'case', 'catch', 'const', 'continue',
+ 'abstract', 'add', 'as', 'base', 'break', 'by', 'case', 'catch', 'const', 'continue',
'default', 'do', 'else', 'event', 'explicit', 'extern', 'false',
- 'finally', 'fixed', 'for', 'foreach', 'from', 'goto', 'if',
- 'implicit', 'in', 'internal', 'lock', 'namespace', 'null',
+ 'finally', 'fixed', 'for', 'foreach', 'from', 'get', 'goto', 'group', 'if',
+ 'implicit', 'in', 'into', 'internal', 'join', 'lock', 'namespace', 'null',
'operator', 'out', 'override', 'params', 'partial', 'private',
- 'protected', 'public', 'readonly', 'ref', 'return', 'sealed',
- 'select', 'stackalloc', 'static', 'switch', 'this', 'throw', 'true',
- 'try', 'unsafe', 'using', 'virtual', 'where', 'while', 'yield'
+ 'protected', 'public', 'readonly', 'remove', 'ref', 'return', 'sealed',
+ 'select', 'set', 'stackalloc', 'static', 'switch', 'this', 'throw', 'true',
+ 'try', 'unsafe', 'using', 'var', 'value', 'virtual', 'volatile', 'where',
+ 'while', 'yield'
),
2 => array(
'#elif', '#endif', '#endregion', '#else', '#error', '#define', '#if',
@@ -78,7 +81,7 @@ $language_data = array (
),
4 => array(
'bool', 'byte', 'char', 'class', 'decimal', 'delegate', 'double',
- 'enum', 'float', 'int', 'interface', 'long', 'object', 'sbyte',
+ 'dynamic', 'enum', 'float', 'int', 'interface', 'long', 'object', 'sbyte',
'short', 'string', 'struct', 'uint', 'ulong', 'ushort', 'void'
),
5 => array(
diff --git a/plugins/wp-syntax/geshi/geshi/css.php b/plugins/wp-syntax/geshi/geshi/css.php
index 2cb3f342..d09bea7d 100644
--- a/plugins/wp-syntax/geshi/geshi/css.php
+++ b/plugins/wp-syntax/geshi/geshi/css.php
@@ -4,7 +4,7 @@
* -------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/18
*
* CSS language file for GeSHi.
@@ -58,12 +58,22 @@ $language_data = array (
),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"', "'"),
- 'ESCAPE_CHAR' => '\\',
+ 'ESCAPE_CHAR' => '',
+ 'ESCAPE_REGEXP' => array(
+ //Simple Single Char Escapes
+ //1 => "#\\\\[nfrtv\$\"\n\\\\]#i",
+ //Hexadecimal Char Specs
+ 2 => "#\\\\[\da-fA-F]{1,6}\s?#i",
+ //Unicode Char Specs
+ //3 => "#\\\\u[\da-fA-F]{1,8}#i",
+ ),
'KEYWORDS' => array(
1 => array(
'aqua', 'azimuth', 'background-attachment', 'background-color',
'background-image', 'background-position', 'background-repeat',
'background', 'black', 'blue', 'border-bottom-color',
+ 'border-radius', 'border-top-left-radius', 'border-top-right-radius',
+ 'border-bottom-right-radius', 'border-bottom-left-radius',
'border-bottom-style', 'border-bottom-width', 'border-left-color',
'border-left-style', 'border-left-width', 'border-right',
'border-right-color', 'border-right-style', 'border-right-width',
@@ -153,7 +163,10 @@ $language_data = array (
'MULTI' => 'color: #808080; font-style: italic;'
),
'ESCAPE_CHAR' => array(
- 0 => 'color: #000099; font-weight: bold;'
+ 0 => 'color: #000099; font-weight: bold;',
+ //1 => 'color: #000099; font-weight: bold;',
+ 2 => 'color: #000099; font-weight: bold;'
+ //3 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #00AA00;'
@@ -204,7 +217,8 @@ $language_data = array (
'TAB_WIDTH' => 4,
'PARSER_CONTROL' => array(
'KEYWORDS' => array(
- 'DISALLOWED_AFTER' => '(?![a-zA-Z0-9_\|%\\-&\.])'
+ 'DISALLOWED_AFTER' => '(?![\-a-zA-Z0-9_\|%\\-&\.])',
+ 'DISALLOWED_BEFORE' => '(?<![\-a-zA-Z0-9_\|%\\~&\.])'
)
)
);
diff --git a/plugins/wp-syntax/geshi/geshi/cuesheet.php b/plugins/wp-syntax/geshi/geshi/cuesheet.php
index 2820b047..ebaca955 100644
--- a/plugins/wp-syntax/geshi/geshi/cuesheet.php
+++ b/plugins/wp-syntax/geshi/geshi/cuesheet.php
@@ -4,7 +4,7 @@
* ----------
* Author: Benny Baumann (benbe@geshi.org)
* Copyright: (c) 2009 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/12/21
*
* Cuesheet language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/d.php b/plugins/wp-syntax/geshi/geshi/d.php
index af0468ae..7f3e9857 100644
--- a/plugins/wp-syntax/geshi/geshi/d.php
+++ b/plugins/wp-syntax/geshi/geshi/d.php
@@ -3,14 +3,18 @@
* d.php
* -----
* Author: Thomas Kuehne (thomas@kuehne.cn)
+ * Contributors:
+ * - Jimmy Cao
* Copyright: (c) 2005 Thomas Kuehne (http://thomas.kuehne.cn/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/04/22
*
* D language file for GeSHi.
*
* CHANGES
* -------
+ * 2011/06/28 (0.0.3) (Jimmy Cao)
+ * - added D2 features
* 2005/04/22 (0.0.2)
* - added _d_* and sizeof/ptrdiff_t
* 2005/04/20 (0.0.1)
@@ -45,7 +49,7 @@
$language_data = array (
'LANG_NAME' => 'D',
'COMMENT_SINGLE' => array(2 => '///', 1 => '//'),
- 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_MULTI' => array('/*' => '*/', '/+' => '+/'),
'COMMENT_REGEXP' => array(
// doxygen comments
3 => '#/\*\*(?![\*\/]).*\*/#sU',
@@ -126,63 +130,39 @@ $language_data = array (
1 => array(
'break', 'case', 'continue', 'do', 'else',
'for', 'foreach', 'goto', 'if', 'return',
- 'switch', 'while'
+ 'switch', 'while', 'foreach_reverse'
),
2 => array(
'alias', 'asm', 'assert', 'body', 'cast',
'catch', 'default', 'delegate', 'delete',
'extern', 'false', 'finally', 'function',
- 'import', 'in', 'inout', 'interface',
- 'invariant', 'is', 'mixin', 'module', 'new',
+ 'import', 'in', 'inout',
+ 'invariant', 'is', 'lazy', 'mixin', 'module', 'new',
'null', 'out', 'pragma', 'ref', 'super', 'this',
- 'throw', 'true', 'try', 'typedef', 'typeid',
- 'typeof', 'union', 'with'
+ 'throw', 'true', 'try', 'typeid',
+ 'typeof', 'union', 'with', 'scope'
),
3 => array(
- 'ArrayBoundsError', 'AssertError',
'ClassInfo', 'Error', 'Exception',
- 'Interface', 'ModuleInfo', 'Object',
- 'OutOfMemoryException', 'SwitchError',
- 'TypeInfo', '_d_arrayappend',
- '_d_arrayappendb', '_d_arrayappendc',
- '_d_arrayappendcb', '_d_arraycast',
- '_d_arraycast_frombit', '_d_arraycat',
- '_d_arraycatb', '_d_arraycatn',
- '_d_arraycopy', '_d_arraycopybit',
- '_d_arraysetbit', '_d_arraysetbit2',
- '_d_arraysetlength', '_d_arraysetlengthb',
- '_d_callfinalizer',
- '_d_create_exception_object',
- '_d_criticalenter', '_d_criticalexit',
- '_d_delarray', '_d_delclass',
- '_d_delinterface', '_d_delmemory',
- '_d_dynamic_cast', '_d_exception',
- '_d_exception_filter', '_d_framehandler',
- '_d_interface_cast', '_d_interface_vtbl',
- '_d_invariant', '_d_isbaseof',
- '_d_isbaseof2', '_d_local_unwind',
- '_d_monitorenter', '_d_monitorexit',
- '_d_monitorrelease', '_d_monitor_epilog',
- '_d_monitor_handler', '_d_monitor_prolog',
- '_d_new', '_d_newarrayi', '_d_newbitarray',
- '_d_newclass', '_d_obj_cmp', '_d_obj_eq',
- '_d_OutOfMemory', '_d_switch_dstring',
- '_d_switch_string', '_d_switch_ustring',
- '_d_throw',
+ 'Interface', 'Object', 'IMonitor',
+ 'OffsetTypeInfo', 'Throwable',
+ 'TypeInfo_Class', 'TypeInfo', '__traits',
+ '__EOF__', '__FILE__', '__LINE__',
),
4 => array(
'abstract', 'align', 'auto', 'bit', 'bool',
- 'byte', 'cdouble', 'cent', 'cfloat', 'char',
- 'class', 'const', 'creal', 'dchar', 'debug',
+ 'byte', 'cdouble', 'cfloat', 'char',
+ 'class', 'const', 'creal', 'dchar', 'dstring', 'debug',
'deprecated', 'double', 'enum', 'export',
- 'final', 'float', 'idouble', 'ifloat', 'int',
- 'ireal', 'long', 'override', 'package',
- 'private', 'protected', 'ptrdiff_t',
- 'public', 'real', 'short', 'size_t',
- 'static', 'struct', 'synchronized',
+ 'final', 'float', 'idouble', 'ifloat', 'immutable', 'int',
+ 'interface', 'ireal', 'long', 'nothrow', 'override',
+ 'package', 'private', 'protected', 'ptrdiff_t',
+ 'public', 'real', 'short', 'shared', 'size_t',
+ 'static', 'string', 'struct', 'synchronized',
'template', 'ubyte', 'ucent', 'uint',
'ulong', 'unittest', 'ushort', 'version',
- 'void', 'volatile', 'wchar'
+ 'void', 'volatile', 'wchar', 'wstring',
+ '__gshared', '@disable', '@property', 'pure', 'safe'
)
),
'SYMBOLS' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/dcl.php b/plugins/wp-syntax/geshi/geshi/dcl.php
new file mode 100644
index 00000000..db12a4c4
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/dcl.php
@@ -0,0 +1,192 @@
+<?php
+/*************************************************************************************
+ * dcl.php
+ * --------
+ * Author: Petr Hendl (petr@hendl.cz)
+ * Copyright: (c) 2011 Petr Hendl http://hendl.cz/geshi/
+ * Release Version: 1.0.8.11
+ * Date Started: 2011/02/17
+ *
+ * DCL language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2011-02-17 (1.0.8.11)
+ * - First Release
+ *
+ * TODO
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'DCL',
+ 'COMMENT_SINGLE' => array('$!', '!'),
+ 'COMMENT_MULTI' => array(),
+ 'COMMENT_REGEXP' => array(
+ 2 => '/(?<=\$)\s*sql\s+.*?(?:quit|exit);?\s*?$/sim' // do not highlight inline sql
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"'),
+ 'HARDESCAPE' => array(),
+ 'ESCAPE_CHAR' => '',
+ 'ESCAPE_REGEXP' => array(
+ 1 => "/''[a-zA-Z\\-_]+'/"
+ ),
+ 'KEYWORDS' => array(
+ 1 => array( // commands
+ 'ACCOUNTING', 'ALLOCATE', 'ANALYZE', 'APPEND', 'ASSIGN', 'ATTACH', 'BACKUP',
+ 'CALL', 'CANCEL', 'CHECKSUM', 'CLOSE', 'CONNECT', 'CONTINUE', 'CONVERT',
+ 'COPY', 'CREATE', 'DEALLOCATE', 'DEASSIGN', 'DEBUG', 'DECK',
+ 'DECRYPT', 'DEFINE', 'DELETE', 'DEPOSIT', 'DIFFERENCES', 'DIRECTORY',
+ 'DISABLE', 'AUTOSTART', 'DISCONNECT', 'DISMOUNT', 'DUMP', 'EDIT', 'ENABLE',
+ 'ENCRYPT', 'ENDSUBROUTINE', 'EOD', 'EOJ', 'EXAMINE', 'EXCHANGE',
+ 'EXIT', 'FONT', 'GOSUB', 'GOTO', 'HELP', 'IF', 'THEN', 'ELSE', 'ENDIF', 'INITIALIZE', 'INQUIRE',
+ 'INSTALL', 'JAVA', 'JOB', 'LIBRARY', 'LICENSE', 'LINK', 'LOGIN', 'LOGOUT',
+ 'MACRO', 'MAIL', 'MERGE', 'MESSAGE', 'MONITOR', 'MOUNT', 'NCS', 'ON', 'OPEN',
+ 'PASSWORD', 'PATCH', 'PHONE', 'PIPE', 'PPPD', 'PRINT', 'PRODUCT', 'PURGE',
+ 'READ', 'RECALL', 'RENAME', 'REPLY', 'REQUEST', 'RETURN', 'RMU', 'RUN', 'RUNOFF',
+ 'SEARCH', 'SET', 'SET AUDIT', 'SET BOOTBLOCK', 'SET BROADCAST',
+ 'SET CACHE', 'SET CARD_READER', 'SET CLUSTER', 'SET COMMAND', 'SET CONTROL',
+ 'SET CPU', 'SET DAY', 'SET DEFAULT', 'SET DEVICE', 'SET DIRECTORY',
+ 'SET DISPLAY', 'SET ENTRY', 'SET FILE', 'SET HOST', 'SET IMAGE', 'SET KEY',
+ 'SET LOGINS', 'SET MAGTAPE', 'SET MESSAGE', 'SET NETWORK', 'SET ON', 'SET OUTPUT_RATE',
+ 'SET PASSWORD', 'SET PREFERRED_PATH', 'SET PREFIX', 'SET PRINTER', 'SET PROCESS',
+ 'SET PROMPT', 'SET PROTECTION', 'SET QUEUE', 'SET RESTART_VALUE',
+ 'SET RIGHTS_LIST', 'SET RMS_DEFAULT', 'SET ROOT', 'SET SECURITY',
+ 'SET SERVER ACME_SERVER', 'SET SERVER REGISTRY_SERVER', 'SET SERVER SECURITY_SERVER',
+ 'SET SHADOW', 'SET SYMBOL', 'SET TERMINAL', 'SET TIME', 'SET VERIFY',
+ 'SET VOLUME', 'SET WORKING_SET', 'SHOW', 'SHOW AUDIT',
+ 'SHOW BROADCAST', 'SHOW CLUSTER', 'SHOW CPU', 'SHOW DEFAULT', 'SHOW DEVICES',
+ 'SHOW DISPLAY', 'SHOW ENTRY', 'SHOW ERROR', 'SHOW FASTPATH', 'SHOW IMAGE',
+ 'SHOW INTRUSION', 'SHOW KEY', 'SHOW LICENSE', 'SHOW LOGICAL', 'SHOW MEMORY',
+ 'SHOW NETWORK', 'SHOW PRINTER', 'SHOW PROCESS', 'SHOW PROTECTION', 'SHOW QUEUE',
+ 'SHOW QUOTA', 'SHOW RMS_DEFAULT', 'SHOW ROOT', 'SHOW SECURITY',
+ 'SHOW SERVER ACME_SERVER', 'SHOW SERVER REGISTRY_SERVER', 'SHOW SHADOW',
+ 'SHOW STATUS', 'SHOW SYMBOL', 'SHOW SYSTEM', 'SHOW TERMINAL', 'SHOW TIME',
+ 'SHOW TRANSLATION', 'SHOW USERS', 'SHOW WORKING_SET', 'SHOW ZONE', 'SORT',
+ 'SPAWN', 'START', 'STOP', 'SUBMIT', 'SUBROUTINE', 'SYNCHRONIZE', 'TYPE',
+ 'UNLOCK', 'VIEW', 'WAIT', 'WRITE', 'XAUTH'
+ ),
+ 2 => array( // lexical functions
+ 'F$CONTEXT', 'F$CSID', 'F$CUNITS', 'F$CVSI', 'F$CVTIME', 'F$CVUI',
+ 'F$DELTA_TIME', 'F$DEVICE', 'F$DIRECTORY', 'F$EDIT', 'F$ELEMENT',
+ 'F$ENVIRONMENT', 'F$EXTRACT', 'F$FAO', 'F$FID_TO_NAME', 'F$FILE_ATTRIBUTES',
+ 'F$GETDVI', 'F$GETENV', 'F$GETJPI', 'F$GETQUI', 'F$GETSYI', 'F$IDENTIFIER',
+ 'F$INTEGER', 'F$LENGTH', 'F$LICENSE', 'F$LOCATE', 'F$MATCH_WILD', 'F$MESSAGE',
+ 'F$MODE', 'F$MULTIPATH', 'F$PARSE', 'F$PID', 'F$PRIVILEGE', 'F$PROCESS',
+ 'F$SEARCH', 'F$SETPRV', 'F$STRING', 'F$TIME', 'F$TRNLNM', 'F$TYPE', 'F$UNIQUE',
+ 'F$USER', 'F$VERIFY'
+ ),
+ 3 => array( // special variables etc
+ 'sql$database', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6', 'P7', 'P8', 'P9',
+ '$status', '$severity', 'sys$login', 'sys$system',
+ 'sys$input', 'sys$output', 'sys$pipe'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '[', ']', '@', '&', '|', '<', '>', '-',
+ '.eqs.', '.eq.', '.lt.', '.lts.', '.gt.', '.gts.', '.ne.', '.nes.',
+ '.le.', '.ge.', '.ges.', '.les.',
+ '.EQS.', '.EQ.', '.LT.', '.LTS.', '.GT.', '.GTS.', '.NE.', '.NES.',
+ '.LE.', '.GE.', '.GES.', '.LES.',
+ '.and.', '.or.', '.not.',
+ '.AND.', '.OR.', '.NOT.',
+ '==', ':==', '=', ':='
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #000099; font-weight: bold;',
+ 2 => 'color: #0066FF;',
+ 3 => 'color: #993300;'
+ ),
+ 'COMMENTS' => array(
+ 0 => 'color: #666666; font-style: italic;',
+ 1 => 'color: #666666; font-style: italic;',
+ 2 => 'color: #9999FF; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #006666;',
+ 1 => 'color: #0099FF;',
+ 2 => 'color: red;',
+ 3 => 'color: #007800;',
+ 4 => 'color: #007800;',
+ 5 => 'color: #780078;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #7a0874; font-weight: bold;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #009900;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #000000;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #000000; font-weight: bold;'
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color: #0099FF;', // variables
+ 1 => 'color: #0000FF;', // qualifiers
+ 2 => 'color: #FF6600; font-weight: bold;' // labels
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ // variables
+ 0 => "'[a-zA-Z_\\-$]+'",
+ // qualifiers and parameters
+ 1 => "(?:\/[a-zA-Z_\/]+)[\s=]",
+ // labels
+ 2 => '(?<=\$)\s*[a-zA-Z\-_]+:'
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4,
+ 'PARSER_CONTROL' => array(
+ 'COMMENTS' => array(
+ ),
+ 'KEYWORDS' => array(
+ )
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/dcpu16.php b/plugins/wp-syntax/geshi/geshi/dcpu16.php
new file mode 100644
index 00000000..5fcb25e5
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/dcpu16.php
@@ -0,0 +1,131 @@
+<?php
+/*************************************************************************************
+ * dcpu16.php
+ * -------
+ * Author: Benny Baumann (BenBE@omorphia.de)
+ * Copyright: (c) 2007-2012 Benny Baumann (http://geshi.org/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2012/04/12
+ *
+ * DCPU/16 Assembly language file for GeSHi.
+ * Syntax definition based on http://0x10c.com/doc/dcpu-16.txt
+ *
+ * CHANGES
+ * -------
+ * 2012/04/12 (1.0.0)
+ * - First Release
+ *
+ * TODO (updated 2012/04/12)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'DCPU-16 Assembly',
+ 'COMMENT_SINGLE' => array(1 => ';'),
+ 'COMMENT_MULTI' => array(),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ 'NUMBERS' => GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_HEX_PREFIX,
+ 'KEYWORDS' => array(
+ /*CPU*/
+ 1 => array(
+ 'set','add','sub','mul','div','mod','shl','shr','and','bor','xor',
+ 'ife','ifn','ifg','ifb',
+ 'jsr'
+ ),
+ /*registers*/
+ 2 => array(
+ 'a','b','c','x','y','z','i','j',
+ 'pc','sp','o',
+ 'pop','peek','push' //Special cases with DCPU-16
+ ),
+ ),
+ 'SYMBOLS' => array(
+ '[', ']', '+', '-', ','
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #000088; font-weight:bold;',
+ 2 => 'color: #0000ff;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #adadad; font-style: italic;',
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #000088;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #7f007f;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #880000;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #008000;'
+ ),
+ 'REGEXPS' => array(
+ 2 => 'color: #993333;'
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => 'http://0x10c.com/doc/dcpu-16.txt',
+ 2 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ //Hex numbers
+ //0 => '0[0-9a-fA-F]{1,32}[hH]',
+ //Binary numbers
+ //1 => '\%[01]{1,64}|[01]{1,64}[bB]?(?![^<]*>)',
+ //Labels
+ 2 => '^:[_a-zA-Z][_a-zA-Z0-9]?(?=\s|$)'
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4,
+ 'PARSER_CONTROL' => array(
+ 'KEYWORDS' => array(
+ 'DISALLOWED_BEFORE' => "(?<![a-zA-Z0-9\$_\|\#\/])",
+ 'DISALLOWED_AFTER' => "(?![a-zA-Z0-9_\|%\\-])"
+ )
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/dcs.php b/plugins/wp-syntax/geshi/geshi/dcs.php
index 05f2d31f..d32cfc5b 100644
--- a/plugins/wp-syntax/geshi/geshi/dcs.php
+++ b/plugins/wp-syntax/geshi/geshi/dcs.php
@@ -4,7 +4,7 @@
* ---------------------------------
* Author: Stelio Passaris (GeSHi@stelio.net)
* Copyright: (c) 2009 Stelio Passaris (http://stelio.net/stiki/GeSHi)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/01/20
*
* DCS language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/delphi.php b/plugins/wp-syntax/geshi/geshi/delphi.php
index 1c252e3f..d5596e0c 100644
--- a/plugins/wp-syntax/geshi/geshi/delphi.php
+++ b/plugins/wp-syntax/geshi/geshi/delphi.php
@@ -4,13 +4,17 @@
* ----------
* Author: J�rja Norbert (jnorbi@vipmail.hu), Benny Baumann (BenBE@omorphia.de)
* Copyright: (c) 2004 J�rja Norbert, Benny Baumann (BenBE@omorphia.de), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/26
*
* Delphi (Object Pascal) language file for GeSHi.
*
* CHANGES
* -------
+ * 2012/06/27 (1.0.8.11)
+ * - Added some keywords
+ * - fixed hex numbers and hex char literals (including WideChar)
+ * - Added support for FPC-Style generics
* 2008/05/23 (1.0.7.22)
* - Added description of extra language features (SF#1970248)
* 2005/11/19 (1.0.3)
@@ -51,27 +55,28 @@ $language_data = array (
'COMMENT_MULTI' => array('(*' => '*)', '{' => '}'),
//Compiler directives
'COMMENT_REGEXP' => array(2 => '/\\{\\$.*?}|\\(\\*\\$.*?\\*\\)/U'),
- 'CASE_KEYWORDS' => 0,
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'"),
'ESCAPE_CHAR' => '',
+
'KEYWORDS' => array(
1 => array(
'Abstract', 'And', 'Array', 'As', 'Asm', 'At', 'Begin', 'Case',
- 'Class', 'Const', 'Constructor', 'Contains', 'Destructor',
+ 'Class', 'Const', 'Constructor', 'Contains', 'Default', 'delayed', 'Destructor',
'DispInterface', 'Div', 'Do', 'DownTo', 'Else', 'End', 'Except',
- 'Export', 'Exports', 'External', 'File', 'Finalization', 'Finally',
- 'For', 'Function', 'Goto', 'If', 'Implementation', 'In', 'Inherited',
- 'Initialization', 'Inline', 'Interface', 'Is', 'Label', 'Library',
- 'Mod', 'Not', 'Object', 'Of', 'On', 'Or', 'Overload', 'Override',
+ 'Export', 'Exports', 'External', 'File', 'Finalization', 'Finally', 'For',
+ 'Function', 'Generic', 'Goto', 'If', 'Implementation', 'In', 'Inherited',
+ 'Initialization', 'Inline', 'Interface', 'Is', 'Label', 'Library', 'Message',
+ 'Mod', 'Nil', 'Not', 'Object', 'Of', 'On', 'Or', 'Overload', 'Override',
'Package', 'Packed', 'Private', 'Procedure', 'Program', 'Property',
- 'Protected', 'Public', 'Published', 'Raise', 'Record', 'Register',
- 'Repeat', 'Requires', 'Resourcestring', 'Set', 'Shl', 'Shr', 'Then',
- 'ThreadVar', 'To', 'Try', 'Type', 'Unit', 'Until', 'Uses', 'Var',
- 'Virtual', 'While', 'With', 'Xor', 'assembler', 'far',
+ 'Protected', 'Public', 'Published', 'Read', 'Raise', 'Record', 'Register',
+ 'Repeat', 'Requires', 'Resourcestring', 'Set', 'Shl', 'Shr', 'Specialize', 'Stored',
+ 'Then', 'ThreadVar', 'To', 'Try', 'Type', 'Unit', 'Until', 'Uses', 'Var',
+ 'Virtual', 'While', 'With', 'Write', 'Xor', 'assembler', 'far',
'near', 'pascal', 'cdecl', 'safecall', 'stdcall', 'varargs'
),
2 => array(
- 'nil', 'false', 'self', 'true', 'var', 'type', 'const'
+ 'false', 'self', 'true',
),
3 => array(
'Abs', 'AcquireExceptionObject', 'Addr', 'AnsiToUtf8', 'Append', 'ArcTan',
@@ -250,7 +255,7 @@ $language_data = array (
1 => 'color: #006600;'
),
'REGEXPS' => array(
- 0 => 'color: #9ac;',
+ 0 => 'color: #0000cc;',
1 => 'color: #ff0000;'
),
'SYMBOLS' => array(
@@ -274,16 +279,23 @@ $language_data = array (
),
'REGEXPS' => array(
//Hex numbers
- 0 => '\$[0-9a-fA-F]+',
+ 0 => '(?<!\#)\$[0-9a-fA-F]+(?!\w)',
//Characters
- 1 => '\#(?:\$[0-9a-fA-F]{1,2}|\d{1,3})'
+ 1 => '\#(?:\$[0-9a-fA-F]{1,4}|\d{1,5})'
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
),
- 'TAB_WIDTH' => 2
+ 'TAB_WIDTH' => 2,
+ 'PARSER_CONTROL' => array(
+ 'KEYWORDS' => array(
+ 3 => array(
+ 'DISALLOWED_AFTER' => '(?=\s*[(;])'
+ )
+ )
+ )
);
-?> \ No newline at end of file
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/diff.php b/plugins/wp-syntax/geshi/geshi/diff.php
index bcf0c1d5..5b681717 100644
--- a/plugins/wp-syntax/geshi/geshi/diff.php
+++ b/plugins/wp-syntax/geshi/geshi/diff.php
@@ -4,7 +4,7 @@
* --------
* Author: Conny Brunnkvist (conny@fuchsia.se), W. Tasin (tasin@fhm.edu)
* Copyright: (c) 2004 Fuchsia Open Source Solutions (http://www.fuchsia.se/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/12/29
*
* Diff-output language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/div.php b/plugins/wp-syntax/geshi/geshi/div.php
index 2bfa24df..aa11795a 100644
--- a/plugins/wp-syntax/geshi/geshi/div.php
+++ b/plugins/wp-syntax/geshi/geshi/div.php
@@ -4,7 +4,7 @@
* ---------------------------------
* Author: Gabriel Lorenzo (ermakina@gmail.com)
* Copyright: (c) 2005 Gabriel Lorenzo (http://ermakina.gazpachito.net)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/06/19
*
* DIV language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/dos.php b/plugins/wp-syntax/geshi/geshi/dos.php
index 75fee1ca..36d99836 100644
--- a/plugins/wp-syntax/geshi/geshi/dos.php
+++ b/plugins/wp-syntax/geshi/geshi/dos.php
@@ -4,7 +4,7 @@
* -------
* Author: Alessandro Staltari (staltari@geocities.com)
* Copyright: (c) 2005 Alessandro Staltari (http://www.geocities.com/SiliconValley/Vista/8155/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/07/05
*
* DOS language file for GeSHi.
@@ -171,7 +171,7 @@ $language_data = array (
/* Variable assignement */
1 => array(
/* GESHI_SEARCH => '(SET[\s]+(?si:\/A[\s]+|\/P[\s]+|))([^=\s\n]+)([\s]*=)',*/
- GESHI_SEARCH => '(SET[\s]+(?si:\/A[\s]+|\/P[\s]+|))([^=\n]+)([\s]*=)',
+ GESHI_SEARCH => '(SET\s+(?si:\\/A\s+|\\/P\s+)?)([^=\n]+)(\s*=)',
GESHI_REPLACE => '\\2',
GESHI_MODIFIERS => 'si',
GESHI_BEFORE => '\\1',
@@ -180,7 +180,7 @@ $language_data = array (
/* Arguments or variable evaluation */
2 => array(
/* GESHI_SEARCH => '(%)([\d*]|[^%\s]*(?=%))((?<!%\d)%|)',*/
- GESHI_SEARCH => '(%(?:%(?=[a-z0-9]))?)([\d*]|(?:~[adfnpstxz]*(?:$\w+:)?)?[a-z0-9](?!\w)|[^%\n]*(?=%))((?<!%\d)%|)',
+ GESHI_SEARCH => '(!(?:!(?=[a-z0-9]))?)([\d*]|(?:~[adfnpstxz]*(?:$\w+:)?)?[a-z0-9](?!\w)|[^!>\n]*(?=!))((?<!%\d)%|)(?!!>)',
GESHI_REPLACE => '\\2',
GESHI_MODIFIERS => 'si',
GESHI_BEFORE => '\\1',
@@ -189,7 +189,7 @@ $language_data = array (
/* Arguments or variable evaluation */
3 => array(
/* GESHI_SEARCH => '(%)([\d*]|[^%\s]*(?=%))((?<!%\d)%|)',*/
- GESHI_SEARCH => '(!(?:!(?=[a-z0-9]))?)([\d*]|(?:~[adfnpstxz]*(?:$\w+:)?)?[a-z0-9](?!\w)|[^!>\n]*(?=!))((?<!%\d)%|)(?!!>)',
+ GESHI_SEARCH => '(%(?:%(?=[a-z0-9]))?)([\d*]|(?:~[adfnpstxz]*(?:$\w+:)?)?[a-z0-9](?!\w)|[^%\n]*(?=%))((?<!%\d)%|)',
GESHI_REPLACE => '\\2',
GESHI_MODIFIERS => 'si',
GESHI_BEFORE => '\\1',
diff --git a/plugins/wp-syntax/geshi/geshi/dot.php b/plugins/wp-syntax/geshi/geshi/dot.php
index 698cf13c..bdf240a1 100644
--- a/plugins/wp-syntax/geshi/geshi/dot.php
+++ b/plugins/wp-syntax/geshi/geshi/dot.php
@@ -4,7 +4,7 @@
* ---------------------------------
* Author: Adrien Friggeri (adrien@friggeri.net)
* Copyright: (c) 2007 Adrien Friggeri (http://www.friggeri.net)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/05/30
*
* dot language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/e.php b/plugins/wp-syntax/geshi/geshi/e.php
index fb80fca4..319bee01 100644
--- a/plugins/wp-syntax/geshi/geshi/e.php
+++ b/plugins/wp-syntax/geshi/geshi/e.php
@@ -4,7 +4,7 @@
* --------
* Author: Kevin Reid (kpreid@switchb.org)
* Copyright: (c) 2010 Kevin Reid (http://switchb.org/kpreid/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/04/16
*
* E language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/ecmascript.php b/plugins/wp-syntax/geshi/geshi/ecmascript.php
index 2d3f09fa..69a55c9a 100644
--- a/plugins/wp-syntax/geshi/geshi/ecmascript.php
+++ b/plugins/wp-syntax/geshi/geshi/ecmascript.php
@@ -4,7 +4,7 @@
* --------------
* Author: Michel Mariani (http://www.tonton-pixel.com/site/)
* Copyright: (c) 2010 Michel Mariani (http://www.tonton-pixel.com/site/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/01/08
*
* ECMAScript language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/eiffel.php b/plugins/wp-syntax/geshi/geshi/eiffel.php
index 57e00b99..baa13c31 100644
--- a/plugins/wp-syntax/geshi/geshi/eiffel.php
+++ b/plugins/wp-syntax/geshi/geshi/eiffel.php
@@ -4,7 +4,7 @@
* ----------
* Author: Zoran Simic (zsimic@axarosenberg.com)
* Copyright: (c) 2005 Zoran Simic
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/06/30
*
* Eiffel language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/email.php b/plugins/wp-syntax/geshi/geshi/email.php
index 6becb1ff..8a313d48 100644
--- a/plugins/wp-syntax/geshi/geshi/email.php
+++ b/plugins/wp-syntax/geshi/geshi/email.php
@@ -4,7 +4,7 @@
* ---------------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/10/19
*
* Email (mbox \ eml \ RFC format) language file for GeSHi.
@@ -51,14 +51,14 @@ $language_data = array (
'HTTP', 'SMTP', 'ASMTP', 'ESMTP'
),
2 => array(
- 'Authentication-Results','Content-Description','Content-Type',
+ 'Authentication-Results','Comment','Content-Description','Content-Type',
'Content-Disposition','Content-Transfer-Encoding','Delivered-To',
'Dkim-Signature','Domainkey-Signature','In-Reply-To','Message-Id',
'MIME-Version','OpenPGP','Received','Received-SPF','References',
- 'Resend-From','Resend-To','Return-Path','User-Agent'
+ 'Reply-To', 'Resend-From','Resend-To','Return-Path','User-Agent'
),
3 => array(
- 'Date','From','Subject','To',
+ 'Date','From','Sender','Subject','To','CC'
),
4 => array(
'by', 'for', 'from', 'id', 'with'
@@ -132,7 +132,7 @@ $language_data = array (
),
//Email-Adresses or Mail-IDs
2 => array(
- GESHI_SEARCH => "\b[\w\.\-]+@\w+(?:(?:\.\w+)*\.\w{2,4})?",
+ GESHI_SEARCH => "\b(?<!\\/)(?P<q>\"?)[\w\.\-]+\k<q>@(?!-)[\w\-]+(?<!-)(?:(?:\.(?!-)[\w\-]+(?<!-))*)?",
GESHI_REPLACE => "\\0",
GESHI_MODIFIERS => "mi",
GESHI_BEFORE => "",
@@ -152,7 +152,19 @@ $language_data = array (
4 => array(
GESHI_SEARCH => "(?<=\s)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?=\s)|".
"(?<=\[)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?=\])|".
- "(?<==)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?=<)",
+ "(?<==)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?=<)|".
+
+ "(?<=\s)(?:[a-f\d]{1,4}\:)+(?:[a-f\d]{0,4})?(?:\:[a-f\d]{1,4})+(?=\s)|".
+ "(?<=\[)(?:[a-f\d]{1,4}\:)+(?:[a-f\d]{0,4})?(?:\:[a-f\d]{1,4})+(?=\])|".
+ "(?<==)(?:[a-f\d]{1,4}\:)+(?:[a-f\d]{0,4})?(?:\:[a-f\d]{1,4})+(?=<)|".
+
+ "(?<=\s)\:(?:\:[a-f\d]{1,4})+(?=\s)|".
+ "(?<=\[)\:(?:\:[a-f\d]{1,4})+(?=\])|".
+ "(?<==)\:(?:\:[a-f\d]{1,4})+(?=<)|".
+
+ "(?<=\s)(?:[a-f\d]{1,4}\:)+\:(?=\s)|".
+ "(?<=\[)(?:[a-f\d]{1,4}\:)+\:(?=\])|".
+ "(?<==)(?:[a-f\d]{1,4}\:)+\:(?=<)",
GESHI_REPLACE => "\\0",
GESHI_MODIFIERS => "i",
GESHI_BEFORE => "",
@@ -178,7 +190,7 @@ $language_data = array (
),
'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
'SCRIPT_DELIMITERS' => array(
- 0 => "/(?P<start>^)[A-Z][a-zA-Z0-9\-]*\s*:\s*(?:.|(?=\n\s)\n)*(?P<end>$)/m"
+ 0 => "/(?P<start>^)[A-Za-z][a-zA-Z0-9\-]*\s*:\s*(?:.|(?=\n\s)\n)*(?P<end>$)/m"
),
'HIGHLIGHT_STRICT_BLOCK' => array(
0 => true,
diff --git a/plugins/wp-syntax/geshi/geshi/epc.php b/plugins/wp-syntax/geshi/geshi/epc.php
new file mode 100644
index 00000000..c575c0c6
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/epc.php
@@ -0,0 +1,154 @@
+<?php
+/*************************************************************************************
+ * epc.php
+ * --------
+ * Author: Thorsten Muehlfelder (muehlfelder@enertex.de)
+ * Copyright: (c) 2010 Enertex Bayern GmbH
+ * Release Version: 1.0.8.11
+ * Date Started: 2010/08/26
+ *
+ * Enerscript language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2010/08/26 (1.0.8.10)
+ * - First Release
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'EPC',
+ 'COMMENT_SINGLE' => array('//'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_REGEXP' => array(
+ //[Sections]
+ //1 => "/^\\[.*\\]/"
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array(
+ 0 => '"',
+ 1 => '$'
+ ),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'if', 'then', 'else', 'endif',
+ 'and', 'or', 'xor', 'hysteresis'
+ ),
+ 2 => array(
+ 'read', 'write', 'event',
+ 'gettime', 'settime', 'getdate', 'setdate', 'gettimedate', 'settimedate',
+ 'hour', 'minute', 'second', 'changehour', 'changeminute', 'changesecond',
+ 'date', 'month', 'day', 'dayofweek', 'sun', 'azimuth', 'elevation',
+ 'sunrisehour', 'sunriseminute', 'sunsethour', 'sunsetminute',
+ 'wtime', 'htime', 'mtime', 'stime',
+ 'cwtime', 'chtime', 'cmtime', 'cstime',
+ 'delay', 'after', 'cycle',
+ 'readflash', 'writeflash',
+ 'abs', 'acos', 'asin', 'atan', 'cos', 'ceil', 'average', 'exp', 'floor',
+ 'log', 'max', 'min', 'mod', 'pow', 'sqrt', 'sin', 'tan', 'change', 'convert',
+ 'eval', 'systemstart', 'random', 'comobject', 'sleep', 'scene', 'storescene', 'callscene',
+ 'find', 'stringcast', 'stringset', 'stringformat', 'split', 'size',
+ 'readrs232'. 'sendrs232', 'address', 'readknx',
+ 'readudp', 'sendudp', 'connecttcp', 'closetcp', 'readtcp', 'sendtcp',
+ 'resolve', 'sendmail',
+ 'button', 'webbutton', 'chart', 'webchart', 'webdisplay', 'getslider', 'pshifter', 'mpshifter',
+ 'getpslider', 'mbutton', 'mbbutton', 'mchart', 'mpchart', 'mpbutton', 'pdisplay', 'pchart',
+ 'pbutton', 'setslider', 'setpslider', 'slider', 'pslider', 'page', 'line', 'header',
+ 'footer', 'none', 'plink', 'link', 'frame', 'dframe'
+ )
+ ),
+ 'SYMBOLS' => array(
+ 0 => array(
+ '%', 'b01',
+ ),
+ 1 => array(
+ '+', '-', '==', '>=', '=<',
+ ),
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #e63ec3;',
+ 2 => 'color: #e63ec3;'
+ ),
+ 'COMMENTS' => array(
+ 0 => 'color: #0000ff;'
+ //1 => 'color: #ffa500;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 1 => 'color: #000099;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #000000;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #8a0808;',
+ 1 => 'color: #6e6e6e;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #0b610b;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #0b610b;',
+ 1 => 'color: #e63ec3;'
+ ),
+ 'REGEXPS' => array(
+ 1 => 'color: #0b610b;'
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ // Numbers, e.g. 255u08
+ 1 => "[0-9]*[subf][0136][12468]"
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4,
+ 'PARSER_CONTROL' => array(
+ 'COMMENTS' => array(
+ 'DISALLOWED_BEFORE' => '$'
+ ),
+ 'KEYWORDS' => array(
+ 'DISALLOWED_BEFORE' => "(?<![\.\-a-zA-Z0-9_\$\#])",
+ 'DISALLOWED_AFTER' => "(?![\.\-a-zA-Z0-9_%=\\/])"
+ )
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/erlang.php b/plugins/wp-syntax/geshi/geshi/erlang.php
index 1d4bccf4..4b8d406b 100644
--- a/plugins/wp-syntax/geshi/geshi/erlang.php
+++ b/plugins/wp-syntax/geshi/geshi/erlang.php
@@ -7,7 +7,7 @@
* - Uwe Dauernheim (uwe@dauernheim.net)
* - Dan Forest-Barbier (dan@twisted.in)
* Copyright: (c) 2008 Uwe Dauernheim (http://www.kreisquadratur.de/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008-09-27
*
* Erlang language file for GeSHi.
@@ -355,7 +355,7 @@ $language_data = array(
2 => ':'
),
'REGEXPS' => array(
- // Macro definitions
+ //�Macro definitions
0 => array(
GESHI_SEARCH => '(-define\s*\()([a-zA-Z0-9_]+)(\(|,)',
GESHI_REPLACE => '\2',
@@ -403,7 +403,7 @@ $language_data = array(
GESHI_BEFORE => '\1',
GESHI_AFTER => ''
),
- // ASCII codes
+ // ASCII�codes
6 => '(\$[a-zA-Z0-9_])',
// Records
7 => array(
@@ -423,8 +423,8 @@ $language_data = array(
'PARSER_CONTROL' => array(
'KEYWORDS' => array(
3 => array(
- 'DISALLOWED_BEFORE' => '',
- 'DISALLOWED_AFTER' => '(?=\s*\()'
+ 'DISALLOWED_BEFORE' => '(?<![\w])',
+ 'DISALLOWED_AFTER' => ''//'(?=\s*\()'
),
5 => array(
'DISALLOWED_BEFORE' => '(?<=\'|)',
diff --git a/plugins/wp-syntax/geshi/geshi/euphoria.php b/plugins/wp-syntax/geshi/geshi/euphoria.php
new file mode 100644
index 00000000..7bbf8846
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/euphoria.php
@@ -0,0 +1,140 @@
+<?php
+/*************************************************************************************
+ * euphoria.php
+ * ---------------------------------
+ * Author: Nicholas Koceja (nerketur@hotmail.com)
+ * Copyright: (c) 2010 Nicholas Koceja
+ * Release Version: 1.0.8.11
+ * Date Started: 11/24/2010
+ *
+ * Euphoria language file for GeSHi.
+ *
+ * Author's note: The colors are based off of the Euphoria Editor (ed.ex) colors.
+ * Also, I added comments in places so I could remember a few things about Euphoria.
+ *
+ *
+ * CHANGES
+ * -------
+ * <date-of-release> (1.0.8.9)
+ * - First Release
+ *
+ * TODO (updated <date-of-release>)
+ * -------------------------
+ * seperate the funtions from the procedures, and have a slight color change for each.
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'Euphoria',
+ 'COMMENT_SINGLE' => array(1 => '--'),
+ 'COMMENT_MULTI' => array(), //Euphoria doesn't support multi-line comments
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ 1 => array( // keywords
+ 'and', 'by', 'constant', 'do', 'else', 'elsif', 'end', 'exit',
+ 'for', 'function', 'global', 'if', 'include', 'not', 'or',
+ 'procedure', 'return', 'then', 'to', 'type', 'while', 'with',
+ 'without', 'xor'
+ ),
+ 2 => array( // built-ins
+ 'abort', 'and_bits', 'append', 'arctan', 'atom', 'c_func', 'call',
+ 'c_proc', 'call_func', 'call_proc', 'clear_screen', 'close', 'compare',
+ 'command_line', 'cos', 'date', 'equal', 'find', 'find_from', 'floor',
+ 'getc', 'getenv', 'gets', 'get_key', 'get_pixel', 'integer', 'length',
+ 'log', 'machine_func', 'machine_proc', 'match', 'match_from',
+ 'mem_copy', 'mem_set', 'not_bits', 'object', 'open', 'or_bits', 'peek',
+ 'peek4s', 'peek4u', 'pixel', 'platform', 'poke', 'poke4', 'position',
+ 'power', 'prepend', 'print', 'printf', 'profile', 'puts', 'rand',
+ 'remainder', 'repeat', 'routine_id', 'sequence', 'sin', 'sprintf',
+ 'sqrt', 'system', 'system_exec', 'tan', 'task_clock_stop',
+ 'task_clock_start', 'task_create', 'task_list', 'task_schedule',
+ 'task_self', 'task_status', 'task_suspend', 'task_yield', 'time',
+ 'trace', 'xor_bits'
+ ),
+ ),
+ 'SYMBOLS' => array(
+ 0 => array(
+ '(', ')', '{', '}', '[', ']'
+ ),
+ 1 => array(
+ '+', '-', '*', '/', '=', '&', '^'
+ ),
+ 2 => array(
+ '&', '?', ','
+ )
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #0000ff; font-weight: bold;', // keywords
+ 2 => 'color: #cc33ff; font-weight: bold;', // builtins
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #ff0000; font-style: italic;',
+ 'MULTI' => '' // doesn't exist
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #009900; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #999900; font-weight: bold;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #00cc00;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc33cc; font-style: italic'
+ ),
+ 'METHODS' => array( // Doesn't exist in Euphoria. Everything is a function =)
+ 0 => ''
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #999900;', // brackets
+ 1 => 'color: #333333;', // operators
+ 2 => 'color: #333333; font-style: bold' // print+concat
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array( // Never included in scripts.
+ )
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/f1.php b/plugins/wp-syntax/geshi/geshi/f1.php
index dd3a812f..7d767608 100644
--- a/plugins/wp-syntax/geshi/geshi/f1.php
+++ b/plugins/wp-syntax/geshi/geshi/f1.php
@@ -4,7 +4,7 @@
* -------
* Author: Juro Bystricky (juro@f1compiler.com)
* Copyright: K2 Software Corp.
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/07/06
*
* Formula One language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/falcon.php b/plugins/wp-syntax/geshi/geshi/falcon.php
new file mode 100644
index 00000000..2111d9e8
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/falcon.php
@@ -0,0 +1,218 @@
+<?php
+/*************************************************************************************
+ * falcon.php
+ * ---------------------------------
+ * Author: billykater (billykater+geshi@gmail.com)
+ * Copyright: (c) 2010 billykater (http://falconpl.org/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2010/06/07
+ *
+ * Falcon language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * <2010/8/1> (1.0.8.10)
+ * - First Release
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'Falcon',
+ 'COMMENT_SINGLE' => array( 1 => '//' ),
+ 'COMMENT_MULTI' => array( '/*' => '*/' ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array( "'", '"' ),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'break','case','catch','class','const','continue','def','default',
+ 'dropping','elif','else','end','enum','for','forfirst','forlast',
+ 'formiddle','from','function','global','if','init','innerfunc',
+ 'launch','loop','object','raise','return','select','state','static',
+ 'switch','try','while'
+ ),
+ 2 => array(
+ 'false','nil','true',
+ ),
+ 3 => array(
+ 'and','as','eq','fself','in','not','notin','or','provides','self','to'
+ ),
+ 4 => array(
+ 'directive','export','import','load','macro'
+ ),
+ 5 => array(
+ 'ArrayType','BooleanType','ClassMethodType','ClassType','DictionaryType',
+ 'FunctionType','MemBufType','MethodType','NilType','NumericType','ObjectType',
+ 'RangeType','StringType','LBindType'
+ ),
+ 6 => array(
+ "CurrentTime","IOStream","InputStream","MemBufFromPtr","OutputStream",
+ "PageDict","ParseRFC2822","abs","acos","all",
+ "allp","any","anyp","argd","argv",
+ "arrayAdd","arrayBuffer","arrayCompact","arrayDel","arrayDelAll",
+ "arrayFill","arrayFind","arrayHead","arrayIns","arrayMerge",
+ "arrayNM","arrayRemove","arrayResize","arrayScan","arraySort",
+ "arrayTail","asin","assert","atan","atan2",
+ "attributes","baseClass","beginCritical","bless","brigade",
+ "broadcast","cascade","ceil","choice","chr",
+ "className","clone","combinations","compare","consume",
+ "cos","deg2rad","deoob","derivedFrom","describe",
+ "deserialize","dictBack","dictBest","dictClear","dictFill",
+ "dictFind","dictFront","dictGet","dictKeys","dictMerge",
+ "dictRemove","dictSet","dictValues","dirChange","dirCurrent",
+ "dirMake","dirMakeLink","dirReadLink","dirRemove","dolist",
+ "endCritical","epoch","eval","exit","exp",
+ "factorial","fileChgroup","fileChmod","fileChown","fileCopy",
+ "fileExt","fileMove","fileName","fileNameMerge","filePath",
+ "fileRemove","fileType","fileUnit","filter","fint",
+ "firstOf","floop","floor","fract","getAssert",
+ "getEnviron","getProperty","getSlot","getSystemEncoding","getenv",
+ "iff","include","input","inspect","int",
+ "isBound","isCallable","isoob","lbind","len",
+ "let","lit","log","map","max",
+ "metaclass","min","numeric","oob","ord",
+ "paramCount","paramIsRef","paramSet","parameter","passvp",
+ "permutations","pow","print","printl","properties",
+ "rad2deg","random","randomChoice","randomDice","randomGrab",
+ "randomPick","randomSeed","randomWalk","readURI","reduce",
+ "retract","round","seconds","serialize","set",
+ "setProperty","setenv","sin","sleep","stdErr",
+ "stdErrRaw","stdIn","stdInRaw","stdOut","stdOutRaw",
+ "strBack","strBackFind","strBackTrim","strBuffer","strCmpIgnoreCase",
+ "strEndsWith","strEscape","strEsq","strFill","strFind",
+ "strFromMemBuf","strFront","strFrontTrim","strLower","strMerge",
+ "strReplace","strReplicate","strSplit","strSplitTrimmed","strStartsWith",
+ "strToMemBuf","strTrim","strUnescape","strUnesq","strUpper",
+ "strWildcardMatch","subscribe","systemErrorDescription","tan","times",
+ "toString","transcodeFrom","transcodeTo","typeOf","unsetenv",
+ "unsubscribe","valof","vmFalconPath","vmIsMain","vmModuleName",
+ "vmModuleVersionInfo","vmSearchPath","vmSystemType","vmVersionInfo","vmVersionName",
+ "writeURI","xmap","yield","yieldOut"
+ ),
+ 7 => array(
+ "AccessError","Array","BOM","Base64","Class",
+ "ClassMethod","CloneError","CmdlineParser","CodeError","Continuation",
+ "Dictionary","Directory","Error","FileStat","Format",
+ "Function","GarbagePointer","GenericError","Integer","InterruptedError",
+ "IoError","Iterator","LateBinding","List","MathError",
+ "MemoryBuffer","MessageError","Method","Numeric","Object",
+ "ParamError","ParseError","Path","Range","Semaphore",
+ "Sequence","Set","Stream","String","StringStream",
+ "SyntaxError","Table","TableError","TimeStamp","TimeZone",
+ "Tokenizer","TypeError","URI","VMSlot"
+ ),
+ 8 => array(
+ "args","scriptName","scriptPath"
+ ),
+ 9 => array(
+ "GC"
+ ),
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => 'http://falconpl.org/project_docs/core/functions.html#typeOf',
+ 6 => 'http://falconpl.org/project_docs/core/functions.html#{FNAME}',
+ 7 => 'http://falconpl.org/project_docs/core/class_{FNAME}.html',
+ 8 => 'http://falconpl.org/project_docs/core/globals.html#{FNAME}',
+ 9 => 'http://falconpl.org/project_docs/core/object_{FNAME}.html)'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ 5 => true,
+ 6 => true,
+ 7 => true,
+ 8 => true,
+ 9 => true
+ ),
+ 'SYMBOLS' => array(
+ '(',')','$','%','&','/','{','[',']','=','}','?','+','-','#','*','@',
+ '<','>','|',',',':',';','\\','^'
+ ),
+ 'REGEXPS' => array(
+ 0 => array(
+ GESHI_SEARCH => '(\[)([a-zA-Z_]|\c{C})(?:[a-zA-Z0-9_]|\p{C})*(\])',
+ GESHI_REPLACE => '\\2',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '\\1',
+ GESHI_AFTER => '\\3',
+
+ ),
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+ 'SCRIPT_DELIMITERS' => array(
+ 0 => array( '<?' => '?>' )
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ 0 => true
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #000080;font-weight:bold;',
+ 2 => 'color: #800000;font-weight:bold;',
+ 3 => 'color: #800000;font-weight:bold;',
+ 4 => 'color: #000080;font-weight:bold;',
+ 5 => 'color: #000000;font-weight:bold;',
+ 6 => 'font-weight:bold;',
+ 7 => 'font-weight:bold;',
+ 8 => 'font-weight:bold;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #29B900;',
+ 'MULTI' => 'color: #008080'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #800000'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #000000'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #800000'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #000000'
+ ),
+ 'METHODS' => array(
+ 0 => 'color: #000000'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #8B0513'
+ ),
+ 'SCRIPT' => array(
+ 0 => ''
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color: #FF00FF'
+ )
+ ),
+
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ '.'
+ )
+);
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/fo.php b/plugins/wp-syntax/geshi/geshi/fo.php
index 9e08b9cf..ba4a5924 100644
--- a/plugins/wp-syntax/geshi/geshi/fo.php
+++ b/plugins/wp-syntax/geshi/geshi/fo.php
@@ -4,7 +4,7 @@
* --------
* Author: Tan-Vinh Nguyen (tvnguyen@web.de)
* Copyright: (c) 2009 Tan-Vinh Nguyen
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/03/23
*
* fo language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/fortran.php b/plugins/wp-syntax/geshi/geshi/fortran.php
index d8b104a7..c21ccd19 100644
--- a/plugins/wp-syntax/geshi/geshi/fortran.php
+++ b/plugins/wp-syntax/geshi/geshi/fortran.php
@@ -4,7 +4,7 @@
* -----------
* Author: Cedric Arrabie (cedric.arrabie@univ-pau.fr)
* Copyright: (C) 2006 Cetric Arrabie
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/04/22
*
* Fortran language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/freebasic.php b/plugins/wp-syntax/geshi/geshi/freebasic.php
index 77f75b5c..b23f39bc 100644
--- a/plugins/wp-syntax/geshi/geshi/freebasic.php
+++ b/plugins/wp-syntax/geshi/geshi/freebasic.php
@@ -4,7 +4,7 @@
* -------------
* Author: Roberto Rossi
* Copyright: (c) 2005 Roberto Rossi (http://rsoftware.altervista.org)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/08/19
*
* FreeBasic (http://www.freebasic.net/) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/freeswitch.php b/plugins/wp-syntax/geshi/geshi/freeswitch.php
new file mode 100644
index 00000000..c6fff276
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/freeswitch.php
@@ -0,0 +1,168 @@
+<?php
+/*************************************************************************************
+ * freeswitch.php
+ * --------
+ * Author: James Rose (james.gs@stubbornroses.com)
+ * Copyright: (c) 2006 Christian Lescuyer http://xtian.goelette.info
+ * Release Version: 1.0.8.11n/a
+ * Date Started: 2011/11/18
+ *
+ * FreeSWITCH language file for GeSHi.
+ *
+ * This file is based on robots.php
+ *
+ * 2011/11/18 (1.0.0)
+ * - First Release
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'FreeSWITCH',
+ 'COMMENT_SINGLE' => array(1 => '#'),
+ 'COMMENT_MULTI' => array(),
+ 'COMMENT_REGEXP' => array(1 => "/^Comment:.*?$/m"),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array(),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+// 1 => array(
+// 'Disallow', 'Request-rate', 'Robot-version',
+// 'Sitemap', 'User-agent', 'Visit-time'
+// )
+ ),
+ 'SYMBOLS' => array(
+// ':'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false
+ ),
+
+//order is important. regexes will overwrite most things....
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+// 1 => 'color: #FF0000; font-weight: bold;',//red
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #808080; font-style: italic;',
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+// 0 => 'color: #66cc66;'
+ ),
+ 'STRINGS' => array(
+// 0 => 'color: #ff0000;'
+ ),
+ 'NUMBERS' => array(
+// 0 => 'color: #cc66cc;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+// 0 => 'color: #66cc66;'
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color: firebrick; font-weight: bold;',
+ 1 => 'color: cornflowerblue; font-weight: bold;',
+ 2 => 'color: goldenrod; font-weight: bold;',
+ 3 => 'color: green; font-weight: bold;',
+ 4 => 'color: dimgrey; font-style: italic;',
+ 5 => 'color: green; font-weight: bold;',
+ 6 => 'color: firebrick; font-weight: bold;',
+ 7 => 'color: indigo; font-weight: italic;'
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+// 1 => 'http://www.robotstxt.org/wc/norobots.html'
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ 0 => array(
+ GESHI_SEARCH => '(^.*ERROR.*)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => 'im',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ ),
+ 1 => array(
+ GESHI_SEARCH => '(^.*NOTICE.*)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => 'im',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ ),
+ 2 => array(
+ GESHI_SEARCH => '(^.*DEBUG.*)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => 'm',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ ),
+ 3 => array(
+ GESHI_SEARCH => '(^.*INFO.*|.*info\(.*|^Channel.*|^Caller.*|^variable.*)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => 'm',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ ),
+ 4 => array(
+ GESHI_SEARCH => '(^Dialplan.*)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => 'im',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ ),
+ 5 => array(
+ GESHI_SEARCH => '(Regex\ \(PASS\))',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ ),
+ 6 => array(
+ GESHI_SEARCH => '(Regex\ \(FAIL\))',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ ),
+ 7 => array(
+ GESHI_SEARCH => '(\d{7,15})',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ )
+ ),
+
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ )
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/fsharp.php b/plugins/wp-syntax/geshi/geshi/fsharp.php
index afff9dc4..d85a7c75 100644
--- a/plugins/wp-syntax/geshi/geshi/fsharp.php
+++ b/plugins/wp-syntax/geshi/geshi/fsharp.php
@@ -4,7 +4,7 @@
* ----------
* Author: julien ortin (jo_spam-divers@yahoo.fr)
* Copyright: (c) 2009 julien ortin
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/09/20
*
* F# language file for GeSHi.
@@ -43,7 +43,8 @@
$language_data = array(
'LANG_NAME' => 'F#',
'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
- 'COMMENT_MULTI' => array('(*' => '*)', '/*' => '*/'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_REGEXP' => array(3 => '/\(\*(?!\)).*?\*\)/s'),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'HARDQUOTE' => array('@"', '"'),
@@ -153,7 +154,8 @@ $language_data = array(
'COMMENTS' => array(
'MULTI' => 'color: #5d478b; font-style: italic;', /* light purple */
1 => 'color: #5d478b; font-style: italic;',
- 2 => 'color: #5d478b; font-style: italic;' /* light purple */
+ 2 => 'color: #5d478b; font-style: italic;', /* light purple */
+ 3 => 'color: #5d478b; font-style: italic;' /* light purple */
),
'ESCAPE_CHAR' => array(
),
diff --git a/plugins/wp-syntax/geshi/geshi/gambas.php b/plugins/wp-syntax/geshi/geshi/gambas.php
index a4dd43f8..352830eb 100644
--- a/plugins/wp-syntax/geshi/geshi/gambas.php
+++ b/plugins/wp-syntax/geshi/geshi/gambas.php
@@ -5,7 +5,7 @@
* Author: Jesus Guardon (jguardon@telefonica.net)
* Copyright: (c) 2009 Jesus Guardon (http://gambas-es.org),
* Benny Baumann (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/20
*
* GAMBAS language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/gdb.php b/plugins/wp-syntax/geshi/geshi/gdb.php
index be94fa8e..0a5e32c3 100644
--- a/plugins/wp-syntax/geshi/geshi/gdb.php
+++ b/plugins/wp-syntax/geshi/geshi/gdb.php
@@ -4,7 +4,7 @@
* --------
* Author: Milian Wolff (mail@milianw.de)
* Copyright: (c) 2009 Milian Wolff
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/06/24
*
* GDB language file for GeSHi.
@@ -43,7 +43,7 @@ $language_data = array (
'COMMENT_MULTI' => array(),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"'),
- 'ESCAPE_CHAR' => '',
+ 'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
0 => array(
'Application',
@@ -54,8 +54,7 @@ $language_data = array (
'[KCrash Handler]',
),
),
- 'NUMBERS' =>
- GESHI_NUMBER_INT_BASIC,
+ 'NUMBERS' => false,
'SYMBOLS' => array(
),
'CASE_SENSITIVE' => array(
@@ -79,7 +78,6 @@ $language_data = array (
0 => 'color: #933;'
),
'NUMBERS' => array(
- 0 => 'color: #cc66cc;',
),
'METHODS' => array(
),
@@ -88,12 +86,14 @@ $language_data = array (
'REGEXPS' => array(
0 => 'color: #000066; font-weight:bold;',
1 => 'color: #006600;',
- 2 => 'color: #000066;',
- 3 => 'color: #0066FF; text-style:italic;',
- 4 => 'color: #80B5FF; text-style:italic;',
- 5 => 'color: #A3007D;',
- 6 => 'color: #FF00BF;',
- 7 => 'font-weight: bold;'
+ 2 => 'color: #B07E00;',
+ 3 => 'color: #0057AE; text-style:italic;',
+ 4 => 'color: #0057AE; text-style:italic;',
+ 5 => 'color: #442886;',
+ 6 => 'color: #442886; font-weight:bold;',
+ 7 => 'color: #FF0000; font-weight:bold;',
+ 8 => 'color: #006E26;',
+ 9 => 'color: #555;',
),
'SCRIPT' => array(
)
@@ -132,7 +132,7 @@ $language_data = array (
),
//Files with linenumbers
3 => array(
- GESHI_SEARCH => '(at )(.+)(:\d+\s*)$',
+ GESHI_SEARCH => '(at\s+)(.+)(:\d+\s*)$',
GESHI_REPLACE => '\\2',
GESHI_MODIFIERS => 'm',
GESHI_BEFORE => '\\1',
@@ -140,16 +140,14 @@ $language_data = array (
),
//Libs without linenumbers
4 => array(
- GESHI_SEARCH => '(from )(.+)(\s*)$',
+ GESHI_SEARCH => '(from\s+)(.+)(\s*)$',
GESHI_REPLACE => '\\2',
GESHI_MODIFIERS => 'm',
GESHI_BEFORE => '\\1',
GESHI_AFTER => '\\3'
),
- //Hex mem address
- 5 => '0x[a-f0-9]+',
//Line numbers
- 6 => array(
+ 5 => array(
GESHI_SEARCH => '(:)(\d+)(\s*)$',
GESHI_REPLACE => '\\2',
GESHI_MODIFIERS => 'm',
@@ -157,19 +155,44 @@ $language_data = array (
GESHI_AFTER => '\\3'
),
//Location
+ 6 => array(
+ GESHI_SEARCH => '(\s+)(in\s+)?([^ 0-9][^ ]*)([ \n]+\()',
+ GESHI_REPLACE => '\\3',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '\\1\\2',
+ GESHI_AFTER => '\\4'
+ ),
+ // interesting parts: abort, qFatal, assertions, null ptrs, ...
7 => array(
- GESHI_SEARCH => '( in )([^ \(\)]+)( \()',
- GESHI_REPLACE => '\\2',
+ GESHI_SEARCH => '\b((?:\*__GI_)?(?:__assert_fail|abort)|qFatal|0x0)\b([^\.]|$)',
+ GESHI_REPLACE => '\\1',
GESHI_MODIFIERS => '',
- GESHI_BEFORE => '\\1',
- GESHI_AFTER => '\\3'
+ GESHI_BEFORE => '',
+ GESHI_AFTER => '\\2'
+ ),
+ // Namespace / Classes
+ 8 => array(
+ GESHI_SEARCH => '\b(\w+)(::)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => 'U',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => '\\2'
),
+ // make ptr adresses and <value optimized out> uninteresting
+ 9 => '\b(?:0x[a-f0-9]{2,}|value\s+optimized\s+out)\b'
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'PARSER_CONTROL' => array(
+ 'ENABLE_FLAGS' => array(
+ 'NUMBERS' => false
+ ),
)
);
+// kate: replace-tabs on; indent-width 4;
+
?>
diff --git a/plugins/wp-syntax/geshi/geshi/genero.php b/plugins/wp-syntax/geshi/geshi/genero.php
index 5f752b80..e1b20b3e 100644
--- a/plugins/wp-syntax/geshi/geshi/genero.php
+++ b/plugins/wp-syntax/geshi/geshi/genero.php
@@ -4,7 +4,7 @@
* ----------
* Author: Lars Gersmann (lars.gersmann@gmail.com)
* Copyright: (c) 2007 Lars Gersmann, Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/07/01
*
* Genero (FOURJ's Genero 4GL) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/genie.php b/plugins/wp-syntax/geshi/geshi/genie.php
index 3c354ad6..db05ec06 100644
--- a/plugins/wp-syntax/geshi/geshi/genie.php
+++ b/plugins/wp-syntax/geshi/geshi/genie.php
@@ -4,7 +4,7 @@
* ----------
* Author: Nicolas Joseph (nicolas.joseph@valaide.org)
* Copyright: (c) 2009 Nicolas Joseph
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/04/29
*
* Genie language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/gettext.php b/plugins/wp-syntax/geshi/geshi/gettext.php
index 90c34a8f..80b531c1 100644
--- a/plugins/wp-syntax/geshi/geshi/gettext.php
+++ b/plugins/wp-syntax/geshi/geshi/gettext.php
@@ -4,7 +4,7 @@
* --------
* Author: Milian Wolff (mail@milianw.de)
* Copyright: (c) 2008 Milian Wolff
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/05/25
*
* GNU Gettext .po/.pot language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/glsl.php b/plugins/wp-syntax/geshi/geshi/glsl.php
index dbb7ff62..3615cfe7 100644
--- a/plugins/wp-syntax/geshi/geshi/glsl.php
+++ b/plugins/wp-syntax/geshi/geshi/glsl.php
@@ -4,7 +4,7 @@
* -----
* Author: Benny Baumann (BenBE@omorphia.de)
* Copyright: (c) 2008 Benny Baumann (BenBE@omorphia.de)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/03/20
*
* glSlang language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/gml.php b/plugins/wp-syntax/geshi/geshi/gml.php
index 9d0d88d8..999251b2 100644
--- a/plugins/wp-syntax/geshi/geshi/gml.php
+++ b/plugins/wp-syntax/geshi/geshi/gml.php
@@ -4,7 +4,7 @@
* --------
* Author: Jos� Jorge Enr�quez (jenriquez@users.sourceforge.net)
* Copyright: (c) 2005 Jos� Jorge Enr�quez Rodr�guez (http://www.zonamakers.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/06/21
*
* GML language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/gnuplot.php b/plugins/wp-syntax/geshi/geshi/gnuplot.php
index 05e26015..d8445eab 100644
--- a/plugins/wp-syntax/geshi/geshi/gnuplot.php
+++ b/plugins/wp-syntax/geshi/geshi/gnuplot.php
@@ -4,7 +4,7 @@
* ----------
* Author: Milian Wolff (mail@milianw.de)
* Copyright: (c) 2008 Milian Wolff (http://milianw.de)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/07/07
*
* Gnuplot script language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/go.php b/plugins/wp-syntax/geshi/geshi/go.php
index 941b74a0..5b7a47db 100644
--- a/plugins/wp-syntax/geshi/geshi/go.php
+++ b/plugins/wp-syntax/geshi/geshi/go.php
@@ -4,7 +4,7 @@
* --------
* Author: Markus Jarderot (mizardx at gmail dot com)
* Copyright: (c) 2010 Markus Jarderot
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/05/20
*
* Go language file for GeSHi.
@@ -55,6 +55,14 @@ $language_data = array(
4 => "#\\\\u[0-9a-fA-F]{4}#",
5 => "#\\\\U[0-9a-fA-F]{8}#"
),
+ 'NUMBERS' => array(
+ # integer literals (possibly imaginary)
+ 0 => '\b([1-9][0-9]*i?|0[0-7]*|0[xX][0-9a-f]+|0[0-9]*i)\b',
+ # real floating point literals
+ 1 => '\b((?:\d+\.\d*(?:[Ee][+-]?\d+\b)?|\.\d+(?:[Ee][+-]?\d+)?|\d+[Ee][+-]?\d+)?)\b',
+ # imaginary floating point literals
+ 2 => '\b((?:\d+\.\d*(?:[Ee][+-]?\d+)?|\.\d+(?:[Ee][+-]?\d+)?|\d+[Ee][+-]?\d+)?i)\b'
+ ),
'KEYWORDS' => array(
# statements
1 => array(
@@ -334,11 +342,11 @@ $language_data = array(
'REGEXPS' => array(
# If CSS classes are enabled, these would be highlighted as numbers (nu0)
# integer literals (possibly imaginary)
- 0 => 'color: #cc66cc;',
+ //0 => 'color: #cc66cc;',
# real floating point literals
- 1 => 'color: #cc66cc;',
+ //1 => 'color: #cc66cc;',
# imaginary floating point literals
- 2 => 'color: #cc66cc;'
+ //2 => 'color: #cc66cc;'
),
'SCRIPT' => array(
)
@@ -351,36 +359,8 @@ $language_data = array(
5 => 'http://golang.org/search?q={FNAME}'
),
'REGEXPS' => array(
- # integer literals (possibly imaginary)
- 0 => array(
- GESHI_SEARCH => '\b([1-9][0-9]+i?|0[0-7]*|0[xX][0-9a-f]+|0[0-9]*i)\b',
- GESHI_REPLACE => '\0',
- GESHI_MODIFIERS => '',
- GESHI_BEFORE => '',
- GESHI_AFTER => '',
- GESHI_CLASS => 'nu0'
- ),
- # real floating point literals
- 1 => array(
- GESHI_SEARCH => '((?:\b\d+\.\d*(?:[Ee][+-]?\d+\b)?|\.\d+(?:[Ee][+-]?\d+)?\b|\b\d+[Ee][+-]?\d+\b)?)',
- GESHI_REPLACE => '\0',
- GESHI_MODIFIERS => '',
- GESHI_BEFORE => '',
- GESHI_AFTER => '',
- GESHI_CLASS => 'nu0'
- ),
- # imaginary floating point literals
- 2 => array(
- GESHI_SEARCH => '((?:\b\d+\.\d*(?:[Ee][+-]?\d+)?|\.\d+(?:[Ee][+-]?\d+)?|\b\d+[Ee][+-]?\d+)?i\b)',
- GESHI_REPLACE => '\0',
- GESHI_MODIFIERS => '',
- GESHI_BEFORE => '',
- GESHI_AFTER => '',
- GESHI_CLASS => 'nu0'
- )
- # NB. "08" is an invalid number (octal), but "08i" is valid (complex).
),
-'OOLANG' => true,
+ 'OOLANG' => true,
'OBJECT_SPLITTERS' => array(1 => '.'),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(),
@@ -388,7 +368,6 @@ $language_data = array(
'PARSER_CONTROL' => array(
'ENABLE_FLAGS' => array(
'BRACKETS' => GESHI_NEVER, # handled by symbols
- 'NUMBERS' => GESHI_NEVER, # handled by regexp
)
)
);
diff --git a/plugins/wp-syntax/geshi/geshi/groovy.php b/plugins/wp-syntax/geshi/geshi/groovy.php
index e6f8ae03..45290d2f 100644
--- a/plugins/wp-syntax/geshi/geshi/groovy.php
+++ b/plugins/wp-syntax/geshi/geshi/groovy.php
@@ -4,7 +4,7 @@
* ----------
* Author: Ivan F. Villanueva B. (geshi_groovy@artificialidea.com)
* Copyright: (c) 2006 Ivan F. Villanueva B.(http://www.artificialidea.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/04/29
*
* Groovy language file for GeSHi.
@@ -983,15 +983,15 @@ $language_data = array (
)
),
'URLS' => array(
- 1 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAMEL}',
- 2 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAMEL}',
+ 1 => 'http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20{FNAMEL}',
+ 2 => 'http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20{FNAMEL}',
3 => 'http://www.google.de/search?as_q={FNAME}&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1%2E5%2E0%2Fdocs%2Fapi%2F',
- 4 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
- 5 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
- 6 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
- 7 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
- 8 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}',
- 9 => 'http://www.google.de/search?q=site%3Adocs.codehaus.org/%20{FNAME}'
+ 4 => 'http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20{FNAME}',
+ 5 => 'http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20{FNAME}',
+ 6 => 'http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20{FNAME}',
+ 7 => 'http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20{FNAME}',
+ 8 => 'http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20{FNAME}',
+ 9 => 'http://www.google.de/search?q=site%3Agroovy.codehaus.org/%20{FNAME}'
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/gwbasic.php b/plugins/wp-syntax/geshi/geshi/gwbasic.php
index 4b2b2722..ecc16341 100644
--- a/plugins/wp-syntax/geshi/geshi/gwbasic.php
+++ b/plugins/wp-syntax/geshi/geshi/gwbasic.php
@@ -4,7 +4,7 @@
* ----------
* Author: José Gabriel Moya Yangüela (josemoya@gmail.com)
* Copyright: (c) 2010 José Gabriel Moya Yangüela (http://doc.apagada.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/01/30
*
* GwBasic language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/haskell.php b/plugins/wp-syntax/geshi/geshi/haskell.php
index d4594707..adae1116 100644
--- a/plugins/wp-syntax/geshi/geshi/haskell.php
+++ b/plugins/wp-syntax/geshi/geshi/haskell.php
@@ -4,7 +4,7 @@
* ----------
* Author: Jason Dagit (dagit@codersbase.com) based on ocaml.php by Flaie (fireflaie@gmail.com)
* Copyright: (c) 2005 Flaie, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/08/27
*
* Haskell language file for GeSHi.
@@ -46,8 +46,8 @@ $language_data = array (
3 => "/{-(?:(?R)|.)-}/s", //Nested Comments
),
'CASE_KEYWORDS' => 0,
- 'QUOTEMARKS' => array('"'),
- 'ESCAPE_CHAR' => "\\",
+ 'QUOTEMARKS' => array('"',"'"),
+ 'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
/* main haskell keywords */
1 => array(
@@ -95,7 +95,7 @@ $language_data = array (
'product', 'concat', 'concatMap', 'maximum',
'minimum', 'scanl', 'scanl1', 'scanr', 'scanr1',
'iterate', 'repeat', 'cycle', 'take', 'drop',
- 'splitAt', 'teakWhile', 'dropWhile', 'span',
+ 'splitAt', 'takeWhile', 'dropWhile', 'span',
'break', 'elem', 'notElem', 'lookup', 'zip',
'zip3', 'zipWith', 'zipWith3', 'unzip', 'unzip3',
'lines', 'words', 'unlines',
diff --git a/plugins/wp-syntax/geshi/geshi/haxe.php b/plugins/wp-syntax/geshi/geshi/haxe.php
new file mode 100644
index 00000000..778637e2
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/haxe.php
@@ -0,0 +1,161 @@
+<?php
+/*************************************************************************************
+ * haxe.php
+ * --------
+ * Author: Andy Li (andy@onthewings.net)
+ * John Liao (colorhook@gmail.com)
+ * Copyright: (c) 2012 onthewings (http://www.onthewings.net/)
+ * 2010 colorhook (http://colorhook.com/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2010/10/05
+ *
+ * Haxe language file for GeSHi.
+ * Haxe version: 2.10
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'Haxe',
+ 'COMMENT_SINGLE' => array(1 => '//'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_REGEXP' => array(
+ //Import and Package directives (Basic Support only)
+ 2 => '/(?:(?<=import[\\n\\s])|(?<=using[\\n\\s])|(?<=package[\\n\\s]))[\\n\\s]*([a-zA-Z0-9_]+\\.)*([a-zA-Z0-9_]+|\*)(?=[\n\s;])/i',
+ // Haxe comments
+ 3 => '#/\*\*(?![\*\/]).*\*/#sU',
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ 1 => array(
+ //http://haxe.org/ref/keywords
+ 'break', 'callback', 'case', 'cast', 'catch', 'class', 'continue', 'default', 'do', 'dynamic',
+ 'else', 'enum', 'extends', 'extern', /*'false',*/ 'for', 'function', 'here', 'if',
+ 'implements', 'import', 'in', 'inline', 'interface', 'never', 'new', /*'null',*/ 'override',
+ 'package', 'private', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw',
+ 'trace', /*'true',*/ 'try', 'typedef', 'untyped', 'using', 'var', 'while',
+ 'macro', '$type',
+ ),
+ 2 => array(
+ //primitive values
+ 'null', 'false', 'true',
+ ),
+ 3 => array(
+ //global types
+ 'Array', 'ArrayAccess', /*'Bool',*/ 'Class', 'Date', 'DateTools', 'Dynamic',
+ 'EReg', 'Enum', 'EnumValue', /*'Float',*/ 'Hash', /*'Int',*/ 'IntHash', 'IntIter',
+ 'Iterable', 'Iterator', 'Lambda', 'List', 'Math', 'Null', 'Reflect', 'Std',
+ /*'String',*/ 'StringBuf', 'StringTools', 'Sys', 'Type', /*'UInt',*/ 'ValueType',
+ /*'Void',*/ 'Xml', 'XmlType',
+ ),
+ 4 => array(
+ //primitive types
+ 'Void', 'Bool', 'Int', 'Float', 'UInt', 'String',
+ ),
+ 5 => array(
+ //compiler switches
+ "#if", "#elseif", "#else", "#end", "#error",
+ ),
+ ),
+ 'SYMBOLS' => array(
+ //http://haxe.org/manual/operators
+ '++', '--',
+ '%',
+ '*', '/',
+ '+', '-',
+ '<<', '>>', '>>>',
+ '|', '&', '^',
+ '==', '!=', '>', '>=', '<', '<=',
+ '...',
+ '&&',
+ '||',
+ '?', ':',
+ '=', '+=', '-=', '/=', '*=', '<<=', '>>=', '>>>=', '|=', '&=', '^=',
+ '(', ')', '[', ']', '{', '}', ';',
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ 5 => true,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #6699cc; font-weight: bold;',
+ 2 => 'color: #000066; font-weight: bold;',
+ 3 => 'color: #03F; ',
+ 4 => 'color: #000033; font-weight: bold;',
+ 5 => 'color: #330000; font-weight: bold;',
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666; font-style: italic;',
+ 2 => 'color: #006699;',
+ 3 => 'color: #008000; font-style: italic; font-weight: bold;',
+ 3 => 'color: #008000; font-style: italic; font-weight: bold;',
+ 'MULTI' => 'color: #666666; font-style: italic;',
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;',
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #000000;',
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #FF0000;',
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;',
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #006633;',
+ 2 => 'color: #006633;',
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #339933;',
+ ),
+ 'SCRIPT' => array(
+ ),
+ 'REGEXPS' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.',
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/hicest.php b/plugins/wp-syntax/geshi/geshi/hicest.php
index 532c83af..78a2bc20 100644
--- a/plugins/wp-syntax/geshi/geshi/hicest.php
+++ b/plugins/wp-syntax/geshi/geshi/hicest.php
@@ -4,7 +4,7 @@
* --------
* Author: Georg Petrich (spt@hicest.com)
* Copyright: (c) 2010 Georg Petrich (http://www.HicEst.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/03/15
*
* HicEst language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/hq9plus.php b/plugins/wp-syntax/geshi/geshi/hq9plus.php
index a06fdc8d..7ba1a73c 100644
--- a/plugins/wp-syntax/geshi/geshi/hq9plus.php
+++ b/plugins/wp-syntax/geshi/geshi/hq9plus.php
@@ -4,7 +4,7 @@
* ----------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/10/31
*
* HQ9+ language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/html4strict.php b/plugins/wp-syntax/geshi/geshi/html4strict.php
index 6e0e2f0d..97392fa8 100644
--- a/plugins/wp-syntax/geshi/geshi/html4strict.php
+++ b/plugins/wp-syntax/geshi/geshi/html4strict.php
@@ -4,7 +4,7 @@
* ---------------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/10
*
* HTML 4.01 strict language file for GeSHi.
@@ -58,42 +58,24 @@ $language_data = array (
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
2 => array(
- 'a', 'abbr', 'acronym', 'address', 'applet',
-
+ 'a', 'abbr', 'acronym', 'address', 'applet', 'area',
'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'b',
-
'caption', 'center', 'cite', 'code', 'colgroup', 'col',
-
'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt',
-
'em',
-
'fieldset', 'font', 'form', 'frame', 'frameset',
-
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html',
-
'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'i',
-
'kbd',
-
'label', 'legend', 'link', 'li',
-
'map', 'meta',
-
'noframes', 'noscript',
-
'object', 'ol', 'optgroup', 'option',
-
'param', 'pre', 'p',
-
'q',
-
'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'style', 'sub', 'sup', 's',
-
'table', 'tbody', 'td', 'textarea', 'text', 'tfoot', 'thead', 'th', 'title', 'tr', 'tt',
-
'ul', 'u',
-
'var',
),
3 => array(
@@ -151,6 +133,7 @@ $language_data = array (
0 => 'color: #66cc66;'
),
'SCRIPT' => array(
+ -2 => 'color: #404040;', // CDATA
-1 => 'color: #808080; font-style: italic;', // comments
0 => 'color: #00bbdd;',
1 => 'color: #ddbb00;',
@@ -170,6 +153,9 @@ $language_data = array (
),
'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
'SCRIPT_DELIMITERS' => array(
+ -2 => array(
+ '<![CDATA[' => ']]>'
+ ),
-1 => array(
'<!--' => '-->'
),
@@ -184,6 +170,7 @@ $language_data = array (
)
),
'HIGHLIGHT_STRICT_BLOCK' => array(
+ -2 => false,
-1 => false,
0 => false,
1 => false,
@@ -200,4 +187,4 @@ $language_data = array (
)
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/html5.php b/plugins/wp-syntax/geshi/geshi/html5.php
new file mode 100644
index 00000000..0d975594
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/html5.php
@@ -0,0 +1,212 @@
+<?php
+/*************************************************************************************
+ * html5.php
+ * ---------------
+ * Author: Nigel McNie (nigel@geshi.org)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2004/07/10
+ *
+ * HTML 5 language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2005/12/28 (1.0.4)
+ * - Removed escape character for strings
+ * 2004/11/27 (1.0.3)
+ * - Added support for multiple object splitters
+ * 2004/10/27 (1.0.2)
+ * - Added support for URLs
+ * 2004/08/05 (1.0.1)
+ * - Added INS and DEL
+ * - Removed the background colour from tags' styles
+ * 2004/07/14 (1.0.0)
+ * - First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ * * Check that only HTML4 strict attributes are highlighted
+ * * Eliminate empty tags that aren't allowed in HTML4 strict
+ * * Split to several files - html4trans, xhtml1 etc
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'HTML5',
+ 'COMMENT_SINGLE' => array(),
+ 'COMMENT_MULTI' => array(),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 2 => array(
+ 'a', 'abbr', 'address', 'article', 'area', 'aside', 'audio',
+
+ 'base', 'bdo', 'blockquote', 'body', 'br', 'button', 'b',
+
+ 'caption', 'cite', 'code', 'colgroup', 'col', 'canvas', 'command', 'datalist', 'details',
+
+ 'dd', 'del', 'dfn', 'div', 'dl', 'dt',
+
+ 'em', 'embed',
+
+ 'fieldset', 'form', 'figcaption', 'figure', 'footer',
+
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html', 'header', 'hgroup',
+
+ 'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'i',
+
+ 'kbd', 'keygen',
+
+ 'label', 'legend', 'link', 'li',
+
+ 'map', 'meta', 'mark', 'meter',
+
+ 'noscript', 'nav',
+
+ 'object', 'ol', 'optgroup', 'option', 'output',
+
+ 'param', 'pre', 'p', 'progress',
+
+ 'q',
+
+ 'rp', 'rt', 'ruby',
+
+ 'samp', 'script', 'select', 'small', 'span', 'strong', 'style', 'sub', 'sup', 's', 'section', 'source', 'summary',
+
+ 'table', 'tbody', 'td', 'textarea', 'text', 'tfoot', 'thead', 'th', 'title', 'tr', 'time',
+
+ 'ul',
+
+ 'var', 'video',
+
+ 'wbr',
+ ),
+ 3 => array(
+ 'abbr', 'accept-charset', 'accept', 'accesskey', 'action', 'align', 'alink', 'alt', 'archive', 'axis', 'autocomplete', 'autofocus',
+ 'background', 'bgcolor', 'border',
+ 'cellpadding', 'cellspacing', 'char', 'charoff', 'charset', 'checked', 'cite', 'class', 'classid', 'clear', 'code', 'codebase', 'codetype', 'color', 'cols', 'colspan', 'compact', 'content', 'coords', 'contenteditable', 'contextmenu',
+ 'data', 'datetime', 'declare', 'defer', 'dir', 'disabled', 'draggable', 'dropzone',
+ 'enctype',
+ 'face', 'for', 'frame', 'frameborder', 'form', 'formaction', 'formenctype', 'formmethod', 'formnovalidate', 'formtarget',
+ 'headers', 'height', 'href', 'hreflang', 'hspace', 'http-equiv', 'hidden',
+ 'id', 'ismap',
+ 'label', 'lang', 'language', 'link', 'longdesc',
+ 'marginheight', 'marginwidth', 'maxlength', 'media', 'method', 'multiple', 'min', 'max',
+ 'name', 'nohref', 'noresize', 'noshade', 'nowrap', 'novalidate',
+ 'object', 'onblur', 'onchange', 'onclick', 'ondblclick', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onselect', 'onsubmit', 'onunload', 'onafterprint', 'onbeforeprint', 'onbeforeonload', 'onerror', 'onhaschange', 'onmessage', 'onoffline', 'ononline', 'onpagehide', 'onpageshow', 'onpopstate', 'onredo', 'onresize', 'onstorage', 'onundo', 'oncontextmenu', 'onformchange', 'onforminput', 'oninput', 'oninvalid', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onmousewheel', 'onscroll', 'oncanplay', 'oncanplaythrough', 'ondurationchange', 'onemptied', 'onended', 'onloadeddata', 'onloadedmetadata', 'onloadstart', 'onpause', 'onplay', 'onplaying', 'onprogress', 'onratechange', 'onreadystatechange', 'onseeked', 'onseeking', 'onstalled', 'onsuspend', 'ontimeupdate', 'onvolumechange', 'onwaiting',
+ 'profile', 'prompt', 'pattern', 'placeholder',
+ 'readonly', 'rel', 'rev', 'rowspan', 'rows', 'rules', 'required',
+ 'scheme', 'scope', 'scrolling', 'selected', 'shape', 'size', 'span', 'src', 'standby', 'start', 'style', 'summary', 'spellcheck', 'step',
+ 'tabindex', 'target', 'text', 'title', 'type',
+ 'usemap',
+ 'valign', 'value', 'valuetype', 'version', 'vlink', 'vspace',
+ 'width'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '/', '='
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 2 => false,
+ 3 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 2 => 'color: #000000; font-weight: bold;',
+ 3 => 'color: #000066;'
+ ),
+ 'COMMENTS' => array(
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'SCRIPT' => array(
+ -2 => 'color: #404040;', // CDATA
+ -1 => 'color: #808080; font-style: italic;', // comments
+ 0 => 'color: #00bbdd;',
+ 1 => 'color: #ddbb00;',
+ 2 => 'color: #009900;'
+ ),
+ 'REGEXPS' => array(
+ )
+ ),
+ 'URLS' => array(
+ 2 => 'http://december.com/html/4/element/{FNAMEL}.html',
+ 3 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
+ 'SCRIPT_DELIMITERS' => array(
+ -2 => array(
+ '<![CDATA[' => ']]>'
+ ),
+ -1 => array(
+ '<!--' => '-->'
+ ),
+ 0 => array(
+ '<!DOCTYPE' => '>'
+ ),
+ 1 => array(
+ '&' => ';'
+ ),
+ 2 => array(
+ '<' => '>'
+ )
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ -2 => false,
+ -1 => false,
+ 0 => false,
+ 1 => false,
+ 2 => true
+ ),
+ 'TAB_WIDTH' => 4,
+ 'PARSER_CONTROL' => array(
+ 'KEYWORDS' => array(
+ 2 => array(
+ 'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
+ 'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
+ )
+ )
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/icon.php b/plugins/wp-syntax/geshi/geshi/icon.php
index 8852e77a..06383ea5 100644
--- a/plugins/wp-syntax/geshi/geshi/icon.php
+++ b/plugins/wp-syntax/geshi/geshi/icon.php
@@ -4,7 +4,7 @@
* --------
* Author: Matt Oates (mattoates@gmail.com)
* Copyright: (c) 2010 Matt Oates (http://mattoates.co.uk)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/04/24
*
* Icon language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/idl.php b/plugins/wp-syntax/geshi/geshi/idl.php
index 5e730274..69bd14ff 100644
--- a/plugins/wp-syntax/geshi/geshi/idl.php
+++ b/plugins/wp-syntax/geshi/geshi/idl.php
@@ -4,7 +4,7 @@
* -------
* Author: Cedric Bosdonnat (cedricbosdo@openoffice.org)
* Copyright: (c) 2006 Cedric Bosdonnat
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/08/20
*
* Unoidl language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/ini.php b/plugins/wp-syntax/geshi/geshi/ini.php
index 692a1aa7..8e6ca76d 100644
--- a/plugins/wp-syntax/geshi/geshi/ini.php
+++ b/plugins/wp-syntax/geshi/geshi/ini.php
@@ -4,7 +4,7 @@
* --------
* Author: deguix (cevo_deguix@yahoo.com.br)
* Copyright: (c) 2005 deguix
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/03/27
*
* INI language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/inno.php b/plugins/wp-syntax/geshi/geshi/inno.php
index af2aab56..1e2ee8be 100644
--- a/plugins/wp-syntax/geshi/geshi/inno.php
+++ b/plugins/wp-syntax/geshi/geshi/inno.php
@@ -4,7 +4,7 @@
* ----------
* Author: Thomas Klingler (hotline@theratech.de) based on delphi.php from J�rja Norbert (jnorbi@vipmail.hu)
* Copyright: (c) 2004 J�rja Norbert, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/07/29
*
* Inno Script language inkl. Delphi (Object Pascal) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/intercal.php b/plugins/wp-syntax/geshi/geshi/intercal.php
index e123dae4..3c81b81c 100644
--- a/plugins/wp-syntax/geshi/geshi/intercal.php
+++ b/plugins/wp-syntax/geshi/geshi/intercal.php
@@ -4,7 +4,7 @@
* ----------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/10/31
*
* INTERCAL language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/io.php b/plugins/wp-syntax/geshi/geshi/io.php
index b6fcb81f..51fad43a 100644
--- a/plugins/wp-syntax/geshi/geshi/io.php
+++ b/plugins/wp-syntax/geshi/geshi/io.php
@@ -4,7 +4,7 @@
* -------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2006 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/09/23
*
* Io language file for GeSHi. Thanks to Johnathan Wright for the suggestion and help
diff --git a/plugins/wp-syntax/geshi/geshi/j.php b/plugins/wp-syntax/geshi/geshi/j.php
index 184385b3..5565bb49 100644
--- a/plugins/wp-syntax/geshi/geshi/j.php
+++ b/plugins/wp-syntax/geshi/geshi/j.php
@@ -4,13 +4,15 @@
* --------
* Author: Ric Sherlock (tikkanz@gmail.com)
* Copyright: (c) 2009 Ric Sherlock
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/11/10
*
* J language file for GeSHi.
*
* CHANGES
* -------
+ * 2010/07/18 (1.0.8.10)
+ * - Infinity and negative infinity recognized as numbers
* 2010/03/01 (1.0.8.8)
* - Add support for label_xyz. and goto_xyz.
* - Fix highlighting of for_i.
@@ -29,7 +31,6 @@
* 2009/11/12 (1.0.0)
* - First Release
*
- *
* TODO (updated 2010/01/27)
* -------------------------
* * combine keyword categories by using conditional regex statement in PARSER CONTROL?
@@ -53,7 +54,7 @@
*
************************************************************************************/
-$language_data = array (
+$language_data = array(
'LANG_NAME' => 'J',
'COMMENT_SINGLE' => array(),
'COMMENT_MULTI' => array(),
@@ -69,12 +70,7 @@ $language_data = array (
'HARDESCAPE' => array("'"),
'HARDCHAR' => "'",
'NUMBERS' => array(
- //Some instances of infinity are not correctly handled by GeSHi NUMBERS currently
- //There are two solutions labelled "infinity Method A" and "infinity Method B"
- //infinity Method B - requires following adjustment to line 3349 of geshi.php
- // preg_match('#\d#' becomes preg_match('#[\d_]#'
- 0 => '\b(?:_?\d+(?:\.\d+)?(?:x|[bejprx]_?[\da-z]+(?:\.[\da-z]+)?)?)(?![\w\.\:])', //infinity Method A
- //0 => '\b(?:_?\d+(?:\.\d+)?(?:x|[bejprx]_?[\da-z]+(?:\.[\da-z]+)?)?|__?)(?![\w\.\:])', //infinity Method B
+ 0 => '\b(?:_?\d+(?:\.\d+)?(?:x|[bejprx]_?[\da-z]+(?:\.[\da-z]+)?)?|__?)(?![\w\.\:])',
),
'KEYWORDS' => array(
//Control words
@@ -87,40 +83,6 @@ $language_data = array (
2 => array(
'm', 'n', 'u', 'v', 'x', 'y'
),
-/*
-Commented out for now due to conflicts with Lang Check
- //Primitives beginning with a symbol (except . or :)
- 6 => array(
- '=', '&lt;', '&lt;.', '&lt;:', //verbs
- '_:','&gt;', '&gt;.', '&gt;:',
- '+', '+.', '+:', '*', '*.', '*:', '-', '-.', '-:', '%', '%.', '%:',
- '^', '^.', '$', '$.', '$:', '~.', '~:', '\|', '|.', '|:',
- ',', ',.', ',:', ';', ';:', '#', '#.', '#:', '!', '/:', '\:',
- '[', '[:', ']', '{', '{.', '{:', '{::', '}.', '}:',
- '&quot;.', '&quot;:', '?', '?.',
- '~', '\/;', '\\', '/.', '\\.', '}', //adverbs
- '^:', ';.', '!.', '!:', //conj
- '&quot;', '`', '`:', '@', '@.', '@:',
- '&amp;', '&amp;.', '&amp;:', '&amp;.:',
- '_.', //nouns
- '=.', '=:', //other
- ),
- //Primitives beginning with a letter or number
- 7 => array(
- 'A.', 'c.', 'C.', 'e.', 'E.', //verbs
- 'i.', 'i:', 'I.', 'j.', 'L.', 'o.',
- 'p.', 'p..', 'p:', 'q:', 'r.', 's:', 'u:', 'x:',
- '_9:', '_8:', '_7:', '_6:', '_5:', '_4:', '_3:', '_2:', '_1:',
- '0:', '1:', '2:', '3:', '4:', '5:', '6:', '7:', '8:', '9:',
- 'b.', 'f.', 'M.', 't.', 't:', //adverbs
- 'd.', 'D.', 'D:', 'H.', 'L:', 'S:', 'T.', //conj
- 'a.', 'a:', //nouns
- ),
- //Primitives beginning with symbol . or :
- 8 => array(
- '..', '.:', '.', ':.', '::', ':', //conj
- ),
-*/
),
'SYMBOLS' => array(
//Punctuation
@@ -132,17 +94,17 @@ Commented out for now due to conflicts with Lang Check
GESHI_COMMENTS => false,
1 => true,
2 => true,
-// 6 => true,
-// 7 => true,
-// 8 => true,
+ //6 => true,
+ //7 => true,
+ //8 => true,
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #0000ff; font-weight: bold;',
2 => 'color: #0000cc; font-weight: bold;',
-// 6 => 'color: #000000; font-weight: bold;',
-// 7 => 'color: #000000; font-weight: bold;',
-// 8 => 'color: #000000; font-weight: bold;',
+ //6 => 'color: #000000; font-weight: bold;',
+ //7 => 'color: #000000; font-weight: bold;',
+ //8 => 'color: #000000; font-weight: bold;',
),
'COMMENTS' => array(
1 => 'color: #666666; font-style: italic;',
@@ -171,7 +133,6 @@ Commented out for now due to conflicts with Lang Check
),
'REGEXPS' => array(
0 => 'color: #0000ff; font-weight: bold;', //for_xyz. - same as kw1
- 1 => 'color: #009999; font-weight: bold;' //infinity - same as nu0
),
'SCRIPT' => array(
)
@@ -179,16 +140,15 @@ Commented out for now due to conflicts with Lang Check
'URLS' => array(
1 => '', //'http://www.jsoftware.com/help/dictionary/ctrl.htm',
2 => '',
-// 6 => '', //'http://www.jsoftware.com/jwiki/Vocabulary',
-// 7 => '', //'http://www.jsoftware.com/jwiki/Vocabulary',
-// 8 => '', //'http://www.jsoftware.com/jwiki/Vocabulary',
+ //6 => '', //'http://www.jsoftware.com/jwiki/Vocabulary',
+ //7 => '', //'http://www.jsoftware.com/jwiki/Vocabulary',
+ //8 => '', //'http://www.jsoftware.com/jwiki/Vocabulary',
),
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
),
'REGEXPS' => array(
0 => '\b(for|goto|label)_[a-zA-Z]\w*\.', //for_xyz. - should be kw1
- 1 => '\b__?(?![\w\.\:])' //infinity - should be nu0
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
@@ -199,6 +159,9 @@ Commented out for now due to conflicts with Lang Check
'ENABLE_FLAGS' => array(
'BRACKETS' => GESHI_NEVER,
),
+ 'NUMBERS' => array(
+ 'PRECHECK_RX' => '#[\d_]#', // underscore is valid number
+ ),
'KEYWORDS' => array(
//Control words
2 => array(
@@ -224,4 +187,4 @@ Commented out for now due to conflicts with Lang Check
)
);
-?> \ No newline at end of file
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/java.php b/plugins/wp-syntax/geshi/geshi/java.php
index 7fcc2e87..652b8ddd 100644
--- a/plugins/wp-syntax/geshi/geshi/java.php
+++ b/plugins/wp-syntax/geshi/geshi/java.php
@@ -4,7 +4,7 @@
* --------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/10
*
* Java language file for GeSHi.
@@ -964,7 +964,7 @@ $language_data = array (
'URLS' => array(
1 => '',
2 => '',
- 3 => 'http://www.google.com/search?hl=en&amp;q=allinurl%3A{FNAMEL}+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky',
+ 3 => 'http://www.google.com/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+{FNAMEL}',
4 => ''
),
'OOLANG' => true,
diff --git a/plugins/wp-syntax/geshi/geshi/java5.php b/plugins/wp-syntax/geshi/geshi/java5.php
index b51edab5..af16bd1e 100644
--- a/plugins/wp-syntax/geshi/geshi/java5.php
+++ b/plugins/wp-syntax/geshi/geshi/java5.php
@@ -4,7 +4,7 @@
* --------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/10
*
* Java language file for GeSHi.
@@ -850,169 +850,169 @@ $language_data = array (
2 => '',
3 => '',
4 => '',
- 5 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/applet/{FNAME}.html',
- 6 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/{FNAME}.html',
- 7 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/color/{FNAME}.html',
- 8 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/datatransfer/{FNAME}.html',
- 9 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/dnd/{FNAME}.html',
- 10 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/event/{FNAME}.html',
- 11 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/font/{FNAME}.html',
- 12 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/geom/{FNAME}.html',
- 13 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/im/{FNAME}.html',
- 14 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/im/spi/{FNAME}.html',
- 15 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/image/{FNAME}.html',
- 16 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/image/renderable/{FNAME}.html',
- 17 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/awt/print/{FNAME}.html',
- 18 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/beans/{FNAME}.html',
- 19 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/beans/beancontext/{FNAME}.html',
- 20 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/io/{FNAME}.html',
- 21 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/{FNAME}.html',
- 22 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/annotation/{FNAME}.html',
- 23 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/instrument/{FNAME}.html',
- 24 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/management/{FNAME}.html',
- 25 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/ref/{FNAME}.html',
- 26 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/lang/reflect/{FNAME}.html',
- 27 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/math/{FNAME}.html',
- 28 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/net/{FNAME}.html',
- 29 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/nio/{FNAME}.html',
- 30 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/nio/channels/{FNAME}.html',
- 31 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/nio/channels/spi/{FNAME}.html',
- 32 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/nio/charset/{FNAME}.html',
- 33 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/nio/charset/spi/{FNAME}.html',
- 34 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/rmi/{FNAME}.html',
- 35 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/rmi/activation/{FNAME}.html',
- 36 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/rmi/dgc/{FNAME}.html',
- 37 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/rmi/registry/{FNAME}.html',
- 38 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/rmi/server/{FNAME}.html',
- 39 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/security/{FNAME}.html',
- 40 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/security/acl/{FNAME}.html',
- 41 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/security/cert/{FNAME}.html',
- 42 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/security/interfaces/{FNAME}.html',
- 43 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/security/spec/{FNAME}.html',
- 44 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/sql/{FNAME}.html',
- 45 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/text/{FNAME}.html',
- 46 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/{FNAME}.html',
- 47 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/concurrent/{FNAME}.html',
- 48 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/concurrent/atomic/{FNAME}.html',
- 49 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/concurrent/locks/{FNAME}.html',
- 50 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/jar/{FNAME}.html',
- 51 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/logging/{FNAME}.html',
- 52 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/prefs/{FNAME}.html',
- 53 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/regex/{FNAME}.html',
- 54 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/java/util/zip/{FNAME}.html',
- 55 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/accessibility/{FNAME}.html',
- 56 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/activity/{FNAME}.html',
- 57 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/crypto/{FNAME}.html',
- 58 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/crypto/interfaces/{FNAME}.html',
- 59 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/crypto/spec/{FNAME}.html',
- 60 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/imageio/{FNAME}.html',
- 61 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/imageio/event/{FNAME}.html',
- 62 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/imageio/metadata/{FNAME}.html',
- 63 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/imageio/plugins/bmp/{FNAME}.html',
- 64 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/imageio/plugins/jpeg/{FNAME}.html',
- 65 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/imageio/spi/{FNAME}.html',
- 66 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/imageio/stream/{FNAME}.html',
- 67 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/{FNAME}.html',
- 68 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/loading/{FNAME}.html',
- 69 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/modelmbean/{FNAME}.html',
- 70 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/monitor/{FNAME}.html',
- 71 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/openmbean/{FNAME}.html',
- 72 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/relation/{FNAME}.html',
- 73 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/remote/{FNAME}.html',
- 74 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/remote/rmi/{FNAME}.html',
- 75 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/management/timer/{FNAME}.html',
- 76 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/naming/{FNAME}.html',
- 77 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/naming/directory/{FNAME}.html',
- 78 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/naming/event/{FNAME}.html',
- 79 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/naming/ldap/{FNAME}.html',
- 80 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/naming/spi/{FNAME}.html',
- 81 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/net/{FNAME}.html',
- 82 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/net/ssl/{FNAME}.html',
- 83 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/print/{FNAME}.html',
- 84 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/print/attribute/{FNAME}.html',
- 85 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/print/attribute/standard/{FNAME}.html',
- 86 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/print/event/{FNAME}.html',
- 87 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/rmi/{FNAME}.html',
- 88 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/rmi/CORBA/{FNAME}.html',
- 89 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/rmi/ssl/{FNAME}.html',
- 90 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/security/auth/{FNAME}.html',
- 91 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/security/auth/callback/{FNAME}.html',
- 92 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/security/auth/kerberos/{FNAME}.html',
- 93 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/security/auth/login/{FNAME}.html',
- 94 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/security/auth/spi/{FNAME}.html',
- 95 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/security/auth/x500/{FNAME}.html',
- 96 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/security/sasl/{FNAME}.html',
- 97 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/sound/midi/{FNAME}.html',
- 98 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/sound/midi/spi/{FNAME}.html',
- 99 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/sound/sampled/{FNAME}.html',
- 100 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/sound/sampled/spi/{FNAME}.html',
- 101 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/sql/{FNAME}.html',
- 102 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/sql/rowset/{FNAME}.html',
- 103 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/sql/rowset/serial/{FNAME}.html',
- 104 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/sql/rowset/spi/{FNAME}.html',
- 105 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/{FNAME}.html',
- 106 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/border/{FNAME}.html',
- 107 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/colorchooser/{FNAME}.html',
- 108 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/event/{FNAME}.html',
- 109 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/filechooser/{FNAME}.html',
- 110 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/plaf/{FNAME}.html',
- 111 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/plaf/basic/{FNAME}.html',
- 112 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/plaf/metal/{FNAME}.html',
- 113 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/plaf/multi/{FNAME}.html',
- 114 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/plaf/synth/{FNAME}.html',
- 115 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/table/{FNAME}.html',
- 116 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/text/{FNAME}.html',
- 117 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/text/html/{FNAME}.html',
- 118 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/text/html/parser/{FNAME}.html',
- 119 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/text/rtf/{FNAME}.html',
- 120 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/tree/{FNAME}.html',
- 121 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/swing/undo/{FNAME}.html',
- 122 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/transaction/{FNAME}.html',
- 123 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/transaction/xa/{FNAME}.html',
- 124 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/{FNAME}.html',
- 125 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/datatype/{FNAME}.html',
- 126 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/namespace/{FNAME}.html',
- 127 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/parsers/{FNAME}.html',
- 128 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/transform/{FNAME}.html',
- 129 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/transform/dom/{FNAME}.html',
- 130 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/transform/sax/{FNAME}.html',
- 131 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/transform/stream/{FNAME}.html',
- 132 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/validation/{FNAME}.html',
- 133 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/javax/xml/xpath/{FNAME}.html',
- 134 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/ietf/jgss/{FNAME}.html',
- 135 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/CORBA/{FNAME}.html',
- 136 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/CORBA/DynAnyPackage/{FNAME}.html',
- 137 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/CORBA/TypeCodePackage/{FNAME}.html',
- 138 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/CORBA/portable/{FNAME}.html',
- 139 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/CosNaming/{FNAME}.html',
- 140 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/CosNaming/NamingContextExtPackage/{FNAME}.html',
- 141 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/CosNaming/NamingContextPackage/{FNAME}.html',
- 142 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/Dynamic/{FNAME}.html',
- 143 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/DynamicAny/{FNAME}.html',
- 144 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/DynamicAny/DynAnyFactoryPackage/{FNAME}.html',
- 145 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/DynamicAny/DynAnyPackage/{FNAME}.html',
- 146 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/IOP/{FNAME}.html',
- 147 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/IOP/CodecFactoryPackage/{FNAME}.html',
- 148 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/IOP/CodecPackage/{FNAME}.html',
- 149 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/Messaging/{FNAME}.html',
- 150 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/PortableInterceptor/{FNAME}.html',
- 151 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/PortableInterceptor/ORBInitInfoPackage/{FNAME}.html',
- 152 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/PortableServer/{FNAME}.html',
- 153 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/PortableServer/CurrentPackage/{FNAME}.html',
- 154 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/PortableServer/POAManagerPackage/{FNAME}.html',
- 155 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/PortableServer/POAPackage/{FNAME}.html',
- 156 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/PortableServer/ServantLocatorPackage/{FNAME}.html',
- 157 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/SendingContext/{FNAME}.html',
- 158 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/omg/stub/java/rmi/{FNAME}.html',
- 159 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/w3c/dom/{FNAME}.html',
- 160 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/w3c/dom/bootstrap/{FNAME}.html',
- 161 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/w3c/dom/events/{FNAME}.html',
- 162 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/w3c/dom/ls/{FNAME}.html',
- 163 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/xml/sax/{FNAME}.html',
- 164 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/xml/sax/ext/{FNAME}.html',
- 165 => 'http://java.sun.com/j2se/1%2E5%2E0/docs/api/org/xml/sax/helpers/{FNAME}.html',
+ 5 => 'http://docs.oracle.com/javase/7/docs/api/java/applet/{FNAME}.html',
+ 6 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/{FNAME}.html',
+ 7 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/color/{FNAME}.html',
+ 8 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/datatransfer/{FNAME}.html',
+ 9 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/dnd/{FNAME}.html',
+ 10 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/event/{FNAME}.html',
+ 11 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/font/{FNAME}.html',
+ 12 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/geom/{FNAME}.html',
+ 13 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/im/{FNAME}.html',
+ 14 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/im/spi/{FNAME}.html',
+ 15 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/image/{FNAME}.html',
+ 16 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/image/renderable/{FNAME}.html',
+ 17 => 'http://docs.oracle.com/javase/7/docs/api/java/awt/print/{FNAME}.html',
+ 18 => 'http://docs.oracle.com/javase/7/docs/api/java/beans/{FNAME}.html',
+ 19 => 'http://docs.oracle.com/javase/7/docs/api/java/beans/beancontext/{FNAME}.html',
+ 20 => 'http://docs.oracle.com/javase/7/docs/api/java/io/{FNAME}.html',
+ 21 => 'http://docs.oracle.com/javase/7/docs/api/java/lang/{FNAME}.html',
+ 22 => 'http://docs.oracle.com/javase/7/docs/api/java/lang/annotation/{FNAME}.html',
+ 23 => 'http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/{FNAME}.html',
+ 24 => 'http://docs.oracle.com/javase/7/docs/api/java/lang/management/{FNAME}.html',
+ 25 => 'http://docs.oracle.com/javase/7/docs/api/java/lang/ref/{FNAME}.html',
+ 26 => 'http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/{FNAME}.html',
+ 27 => 'http://docs.oracle.com/javase/7/docs/api/java/math/{FNAME}.html',
+ 28 => 'http://docs.oracle.com/javase/7/docs/api/java/net/{FNAME}.html',
+ 29 => 'http://docs.oracle.com/javase/7/docs/api/java/nio/{FNAME}.html',
+ 30 => 'http://docs.oracle.com/javase/7/docs/api/java/nio/channels/{FNAME}.html',
+ 31 => 'http://docs.oracle.com/javase/7/docs/api/java/nio/channels/spi/{FNAME}.html',
+ 32 => 'http://docs.oracle.com/javase/7/docs/api/java/nio/charset/{FNAME}.html',
+ 33 => 'http://docs.oracle.com/javase/7/docs/api/java/nio/charset/spi/{FNAME}.html',
+ 34 => 'http://docs.oracle.com/javase/7/docs/api/java/rmi/{FNAME}.html',
+ 35 => 'http://docs.oracle.com/javase/7/docs/api/java/rmi/activation/{FNAME}.html',
+ 36 => 'http://docs.oracle.com/javase/7/docs/api/java/rmi/dgc/{FNAME}.html',
+ 37 => 'http://docs.oracle.com/javase/7/docs/api/java/rmi/registry/{FNAME}.html',
+ 38 => 'http://docs.oracle.com/javase/7/docs/api/java/rmi/server/{FNAME}.html',
+ 39 => 'http://docs.oracle.com/javase/7/docs/api/java/security/{FNAME}.html',
+ 40 => 'http://docs.oracle.com/javase/7/docs/api/java/security/acl/{FNAME}.html',
+ 41 => 'http://docs.oracle.com/javase/7/docs/api/java/security/cert/{FNAME}.html',
+ 42 => 'http://docs.oracle.com/javase/7/docs/api/java/security/interfaces/{FNAME}.html',
+ 43 => 'http://docs.oracle.com/javase/7/docs/api/java/security/spec/{FNAME}.html',
+ 44 => 'http://docs.oracle.com/javase/7/docs/api/java/sql/{FNAME}.html',
+ 45 => 'http://docs.oracle.com/javase/7/docs/api/java/text/{FNAME}.html',
+ 46 => 'http://docs.oracle.com/javase/7/docs/api/java/util/{FNAME}.html',
+ 47 => 'http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/{FNAME}.html',
+ 48 => 'http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/{FNAME}.html',
+ 49 => 'http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/{FNAME}.html',
+ 50 => 'http://docs.oracle.com/javase/7/docs/api/java/util/jar/{FNAME}.html',
+ 51 => 'http://docs.oracle.com/javase/7/docs/api/java/util/logging/{FNAME}.html',
+ 52 => 'http://docs.oracle.com/javase/7/docs/api/java/util/prefs/{FNAME}.html',
+ 53 => 'http://docs.oracle.com/javase/7/docs/api/java/util/regex/{FNAME}.html',
+ 54 => 'http://docs.oracle.com/javase/7/docs/api/java/util/zip/{FNAME}.html',
+ 55 => 'http://docs.oracle.com/javase/7/docs/api/javax/accessibility/{FNAME}.html',
+ 56 => 'http://docs.oracle.com/javase/7/docs/api/javax/activity/{FNAME}.html',
+ 57 => 'http://docs.oracle.com/javase/7/docs/api/javax/crypto/{FNAME}.html',
+ 58 => 'http://docs.oracle.com/javase/7/docs/api/javax/crypto/interfaces/{FNAME}.html',
+ 59 => 'http://docs.oracle.com/javase/7/docs/api/javax/crypto/spec/{FNAME}.html',
+ 60 => 'http://docs.oracle.com/javase/7/docs/api/javax/imageio/{FNAME}.html',
+ 61 => 'http://docs.oracle.com/javase/7/docs/api/javax/imageio/event/{FNAME}.html',
+ 62 => 'http://docs.oracle.com/javase/7/docs/api/javax/imageio/metadata/{FNAME}.html',
+ 63 => 'http://docs.oracle.com/javase/7/docs/api/javax/imageio/plugins/bmp/{FNAME}.html',
+ 64 => 'http://docs.oracle.com/javase/7/docs/api/javax/imageio/plugins/jpeg/{FNAME}.html',
+ 65 => 'http://docs.oracle.com/javase/7/docs/api/javax/imageio/spi/{FNAME}.html',
+ 66 => 'http://docs.oracle.com/javase/7/docs/api/javax/imageio/stream/{FNAME}.html',
+ 67 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/{FNAME}.html',
+ 68 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/loading/{FNAME}.html',
+ 69 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/modelmbean/{FNAME}.html',
+ 70 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/monitor/{FNAME}.html',
+ 71 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/openmbean/{FNAME}.html',
+ 72 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/relation/{FNAME}.html',
+ 73 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/remote/{FNAME}.html',
+ 74 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/remote/rmi/{FNAME}.html',
+ 75 => 'http://docs.oracle.com/javase/7/docs/api/javax/management/timer/{FNAME}.html',
+ 76 => 'http://docs.oracle.com/javase/7/docs/api/javax/naming/{FNAME}.html',
+ 77 => 'http://docs.oracle.com/javase/7/docs/api/javax/naming/directory/{FNAME}.html',
+ 78 => 'http://docs.oracle.com/javase/7/docs/api/javax/naming/event/{FNAME}.html',
+ 79 => 'http://docs.oracle.com/javase/7/docs/api/javax/naming/ldap/{FNAME}.html',
+ 80 => 'http://docs.oracle.com/javase/7/docs/api/javax/naming/spi/{FNAME}.html',
+ 81 => 'http://docs.oracle.com/javase/7/docs/api/javax/net/{FNAME}.html',
+ 82 => 'http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/{FNAME}.html',
+ 83 => 'http://docs.oracle.com/javase/7/docs/api/javax/print/{FNAME}.html',
+ 84 => 'http://docs.oracle.com/javase/7/docs/api/javax/print/attribute/{FNAME}.html',
+ 85 => 'http://docs.oracle.com/javase/7/docs/api/javax/print/attribute/standard/{FNAME}.html',
+ 86 => 'http://docs.oracle.com/javase/7/docs/api/javax/print/event/{FNAME}.html',
+ 87 => 'http://docs.oracle.com/javase/7/docs/api/javax/rmi/{FNAME}.html',
+ 88 => 'http://docs.oracle.com/javase/7/docs/api/javax/rmi/CORBA/{FNAME}.html',
+ 89 => 'http://docs.oracle.com/javase/7/docs/api/javax/rmi/ssl/{FNAME}.html',
+ 90 => 'http://docs.oracle.com/javase/7/docs/api/javax/security/auth/{FNAME}.html',
+ 91 => 'http://docs.oracle.com/javase/7/docs/api/javax/security/auth/callback/{FNAME}.html',
+ 92 => 'http://docs.oracle.com/javase/7/docs/api/javax/security/auth/kerberos/{FNAME}.html',
+ 93 => 'http://docs.oracle.com/javase/7/docs/api/javax/security/auth/login/{FNAME}.html',
+ 94 => 'http://docs.oracle.com/javase/7/docs/api/javax/security/auth/spi/{FNAME}.html',
+ 95 => 'http://docs.oracle.com/javase/7/docs/api/javax/security/auth/x500/{FNAME}.html',
+ 96 => 'http://docs.oracle.com/javase/7/docs/api/javax/security/sasl/{FNAME}.html',
+ 97 => 'http://docs.oracle.com/javase/7/docs/api/javax/sound/midi/{FNAME}.html',
+ 98 => 'http://docs.oracle.com/javase/7/docs/api/javax/sound/midi/spi/{FNAME}.html',
+ 99 => 'http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/{FNAME}.html',
+ 100 => 'http://docs.oracle.com/javase/7/docs/api/javax/sound/sampled/spi/{FNAME}.html',
+ 101 => 'http://docs.oracle.com/javase/7/docs/api/javax/sql/{FNAME}.html',
+ 102 => 'http://docs.oracle.com/javase/7/docs/api/javax/sql/rowset/{FNAME}.html',
+ 103 => 'http://docs.oracle.com/javase/7/docs/api/javax/sql/rowset/serial/{FNAME}.html',
+ 104 => 'http://docs.oracle.com/javase/7/docs/api/javax/sql/rowset/spi/{FNAME}.html',
+ 105 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/{FNAME}.html',
+ 106 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/border/{FNAME}.html',
+ 107 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/colorchooser/{FNAME}.html',
+ 108 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/event/{FNAME}.html',
+ 109 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/filechooser/{FNAME}.html',
+ 110 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/plaf/{FNAME}.html',
+ 111 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/plaf/basic/{FNAME}.html',
+ 112 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/plaf/metal/{FNAME}.html',
+ 113 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/plaf/multi/{FNAME}.html',
+ 114 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/plaf/synth/{FNAME}.html',
+ 115 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/table/{FNAME}.html',
+ 116 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/text/{FNAME}.html',
+ 117 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/text/html/{FNAME}.html',
+ 118 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/text/html/parser/{FNAME}.html',
+ 119 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/text/rtf/{FNAME}.html',
+ 120 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/tree/{FNAME}.html',
+ 121 => 'http://docs.oracle.com/javase/7/docs/api/javax/swing/undo/{FNAME}.html',
+ 122 => 'http://docs.oracle.com/javase/7/docs/api/javax/transaction/{FNAME}.html',
+ 123 => 'http://docs.oracle.com/javase/7/docs/api/javax/transaction/xa/{FNAME}.html',
+ 124 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/{FNAME}.html',
+ 125 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/datatype/{FNAME}.html',
+ 126 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/namespace/{FNAME}.html',
+ 127 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/{FNAME}.html',
+ 128 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/transform/{FNAME}.html',
+ 129 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/transform/dom/{FNAME}.html',
+ 130 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/transform/sax/{FNAME}.html',
+ 131 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/transform/stream/{FNAME}.html',
+ 132 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/validation/{FNAME}.html',
+ 133 => 'http://docs.oracle.com/javase/7/docs/api/javax/xml/xpath/{FNAME}.html',
+ 134 => 'http://docs.oracle.com/javase/7/docs/api/org/ietf/jgss/{FNAME}.html',
+ 135 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/CORBA/{FNAME}.html',
+ 136 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/CORBA/DynAnyPackage/{FNAME}.html',
+ 137 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/CORBA/TypeCodePackage/{FNAME}.html',
+ 138 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/CORBA/portable/{FNAME}.html',
+ 139 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/CosNaming/{FNAME}.html',
+ 140 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/CosNaming/NamingContextExtPackage/{FNAME}.html',
+ 141 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/CosNaming/NamingContextPackage/{FNAME}.html',
+ 142 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/Dynamic/{FNAME}.html',
+ 143 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/DynamicAny/{FNAME}.html',
+ 144 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/DynamicAny/DynAnyFactoryPackage/{FNAME}.html',
+ 145 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/DynamicAny/DynAnyPackage/{FNAME}.html',
+ 146 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/IOP/{FNAME}.html',
+ 147 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/IOP/CodecFactoryPackage/{FNAME}.html',
+ 148 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/IOP/CodecPackage/{FNAME}.html',
+ 149 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/Messaging/{FNAME}.html',
+ 150 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/PortableInterceptor/{FNAME}.html',
+ 151 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/PortableInterceptor/ORBInitInfoPackage/{FNAME}.html',
+ 152 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/PortableServer/{FNAME}.html',
+ 153 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/PortableServer/CurrentPackage/{FNAME}.html',
+ 154 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/PortableServer/POAManagerPackage/{FNAME}.html',
+ 155 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/PortableServer/POAPackage/{FNAME}.html',
+ 156 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/PortableServer/ServantLocatorPackage/{FNAME}.html',
+ 157 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/SendingContext/{FNAME}.html',
+ 158 => 'http://docs.oracle.com/javase/7/docs/api/org/omg/stub/java/rmi/{FNAME}.html',
+ 159 => 'http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/{FNAME}.html',
+ 160 => 'http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/bootstrap/{FNAME}.html',
+ 161 => 'http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/events/{FNAME}.html',
+ 162 => 'http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/{FNAME}.html',
+ 163 => 'http://docs.oracle.com/javase/7/docs/api/org/xml/sax/{FNAME}.html',
+ 164 => 'http://docs.oracle.com/javase/7/docs/api/org/xml/sax/ext/{FNAME}.html',
+ 165 => 'http://docs.oracle.com/javase/7/docs/api/org/xml/sax/helpers/{FNAME}.html',
/* ambiguous class names (appear in more than one package) */
- 166 => 'http://www.google.com/search?sitesearch=java.sun.com&amp;q=allinurl%3Aj2se%2F1+5+0%2Fdocs%2Fapi+{FNAME}'
+ 166 => 'http://www.google.com/search?sitesearch=docs.oracle.com&amp;q=allinurl%3Ajavase+docs+api+{FNAME}'
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
@@ -1034,4 +1034,4 @@ $language_data = array (
)
);
-?> \ No newline at end of file
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/javascript.php b/plugins/wp-syntax/geshi/geshi/javascript.php
index f250e50c..b96d1b5b 100644
--- a/plugins/wp-syntax/geshi/geshi/javascript.php
+++ b/plugins/wp-syntax/geshi/geshi/javascript.php
@@ -4,13 +4,15 @@
* --------------
* Author: Ben Keen (ben.keen@gmail.com)
* Copyright: (c) 2004 Ben Keen (ben.keen@gmail.com), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/20
*
* JavaScript language file for GeSHi.
*
* CHANGES
* -------
+ * 2012/06/27 (1.0.8.11)
+ * - Reordered Keyword Groups to reflect syntactical meaning of keywords
* 2008/05/23 (1.0.7.22)
* - Added description of extra language features (SF#1970248)
* 2004/11/27 (1.0.1)
@@ -45,30 +47,47 @@ $language_data = array (
'LANG_NAME' => 'Javascript',
'COMMENT_SINGLE' => array(1 => '//'),
'COMMENT_MULTI' => array('/*' => '*/'),
- //Regular Expressions
- 'COMMENT_REGEXP' => array(2 => "/(?<=[\\s^])s\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[gimsu]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])m?\\/(?:\\\\.|(?!\n)[^\\/\\\\])+\\/[gimsu]*(?=[\\s$\\.\\,\\;\\)])/iU"),
+ 'COMMENT_REGEXP' => array(
+ //Regular Expressions
+ 2 => "/(?<=[\\s^])(s|tr|y)\\/(?!\*)(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])+(?<!\s)\\/(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])*(?<!\s)\\/[msixpogcde]*(?=[\\s$\\.\\;])|(?<=[\\s^(=])(m|q[qrwx]?)?\\/(?!\*)(?!\s)(?:\\\\.|(?!\n)[^\\/\\\\])+(?<!\s)\\/[msixpogc]*(?=[\\s$\\.\\,\\;\\)])/iU"
+ ),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '\\',
'KEYWORDS' => array(
1 => array(
- 'as', 'break', 'case', 'catch', 'continue', 'decodeURI', 'delete', 'do',
- 'else', 'encodeURI', 'eval', 'finally', 'for', 'if', 'in', 'is', 'item',
- 'instanceof', 'return', 'switch', 'this', 'throw', 'try', 'typeof', 'void',
- 'while', 'write', 'with'
+ //reserved/keywords; also some non-reserved keywords
+ 'break','case','catch','const','continue',
+ 'default','delete','do',
+ 'else',
+ 'finally','for','function',
+ 'get','goto',
+ 'if','in','instanceof',
+ 'new',
+ 'prototype',
+ 'return',
+ 'set','static','switch',
+ 'this','throw','try','typeof',
+ 'var','void'
),
2 => array(
- 'class', 'const', 'default', 'debugger', 'export', 'extends', 'false',
- 'function', 'import', 'namespace', 'new', 'null', 'package', 'private',
- 'protected', 'public', 'super', 'true', 'use', 'var'
+ //reserved/non-keywords; metaconstants
+ 'false','null','true','undefined','NaN','Infinity'
),
3 => array(
- // common functions for Window object
- 'alert', 'back', 'blur', 'close', 'confirm', 'focus', 'forward', 'home',
- 'name', 'navigate', 'onblur', 'onerror', 'onfocus', 'onload', 'onmove',
- 'onresize', 'onunload', 'open', 'print', 'prompt', 'scroll', 'status',
- 'stop',
- )
+ //magic properties/functions
+ '__proto__','__defineGetter__','__defineSetter__','hasOwnProperty','hasProperty'
+ ),
+ 4 => array(
+ //type constructors
+ 'Object', 'Function', 'Date', 'Math', 'String', 'Number', 'Boolean', 'Array'
+ ),
+ 5 => array(
+ //reserved, but invalid in language
+ 'abstract','boolean','byte','char','class','debugger','double','enum','export','extends',
+ 'final','float','implements','import','int','interface','long','native',
+ 'short','super','synchronized','throws','transient','volatile'
+ ),
),
'SYMBOLS' => array(
'(', ')', '[', ']', '{', '}',
@@ -79,15 +98,18 @@ $language_data = array (
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
- 1 => false,
- 2 => false,
- 3 => false
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ 5 => true
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #000066; font-weight: bold;',
2 => 'color: #003366; font-weight: bold;',
- 3 => 'color: #000066;'
+ 3 => 'color: #000066;',
+ 5 => 'color: #FF0000;'
),
'COMMENTS' => array(
1 => 'color: #006600; font-style: italic;',
@@ -124,8 +146,10 @@ $language_data = array (
'URLS' => array(
1 => '',
2 => '',
- 3 => ''
- ),
+ 3 => '',
+ 4 => '',
+ 5 => ''
+ ),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
1 => '.'
@@ -147,4 +171,4 @@ $language_data = array (
)
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/jquery.php b/plugins/wp-syntax/geshi/geshi/jquery.php
index bd7cd5c3..a75320d5 100644
--- a/plugins/wp-syntax/geshi/geshi/jquery.php
+++ b/plugins/wp-syntax/geshi/geshi/jquery.php
@@ -4,7 +4,7 @@
* --------------
* Author: Rob Loach (http://www.robloach.net)
* Copyright: (c) 2009 Rob Loach (http://www.robloach.net)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/07/20
*
* jQuery 1.3 language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/kixtart.php b/plugins/wp-syntax/geshi/geshi/kixtart.php
index e2d71746..5b909198 100644
--- a/plugins/wp-syntax/geshi/geshi/kixtart.php
+++ b/plugins/wp-syntax/geshi/geshi/kixtart.php
@@ -4,7 +4,7 @@
* --------
* Author: Riley McArdle (riley@glyff.net)
* Copyright: (c) 2007 Riley McArdle (http://www.glyff.net/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/08/31
*
* PHP language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/klonec.php b/plugins/wp-syntax/geshi/geshi/klonec.php
index 9a33499b..5f86e78d 100644
--- a/plugins/wp-syntax/geshi/geshi/klonec.php
+++ b/plugins/wp-syntax/geshi/geshi/klonec.php
@@ -4,7 +4,7 @@
* --------
* Author: AUGER Mickael
* Copyright: Synchronic
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/04/16
*
* KLone with C language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/klonecpp.php b/plugins/wp-syntax/geshi/geshi/klonecpp.php
index 9018b781..6564c6b7 100644
--- a/plugins/wp-syntax/geshi/geshi/klonecpp.php
+++ b/plugins/wp-syntax/geshi/geshi/klonecpp.php
@@ -4,7 +4,7 @@
* --------
* Author: AUGER Mickael
* Copyright: Synchronic
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/04/16
*
* KLone with C++ language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/latex.php b/plugins/wp-syntax/geshi/geshi/latex.php
index 51ca73fe..386a0b98 100644
--- a/plugins/wp-syntax/geshi/geshi/latex.php
+++ b/plugins/wp-syntax/geshi/geshi/latex.php
@@ -4,7 +4,7 @@
* -----
* Author: efi, Matthias Pospiech (matthias@pospiech.eu)
* Copyright: (c) 2006 efi, Matthias Pospiech (matthias@pospiech.eu), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/09/23
*
* LaTeX language file for GeSHi.
@@ -67,7 +67,7 @@ $language_data = array (
'colorbox','date','dedication','def','definecolor','documentclass',
'edef','else','email','emph','eqref','extratitle','fbox','fi',
'flushleft','flushright','footnote','frac','frontmatter',
- 'graphicspath','hfill','hline','hspace','huge','ifx','include',
+ 'graphicspath','hfil','hfill','hfilll','hline','hspace','huge','ifx','include',
'includegraphics','infty','input','int','item','itemsep',
'KOMAoption','KOMAoptions','label','LaTeX','left','let','limits',
'listfiles','listoffigures','listoftables','lowertitleback',
@@ -81,7 +81,7 @@ $language_data = array (
'table','tableofcontents','textbf','textcolor','textit',
'textnormal','textsuperscript','texttt','textwidth','thanks','title',
'titlehead','today','ttfamily','uppertitleback','urlstyle',
- 'usepackage','vspace'
+ 'usepackage','vfil','vfill','vfilll','vspace'
)
),
'SYMBOLS' => array(
@@ -185,7 +185,7 @@ $language_data = array (
8 => "\\\\(?:end|begin)(?=[^a-zA-Z])",
// {parameters}
9 => array(
- GESHI_SEARCH => "(?<=\\{)(?!<\|!REG3XP5!>).*(?=\\})",
+ GESHI_SEARCH => "(?<=\\{)(?!<\|!REG3XP5!>).*?(?=\\})",
GESHI_REPLACE => '\0',
GESHI_MODIFIERS => 'Us',
GESHI_BEFORE => '',
diff --git a/plugins/wp-syntax/geshi/geshi/lb.php b/plugins/wp-syntax/geshi/geshi/lb.php
index 6c93268a..6c288289 100644
--- a/plugins/wp-syntax/geshi/geshi/lb.php
+++ b/plugins/wp-syntax/geshi/geshi/lb.php
@@ -4,7 +4,7 @@
* --------
* Author: Chris Iverson (cj.no.one@gmail.com)
* Copyright: (c) 2010 Chris Iverson
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/07/18
*
* Liberty BASIC language file for GeSHi.
@@ -14,7 +14,10 @@
* 2010/07/22
* - First Release
*
- * TODO (updated 2010/07/22)
+ * 2010/08/23
+ * - Added missing default variables
+ *
+ * TODO (updated 2010/07/20)
* -------------------------
* Prevent highlighting numbers in handle names(constants beginning with #)
* Allow number highlighting after a single period(e.g. .9 = 0.9, should be
@@ -80,12 +83,13 @@ $language_data = array(
'winstring', 'word$'
),
3 => array(
- 'BackgroundColor$', 'ComboboxColor$', 'CommandLine$', 'DefaultDir$',
+ 'BackgroundColor$', 'Com', 'ComboboxColor$', 'ComError', 'ComErrorNumber',
+ 'CommandLine$', 'ComPortNumber', 'DefaultDir$',
'DisplayHeight', 'DisplayWidth', 'Drives$', 'Err', 'Err$',
'ForegroundColor$', 'Inkey$', 'Joy1x', 'Joy1y', 'Joy1z',
'Joy1button1', 'Joy1button2', 'Joy2x', 'Joy2y', 'Joy2z',
- 'Joy2button1', 'Joy2button2', 'ListboxColor$', 'Platform$',
- 'PrintCollate', 'PrintCopies', 'PrinterFont$', 'PrinterName$',
+ 'Joy2button1', 'Joy2button2', 'ListboxColor$', 'MouseX', 'MouseY', 'Platform$',
+ 'PrintCollate', 'PrintCopies', 'PrinterFont$', 'PrinterName$', 'StartupDir$',
'TextboxColor$', 'TexteditorColor$', 'Version$', 'WindowHeight',
'WindowWidth', 'UpperLeftX', 'UpperLeftY'
)
@@ -150,9 +154,9 @@ $language_data = array(
//and their names should not be highlighted unless being used
//as a function name.
'DISALLOWED_AFTER' => '(?=\s*\()'
+ )
)
)
- )
);
?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/ldif.php b/plugins/wp-syntax/geshi/geshi/ldif.php
new file mode 100644
index 00000000..42481838
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/ldif.php
@@ -0,0 +1,116 @@
+<?php
+/*************************************************************************************
+ * ldif.php
+ * --------
+ * Author: Bruno Harbulot (Bruno.Harbulot@manchester.ac.uk)
+ * Copyright: (c) 2005 deguix, (c) 2010 Bruno Harbulot
+ * Release Version: 1.0.8.11
+ * Date Started: 2010/03/01
+ *
+ * LDIF language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2010/03/01 (1.0.8.11)
+ * - First Release
+ * - Derived from ini.php (INI language), (c) 2005 deguix
+ *
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'LDIF',
+ 'COMMENT_SINGLE' => array(1 => '#'),
+ 'COMMENT_MULTI' => array(),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array(),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ ),
+ 'SYMBOLS' => array(
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => ''
+ ),
+ 'BRACKETS' => array(
+ 0 => ''
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #933;'
+ ),
+ 'NUMBERS' => array(
+ 0 => ''
+ ),
+ 'METHODS' => array(
+ 0 => ''
+ ),
+ 'SYMBOLS' => array(
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color: #000066; font-weight: bold;',
+ 1 => 'color: #FF0000;'
+ ),
+ 'SCRIPT' => array(
+ 0 => ''
+ )
+ ),
+ 'URLS' => array(
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ 0 => array(
+ GESHI_SEARCH => '([a-zA-Z0-9_]+):(.+)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ':\\2'
+ ),
+ 1 => array(
+ // Evil hackery to get around GeSHi bug: <>" and ; are added so <span>s can be matched
+ // Explicit match on variable names because if a comment is before the first < of the span
+ // gets chewed up...
+ GESHI_SEARCH => '([<>";a-zA-Z0-9_]+):(.+)',
+ GESHI_REPLACE => '\\2',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '\\1:',
+ GESHI_AFTER => ''
+ )
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/lisp.php b/plugins/wp-syntax/geshi/geshi/lisp.php
index c80ce23e..be823a40 100644
--- a/plugins/wp-syntax/geshi/geshi/lisp.php
+++ b/plugins/wp-syntax/geshi/geshi/lisp.php
@@ -4,7 +4,7 @@
* --------
* Author: Roberto Rossi (rsoftware@altervista.org)
* Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/30
*
* Generic Lisp language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/llvm.php b/plugins/wp-syntax/geshi/geshi/llvm.php
new file mode 100644
index 00000000..580099b5
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/llvm.php
@@ -0,0 +1,385 @@
+<?php
+/*************************************************************************************
+ * llvm.php
+ * --------
+ * Author: Benny Baumann (BenBE@geshi.org), Azriel Fasten (azriel.fasten@gmail.com)
+ * Copyright: (c) 2010 Benny Baumann (http://qbnz.com/highlighter/), Azriel Fasten (azriel.fasten@gmail.com)
+ * Release Version: 1.0.8.11
+ * Date Started: 2010/10/14
+ *
+ * LLVM language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2010/10/14 (1.0.8.10)
+ * - First Release
+ *
+ * TODO (updated 2010/10/14)
+ * -------------------------
+ * * Check if all links aren't broken
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+ 'LANG_NAME' => 'LLVM Intermediate Representation',
+ 'COMMENT_SINGLE' => array(1 => ';'),
+ 'COMMENT_MULTI' => array(),
+ 'HARDQUOTE' => array("\"", "\""),
+ 'HARDESCAPE' => array("\"", "\\"),
+ 'HARDCHAR' => "\\",
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"'),
+ 'ESCAPE_CHAR' => '',
+ 'ESCAPE_REGEXP' => array(
+ //Simple Single Char Escapes
+ // 1 => "#\\\\[nfrtv\$\"\n\\\\]#i",
+ //Hexadecimal Char Specs
+ // 2 => "#\\\\x[\da-fA-F]{1,2}#i",
+ //Octal Char Specs
+ // 3 => "#\\\\[0-7]{1,3}#",
+ //String Parsing of Variable Names
+ // 4 => "#\\$[a-z0-9_]+(?:\\[[a-z0-9_]+\\]|->[a-z0-9_]+)?|(?:\\{\\$|\\$\\{)[a-z0-9_]+(?:\\[('?)[a-z0-9_]*\\1\\]|->[a-z0-9_]+)*\\}#i",
+ //Experimental extension supporting cascaded {${$var}} syntax
+ // 5 => "#\$[a-z0-9_]+(?:\[[a-z0-9_]+\]|->[a-z0-9_]+)?|(?:\{\$|\$\{)[a-z0-9_]+(?:\[('?)[a-z0-9_]*\\1\]|->[a-z0-9_]+)*\}|\{\$(?R)\}#i",
+ //Format String support in ""-Strings
+ // 6 => "#%(?:%|(?:\d+\\\\\\\$)?\\+?(?:\x20|0|'.)?-?(?:\d+|\\*)?(?:\.\d+)?[bcdefFosuxX])#"
+ ),
+ 'NUMBERS' =>
+ GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_SCI_ZERO,
+ 'KEYWORDS' => array(
+ 0 => array(
+ 'to', 'nuw', 'nsw', 'align', 'inbounds', 'entry', 'return'
+ ),
+ //Terminator Instructions
+ 1 => array(
+ 'ret', 'br', 'switch', 'indirectbr', 'invoke', 'unwind', 'unreachable'
+ ),
+ //Binary Operations
+ 2 => array(
+ 'add', 'fadd', 'sub', 'fsub', 'mul', 'fmul', 'udiv', 'sdiv', 'fdiv', 'urem', 'frem', 'srem'
+ ),
+ //Bitwise Binary Operations
+ 3 => array(
+ 'shl', 'lshr', 'ashr', 'and', 'or', 'xor'
+ ),
+ //Vector Operations
+ 4 => array(
+ 'extractelement', 'insertelement', 'shufflevector'
+ ),
+ //Aggregate Operations
+ 5 => array(
+ 'extractvalue', 'insertvalue'
+ ),
+ //Memory Access and Addressing Operations
+ 6 => array(
+ 'alloca', 'load', 'store', 'getelementptr'
+ ),
+ //Conversion Operations
+ 7 => array(
+ 'trunc', 'zext', 'sext', 'fptrunc', 'fpext', 'fptoui', 'fptosi',
+ 'uitofp', 'sitofp', 'ptrtoint', 'inttoptr', 'bitcast'
+ ),
+ //Other Operations
+ 8 => array(
+ 'icmp', 'fcmp', 'phi', 'select', 'call', 'va_arg'
+ ),
+ //Linkage Types
+ 9 => array(
+ 'private', 'linker_private', 'linker_private_weak', 'linker_private_weak_def_auto',
+ 'internal', 'available_externally', 'linkonce', 'common', 'weak', 'appending',
+ 'extern_weak', 'linkonce_odr', 'weak_odr', 'externally visible', 'dllimport', 'dllexport',
+ ),
+ //Calling Conventions
+ 10 => array(
+ 'ccc', 'fastcc', 'coldcc', 'cc 10'
+ ),
+ //Named Types
+ 11 => array(
+ 'type'
+ ),
+ //Parameter Attributes
+ 12 => array(
+ 'zeroext', 'signext', 'inreg', 'byval', 'sret', 'noalias', 'nocapture', 'nest'
+ ),
+ //Function Attributes
+ 13 => array(
+ 'alignstack', 'alwaysinline', 'inlinehint', 'naked', 'noimplicitfloat', 'noinline', 'noredzone', 'noreturn',
+ 'nounwind', 'optsize', 'readnone', 'readonly', 'ssp', 'sspreq',
+ ),
+ //Module-Level Inline Assembly
+ 14 => array(
+ 'module asm'
+ ),
+ //Data Layout
+ 15 => array(
+ 'target datalayout'
+ ),
+ //Primitive Types
+ 16 => array(
+ 'x86mmx',
+ 'void',
+ 'label',
+ 'metadata',
+ 'opaque'
+ ),
+ //Floating Point Types
+ 17 => array(
+ 'float', 'double', 'fp128', 'x86_fp80', 'ppc_fp128',
+ ),
+ //Simple Constants
+ 18 => array(
+ 'false', 'true', 'null'
+ ),
+ //Global Variable and Function Addresses
+ 19 => array(
+ 'global', 'addrspace', 'constant', 'section'
+ ),
+ //Functions
+ 20 => array(
+ 'declare', 'define'
+ ),
+ //Complex Constants
+ 21 => array(
+ 'zeroinitializer'
+ ),
+ //Undefined Values
+ 22 => array(
+ 'undef'
+ ),
+ //Addresses of Basic Blocks
+ 23 => array(
+ 'blockaddress'
+ ),
+ //Visibility Styles
+ 24 => array(
+ 'default', 'hidden', 'protected'
+ ),
+ 25 => array(
+ 'volatile'
+ ),
+ 26 => array(
+ 'tail'
+ ),
+ ),
+ 'SYMBOLS' => array(
+ 0 => array(
+ '(', ')', '[', ']', '{', '}',
+ '!', '@', '%', '&', '|', '/',
+ '<', '>',
+ '=', '-', '+', '*',
+ '.', ':', ',', ';'
+ )
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ 5 => true,
+ 6 => true,
+ 7 => true,
+ 8 => true,
+ 9 => true,
+ 10 => true,
+ 11 => true,
+ 12 => true,
+ 13 => true,
+ 14 => true,
+ 15 => true,
+ 16 => true,
+ 17 => true,
+ 18 => true,
+ 19 => true,
+ 20 => true,
+ 21 => true,
+ 22 => true,
+ 23 => true,
+ 24 => true,
+ 25 => true,
+ 26 => true,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 0 => 'color: #209090;',
+ 1 => 'color: #0000F0;',
+ 2 => 'color: #00F000; font-weight: bold;',
+ 3 => 'color: #F00000;',
+ 4 => 'color: #00F0F0; font-weight: bold;',
+ 5 => 'color: #F000F0; font-weight: bold;',
+ 6 => 'color: #403020; font-weight: bold;',
+ 7 => 'color: #909090; font-weight: bold;',
+ 8 => 'color: #009090; font-weight: bold;',
+ 9 => 'color: #900090; font-weight: bold;',
+ 10 => 'color: #909000; font-weight: bold;',
+ 11 => 'color: #000090; font-weight: bold;',
+ 12 => 'color: #900000; font-weight: bold;',
+ 13 => 'color: #009000; font-weight: bold;',
+ 14 => 'color: #F0F090; font-weight: bold;',
+ 15 => 'color: #F090F0; font-weight: bold;',
+ 16 => 'color: #90F0F0; font-weight: bold;',
+ 17 => 'color: #9090F0; font-weight: bold;',
+ 18 => 'color: #90F090; font-weight: bold;',
+ 19 => 'color: #F09090; font-weight: bold;',
+ 20 => 'color: #4040F0; font-weight: bold;',
+ 21 => 'color: #40F040; font-weight: bold;',
+ 22 => 'color: #F04040; font-weight: bold;',
+ 23 => 'color: #F0F040; font-weight: bold;',
+ 24 => 'color: #F040F0; font-weight: bold;',
+ 25 => 'color: #40F0F0; font-weight: bold;',
+ 26 => 'color: #904040; font-weight: bold;',
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666; font-style: italic;',
+ 'MULTI' => 'color: #666666; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;',
+ 1 => 'color: #000099; font-weight: bold;',
+ 2 => 'color: #660099; font-weight: bold;',
+ 3 => 'color: #660099; font-weight: bold;',
+ 4 => 'color: #006699; font-weight: bold;',
+ 5 => 'color: #006699; font-weight: bold; font-style: italic;',
+ 6 => 'color: #009933; font-weight: bold;',
+ 'HARD' => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #009900;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #0000ff;',
+ 'HARD' => 'color: #0000ff;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;',
+ GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+ GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+ GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #004000;',
+ 2 => 'color: #004000;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #339933;',
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color: #007088;',
+ 1 => 'color: #007088;',
+ // 2 => 'color: #000088;',
+ 3 => 'color: #700088;',
+ 4 => 'color: #010088;',
+ // 5 => 'color: #610088;',
+ // 6 => 'color: #616088;',
+ // 7 => 'color: #616988;',
+ // 8 => 'color: #616908;',
+ 9 => 'color: #6109F8;',
+ ),
+ 'SCRIPT' => array(
+ 0 => '',
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => ''
+ )
+ ),
+ 'URLS' => array(
+ 0 => '',
+ 1 => 'http://llvm.org/docs/LangRef.html#i_{FNAME}',
+ 2 => 'http://llvm.org/docs/LangRef.html#i_{FNAME}',
+ 3 => 'http://llvm.org/docs/LangRef.html#i_{FNAME}',
+ 4 => 'http://llvm.org/docs/LangRef.html#i_{FNAME}',
+ 5 => 'http://llvm.org/docs/LangRef.html#i_{FNAME}',
+ 6 => 'http://llvm.org/docs/LangRef.html#i_{FNAME}',
+ 7 => 'http://llvm.org/docs/LangRef.html#i_{FNAME}',
+ 8 => 'http://llvm.org/docs/LangRef.html#i_{FNAME}',
+ 9 => 'http://llvm.org/docs/LangRef.html#linkage_{FNAME}',
+ 10 => 'http://llvm.org/docs/LangRef.html#callingconv',
+ 11 => 'http://llvm.org/docs/LangRef.html#namedtypes',
+ 12 => 'http://llvm.org/docs/LangRef.html#paramattrs',
+ 13 => 'http://llvm.org/docs/LangRef.html#fnattrs',
+ 14 => 'http://llvm.org/docs/LangRef.html#moduleasm',
+ 15 => 'http://llvm.org/docs/LangRef.html#datalayout',
+ 16 => 'http://llvm.org/docs/LangRef.html#t_{FNAME}',
+ 17 => 'http://llvm.org/docs/LangRef.html#t_floating',
+ 18 => 'http://llvm.org/docs/LangRef.html#simpleconstants',
+ 19 => 'http://llvm.org/docs/LangRef.html#globalvars',
+ 20 => 'http://llvm.org/docs/LangRef.html#functionstructure',
+ 21 => 'http://llvm.org/docs/LangRef.html#complexconstants',
+ 22 => 'http://llvm.org/docs/LangRef.html#undefvalues',
+ 23 => 'http://llvm.org/docs/LangRef.html#blockaddress',
+ 24 => 'http://llvm.org/docs/LangRef.html#visibility',
+ 25 => 'http://llvm.org/docs/LangRef.html#volatile',
+ 26 => 'http://llvm.org/docs/LangRef.html#i_call',
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ //Variables
+ 0 => '%[-a-zA-Z$\._][-a-zA-Z$\._0-9]*',
+ //Labels
+ // 1 => '[-a-zA-Z$\._0-9]+:',
+ 1 => '(?<!\w)[\-\w\$\.]+:(?![^">]*<)',
+ //Strings
+ // 2 => '"[^"]+"',
+ //Unnamed variable slots
+ 3 => '%[-]?[0-9]+',
+ //Integer Types
+ 4 => array(
+ GESHI_SEARCH => '(?<!\w)i\d+(?!\w)',
+ GESHI_REPLACE => '\\0',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '<a href="http://llvm.org/docs/LangRef.html#t_integer">',
+ GESHI_AFTER => '</a>'
+ ),
+ //Comments
+ // 5 => ';.*',
+ //Integer literals
+ // 6 => '\\b[-]?[0-9]+\\b',
+ //Floating point constants
+ // 7 => '\\b[-+]?[0-9]+\.[0-9]*\([eE][-+]?[0-9]+\)?\\b',
+ //Hex constants
+ // 8 => '\\b0x[0-9A-Fa-f]+\\b',
+ //Global variables
+ 9 => array(
+ GESHI_SEARCH => '@[-a-zA-Z$\._][-a-zA-Z$\._0-9]*',
+ GESHI_REPLACE => '\\0',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '<a href="http://llvm.org/docs/LangRef.html#globalvars">',
+ GESHI_AFTER => '</a>'
+ ),
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ 0 => true,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ 5 => true
+ ),
+ 'SCRIPT_DELIMITERS' => array(),
+ 'TAB_WIDTH' => 4
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/locobasic.php b/plugins/wp-syntax/geshi/geshi/locobasic.php
index 1bc88c8b..61c8a3c8 100644
--- a/plugins/wp-syntax/geshi/geshi/locobasic.php
+++ b/plugins/wp-syntax/geshi/geshi/locobasic.php
@@ -4,7 +4,7 @@
* -------------
* Author: Nacho Cabanes
* Copyright: (c) 2009 Nacho Cabanes (http://www.nachocabanes.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/03/22
*
* Locomotive Basic (Amstrad CPC series) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/logtalk.php b/plugins/wp-syntax/geshi/geshi/logtalk.php
index 90355ff0..05734663 100644
--- a/plugins/wp-syntax/geshi/geshi/logtalk.php
+++ b/plugins/wp-syntax/geshi/geshi/logtalk.php
@@ -4,14 +4,25 @@
* -----------
*
* Author: Paulo Moura (pmoura@logtalk.org)
- * Copyright: (c) 2009 Paulo Moura (http://logtalk.org/)
- * Release Version: 1.0.8.9
+ * Copyright: (c) 2009-2011 Paulo Moura (http://logtalk.org/)
+ * Release Version: 1.0.8.11
* Date Started: 2009/10/24
*
* Logtalk language file for GeSHi.
*
* CHANGES
* -------
+ * 2011/01/18 (1.1.4)
+ * - Added syntax coloring of ignore/1
+ * 2010/11/28 (1.1.3)
+ * - Added syntax coloring of conforms_to_protocol/2-3
+ * 2010/09/14 (1.1.2)
+ * - Added syntax coloring of coinductive/1
+ * 2010/06/23 (1.1.1)
+ * - Added syntax coloring of e/0 and pi/0
+ * - Added syntax coloring of ground/1, numbervars/3, keysort/2, and sort/2
+ * 2010/05/15 (1.1.0)
+ * - Added syntax coloring of callable/1 and compare/3
* 2009/10/28 (1.0.0)
* - First Release
*
@@ -76,7 +87,7 @@ $language_data = array(
// entity directives
'calls', 'initialization', 'op', 'uses',
// predicate directives
- 'alias', 'discontiguous', 'dynamic', 'mode', 'info', 'meta_predicate', 'multifile', 'synchronized',
+ 'alias', 'coinductive', 'discontiguous', 'dynamic', 'mode', 'info', 'meta_predicate', 'multifile', 'synchronized',
// module directives
'export', 'module', 'reexport', 'use_module'
),
@@ -111,7 +122,7 @@ $language_data = array(
'current_category', 'current_object', 'current_protocol',
'category_property', 'object_property', 'protocol_property',
// entity relations
- 'complements_object',
+ 'complements_object', 'conforms_to_protocol',
'extends_category', 'extends_object', 'extends_protocol',
'implements_protocol', 'imports_category',
'instantiates_class', 'specializes_class',
@@ -125,7 +136,7 @@ $language_data = array(
// database
'abolish', 'asserta', 'assertz', 'clause', 'retract', 'retractall',
// control
- 'call', 'catch', 'once', 'throw',
+ 'call', 'catch', 'ignore', 'once', 'throw',
// all solutions predicates
'bagof', 'findall', 'forall', 'setof',
// multi-threading meta-predicates
@@ -139,9 +150,11 @@ $language_data = array(
'number_chars', 'number_codes',
'char_code',
// term creation and decomposition
- 'arg', 'copy_term', 'functor',
+ 'arg', 'copy_term', 'functor', 'numbervars',
// term testing
- 'atom', 'atomic', 'compound', 'float', 'integer', 'nonvar', 'number', 'sub_atom', 'var',
+ 'atom', 'atomic', 'callable', 'compound', 'float', 'ground', 'integer', 'nonvar', 'number', 'sub_atom', 'var',
+ // term comparison
+ 'compare',
// stream selection and control
'current_input', 'current_output', 'set_input', 'set_output',
'open', 'close', 'flush_output', 'stream_property',
@@ -156,8 +169,10 @@ $language_data = array(
'write', 'writeq', 'write_canonical', 'write_term',
'read', 'read_term',
'char_conversion', 'current_char_conversion',
- //
- 'halt'
+ // hooks
+ 'halt',
+ // sorting
+ 'keysort', 'sort'
),
// Built-in predicates (no arguments)
5 => array(
@@ -180,7 +195,7 @@ $language_data = array(
),
// Evaluable functors (no arguments)
7 => array(
- 'mod', 'rem'
+ 'e', 'pi', 'mod', 'rem'
),
),
'SYMBOLS' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/lolcode.php b/plugins/wp-syntax/geshi/geshi/lolcode.php
index f161ff3e..ab6088b1 100644
--- a/plugins/wp-syntax/geshi/geshi/lolcode.php
+++ b/plugins/wp-syntax/geshi/geshi/lolcode.php
@@ -4,7 +4,7 @@
* ----------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/10/31
*
* LOLcode language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/lotusformulas.php b/plugins/wp-syntax/geshi/geshi/lotusformulas.php
index 6542375f..12257d74 100644
--- a/plugins/wp-syntax/geshi/geshi/lotusformulas.php
+++ b/plugins/wp-syntax/geshi/geshi/lotusformulas.php
@@ -4,7 +4,7 @@
* ------------------------
* Author: Richard Civil (info@richardcivil.net)
* Copyright: (c) 2008 Richard Civil (info@richardcivil.net), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/04/12
*
* @Formula/@Command language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/lotusscript.php b/plugins/wp-syntax/geshi/geshi/lotusscript.php
index 412e6e4a..b8b65f20 100644
--- a/plugins/wp-syntax/geshi/geshi/lotusscript.php
+++ b/plugins/wp-syntax/geshi/geshi/lotusscript.php
@@ -4,7 +4,7 @@
* ------------------------
* Author: Richard Civil (info@richardcivil.net)
* Copyright: (c) 2008 Richard Civil (info@richardcivil.net), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/04/12
*
* LotusScript language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/lscript.php b/plugins/wp-syntax/geshi/geshi/lscript.php
index fb16d35c..298af618 100644
--- a/plugins/wp-syntax/geshi/geshi/lscript.php
+++ b/plugins/wp-syntax/geshi/geshi/lscript.php
@@ -4,7 +4,7 @@
* ---------
* Author: Arendedwinter (admin@arendedwinter.com)
* Copyright: (c) 2008 Beau McGuigan (http://www.arendedwinter.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 15/11/2008
*
* Lightwave Script language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/lsl2.php b/plugins/wp-syntax/geshi/geshi/lsl2.php
index 5e50d1f0..f80cf4f2 100644
--- a/plugins/wp-syntax/geshi/geshi/lsl2.php
+++ b/plugins/wp-syntax/geshi/geshi/lsl2.php
@@ -4,7 +4,7 @@
* --------
* Author: William Fry (william.fry@nyu.edu)
* Copyright: (c) 2009 William Fry
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/02/04
*
* Linden Scripting Language (LSL2) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/lua.php b/plugins/wp-syntax/geshi/geshi/lua.php
index 2d43b84d..8a09ba20 100644
--- a/plugins/wp-syntax/geshi/geshi/lua.php
+++ b/plugins/wp-syntax/geshi/geshi/lua.php
@@ -4,7 +4,7 @@
* -------
* Author: Roberto Rossi (rsoftware@altervista.org)
* Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/10
*
* LUA language file for GeSHi.
@@ -46,13 +46,29 @@ $language_data = array (
'LANG_NAME' => 'Lua',
'COMMENT_SINGLE' => array(1 => "--"),
'COMMENT_MULTI' => array('--[[' => ']]'),
+ 'COMMENT_REGEXP' => array(2 => '/\[(=*)\[.*?\]\1\]/s'),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
- 'ESCAPE_CHAR' => '\\',
+ 'ESCAPE_CHAR' => '',
+ 'ESCAPE_REGEXP' => array(
+ //Simple Single Char Escapes
+ 1 => "#\\\\[\\\\abfnrtv\'\"]#i",
+ //Octal Char Specs
+ 2 => "#\\\\\\d{1,3}#"
+ ),
+ 'NUMBERS' =>
+ GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_HEX_PREFIX |
+ GESHI_NUMBER_FLT_NONSCI | GESHI_NUMBER_FLT_NONSCI_F |
+ GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
'KEYWORDS' => array(
1 => array(
- 'and','break','do','else','elseif','end','false','for','function','if',
- 'in','local','nil','not','or','repeat','return','then','true','until','while',
+ 'break','do','else','elseif','end','for','function','if',
+ 'local','repeat','return','then','until','while'
+ ),
+ 2 => array(
+ 'and','in','not','or'
+ ),
+ 3 => array(
'_VERSION','assert','collectgarbage','dofile','error','gcinfo','loadfile','loadstring',
'print','tonumber','tostring','type','unpack',
'_ALERT','_ERRORMESSAGE','_INPUT','_PROMPT','_OUTPUT',
@@ -79,37 +95,57 @@ $language_data = array (
'os.clock','os.date','os.difftime','os.execute','os.exit','os.getenv','os.remove','os.rename',
'os.setlocale','os.time','os.tmpname',
'string','table','math','coroutine','io','os','debug'
+ ),
+ 4 => array(
+ 'nil', 'false', 'true'
+ ),
+ 5 => array(
+ 'Nil', 'Boolean', 'Number', 'String', 'Userdata', 'Thread', 'Table'
)
),
'SYMBOLS' => array(
- '(', ')', '{', '}', '!', '@', '%', '&', '*', '|', '/', '<', '>', '=', ';'
+ '+', '-', '*', '/', '%', '^', '#',
+ '==', '~=', '<=', '>=', '<', '>', '=',
+ '(', ')', '{', '}', '[', ']',
+ ';', ':', ',', '.', '..', '...'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
- 1 => true
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ 5 => true
),
'STYLES' => array(
'KEYWORDS' => array(
- 1 => 'color: #b1b100;'
+ 1 => 'color: #aa9900; font-weight: bold;',
+ 2 => 'color: #aa9900; font-weight: bold;',
+ 3 => 'color: #0000aa;',
+ 4 => 'color: #aa9900;',
+ 5 => 'color: #aa9900;'
),
'COMMENTS' => array(
1 => 'color: #808080; font-style: italic;',
+ 2 => 'color: #ff0000;',
'MULTI' => 'color: #808080; font-style: italic;'
),
'ESCAPE_CHAR' => array(
- 0 => 'color: #000099; font-weight: bold;'
+ 0 => 'color: #000099; font-weight: bold;',
+ 1 => 'color: #000099; font-weight: bold;',
+ 2 => 'color: #000099; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #66cc66;'
),
'STRINGS' => array(
- 0 => 'color: #ff0000;'
+ 0 => 'color: #ff6666;'
),
'NUMBERS' => array(
0 => 'color: #cc66cc;'
),
'METHODS' => array(
- 0 => 'color: #b1b100;'
+ 0 => 'color: #aa9900;'
),
'SYMBOLS' => array(
0 => 'color: #66cc66;'
@@ -120,7 +156,11 @@ $language_data = array (
)
),
'URLS' => array(
- 1 => ''
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => ''
),
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/m68k.php b/plugins/wp-syntax/geshi/geshi/m68k.php
index 3c0dfc20..98321577 100644
--- a/plugins/wp-syntax/geshi/geshi/m68k.php
+++ b/plugins/wp-syntax/geshi/geshi/m68k.php
@@ -4,7 +4,7 @@
* --------
* Author: Benny Baumann (BenBE@omorphia.de)
* Copyright: (c) 2007 Benny Baumann (http://www.omorphia.de/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/02/06
*
* Motorola 68000 Assembler language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/magiksf.php b/plugins/wp-syntax/geshi/geshi/magiksf.php
index 5cb21af4..612e1603 100644
--- a/plugins/wp-syntax/geshi/geshi/magiksf.php
+++ b/plugins/wp-syntax/geshi/geshi/magiksf.php
@@ -4,7 +4,7 @@
* --------
* Author: Sjoerd van Leent (svanleent@gmail.com)
* Copyright: (c) 2010 Sjoerd van Leent
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/02/15
*
* MagikSF language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/make.php b/plugins/wp-syntax/geshi/geshi/make.php
index fe495838..885fa176 100644
--- a/plugins/wp-syntax/geshi/geshi/make.php
+++ b/plugins/wp-syntax/geshi/geshi/make.php
@@ -4,7 +4,7 @@
* --------
* Author: Neil Bird <phoenix@fnxweb.com>
* Copyright: (c) 2008 Neil Bird
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/08/26
*
* make language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/mapbasic.php b/plugins/wp-syntax/geshi/geshi/mapbasic.php
index c8cf0e19..8859c483 100644
--- a/plugins/wp-syntax/geshi/geshi/mapbasic.php
+++ b/plugins/wp-syntax/geshi/geshi/mapbasic.php
@@ -4,7 +4,7 @@
* ------
* Author: Tomasz Berus (t.berus@gisodkuchni.pl)
* Copyright: (c) 2009 Tomasz Berus (http://sourceforge.net/projects/mbsyntax/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/11/25
*
* MapBasic language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/matlab.php b/plugins/wp-syntax/geshi/geshi/matlab.php
index 3922f50c..7cdd50e5 100644
--- a/plugins/wp-syntax/geshi/geshi/matlab.php
+++ b/plugins/wp-syntax/geshi/geshi/matlab.php
@@ -4,7 +4,7 @@
* -----------
* Author: Florian Knorn (floz@gmx.de)
* Copyright: (c) 2004 Florian Knorn (http://www.florian-knorn.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/02/09
*
* Matlab M-file language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/mirc.php b/plugins/wp-syntax/geshi/geshi/mirc.php
index d6d8e294..fa2f307e 100644
--- a/plugins/wp-syntax/geshi/geshi/mirc.php
+++ b/plugins/wp-syntax/geshi/geshi/mirc.php
@@ -4,7 +4,7 @@
* -----
* Author: Alberto 'Birckin' de Areba (Birckin@hotmail.com)
* Copyright: (c) 2006 Alberto de Areba
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/05/29
*
* mIRC Scripting language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/mmix.php b/plugins/wp-syntax/geshi/geshi/mmix.php
index 75b69c2b..60b6e28c 100644
--- a/plugins/wp-syntax/geshi/geshi/mmix.php
+++ b/plugins/wp-syntax/geshi/geshi/mmix.php
@@ -4,7 +4,7 @@
* -------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2009 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/10/16
*
* MMIX Assembler language file for GeSHi.
@@ -41,13 +41,21 @@
$language_data = array (
'LANG_NAME' => 'MMIX',
- 'COMMENT_SINGLE' => array(1 => ';'),
+ 'COMMENT_SINGLE' => array(1 => ';', 2 => '%'),
'COMMENT_MULTI' => array(),
//Line address prefix suppression
- 'COMMENT_REGEXP' => array(2 => "/^\s*[0-9a-f]{12,16}+(?:\s+[0-9a-f]+(?:\.{3}[0-9a-f]{2,})?)?:/mi"),
+ 'COMMENT_REGEXP' => array(
+ 3 => "/^\s*(?!\s)[^\w].*$/m",
+ 4 => "/^\s*[0-9a-f]{12,16}+(?:\s+[0-9a-f]+(?:\.{3}[0-9a-f]{2,})?)?:/mi"
+ ),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '',
+ 'NUMBERS' => array(
+ 1 => '(?<![\d\$#\w])[\da-fA-F]+(?!\w)',
+ 2 => '#[\da-fA-F]+',
+ 3 => '\$\d+'
+ ),
'KEYWORDS' => array(
/*CPU*/
1 => array(
@@ -57,54 +65,61 @@ $language_data = array (
'CSP','CSWAP','CSZ','DIV','DIVU','FADD','FCMP','FCMPE','FDIV',
'FEQL','FEQLE','FINT','FIX','FIXU','FLOT','FLOTU','FMUL','FREM',
'FSQRT','FSUB','FUN','FUNE','GET','GETA','GO','INCH','INCL','INCMH',
- 'INCML','JMP','LDB','LDBU','LDHT','LDO','LDOU','LDSF','LDT','LDTU',
- 'LDUNC','LDVTS','LDW','LDWU','MOR','MUL','MULU','MUX','MXOR','NAND',
- 'NEG','NEGU','NOR','NXOR','ODIF','OR','ORH','ORL','ORMH','ORML',
- 'ORN','PBEV','PBN','PBNN','PBNP','PBNZ','PBOD','PBP','PBZ','POP',
- 'PREGO','PRELD','PREST','PUSHGO','PUSHJ','PUT','RESUME','SADD',
+ 'INCML','JMP','LDA','LDB','LDBU','LDHT','LDO','LDOU','LDSF','LDT',
+ 'LDTU','LDUNC','LDVTS','LDW','LDWU','MOR','MUL','MULU','MUX','MXOR',
+ 'NAND','NEG','NEGU','NOR','NXOR','ODIF','OR','ORH','ORL','ORMH',
+ 'ORML','ORN','PBEV','PBN','PBNN','PBNP','PBNZ','PBOD','PBP','PBZ',
+ 'POP','PREGO','PRELD','PREST','PUSHGO','PUSHJ','PUT','RESUME','SADD',
'SAVE','SETH','SETL','SETMH','SETML','SFLOT','SFLOTU','SL','SLU',
'SR','SRU','STB','STBU','STCO','STHT','STO','STOU','STSF','STT',
'STTU','STUNC','STW','STWU','SUB','SUBU','SWYM','SYNC','SYNCD',
'SYNCID','TDIF','TRAP','TRIP','UNSAVE','WDIF','XOR','ZSEV','ZSN',
'ZSNN','ZSNP','ZSNZ','ZSOD','ZSP','ZSZ'
),
+ 2 => array(
+ 'BSPEC','BYTE','ESPEC','GREG','IS','LOC','LOCAL','OCTA',
+ 'PREFIX','SET','TETRA','WYDE'
+ ),
/*registers*/
3 => array(
'rA','rB','rC','rD','rE','rF','rG','rH','rI','rJ','rK','rL','rM',
'rN','rO','rP','rQ','rR','rS','rT','rU','rV','rW','rX','rY','rZ',
'rBB','rTT','rWW','rXX','rYY','rZZ'
),
- /*Directive*/
- 4 => array(
- ),
- /*Operands*/
- 5 => array(
- )
+// /*Directive*/
+// 4 => array(
+// ),
+// /*Operands*/
+// 5 => array(
+// )
),
'SYMBOLS' => array(
'[', ']', '(', ')',
'+', '-', '*', '/', '%',
- '.', ',', ';', ':'
+ '.', ',', ';', ':',
+ '<<','>>'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => true,
2 => false,
3 => true,
- 4 => false,
- 5 => false
+// 4 => false,
+// 5 => false
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #00007f; font-weight: bold;',
2 => 'color: #0000ff; font-weight: bold;',
3 => 'color: #00007f;',
- 4 => 'color: #000000; font-weight: bold;',
- 5 => 'color: #000000; font-weight: bold;'
+// 4 => 'color: #000000; font-weight: bold;',
+// 5 => 'color: #000000; font-weight: bold;'
),
'COMMENTS' => array(
1 => 'color: #666666; font-style: italic;',
- 2 => 'color: #adadad; font-style: italic;',
+ 2 => 'color: #666666; font-style: italic;',
+ 3 => 'color: #666666; font-style: italic;',
+ 4 => 'color: #adadad; font-style: italic;',
),
'ESCAPE_CHAR' => array(
0 => 'color: #000099; font-weight: bold;'
@@ -116,7 +131,10 @@ $language_data = array (
0 => 'color: #7f007f;'
),
'NUMBERS' => array(
- 0 => 'color: #0000ff;'
+ 0 => 'color: #0000ff;',
+ 1 => 'color: #0000ff;',
+ 2 => 'color: #0000ff;',
+ 3 => 'color: #00007f;'
),
'METHODS' => array(
),
@@ -134,9 +152,10 @@ $language_data = array (
1 => '',
2 => '',
3 => '',
- 4 => '',
- 5 => ''
+// 4 => '',
+// 5 => ''
),
+/*
'NUMBERS' =>
GESHI_NUMBER_BIN_PREFIX_PERCENT |
GESHI_NUMBER_BIN_SUFFIX |
@@ -147,6 +166,7 @@ $language_data = array (
GESHI_NUMBER_FLT_NONSCI |
GESHI_NUMBER_FLT_NONSCI_F |
GESHI_NUMBER_FLT_SCI_ZERO,
+*/
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
),
diff --git a/plugins/wp-syntax/geshi/geshi/modula2.php b/plugins/wp-syntax/geshi/geshi/modula2.php
index 0e3a9aea..18508340 100644
--- a/plugins/wp-syntax/geshi/geshi/modula2.php
+++ b/plugins/wp-syntax/geshi/geshi/modula2.php
@@ -4,7 +4,7 @@
* -----------
* Author: Benjamin Kowarsch (benjamin@modula2.net)
* Copyright: (c) 2009 Benjamin Kowarsch (benjamin@modula2.net)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/11/05
*
* Modula-2 language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/modula3.php b/plugins/wp-syntax/geshi/geshi/modula3.php
index e6a9a07f..ae08dcf9 100644
--- a/plugins/wp-syntax/geshi/geshi/modula3.php
+++ b/plugins/wp-syntax/geshi/geshi/modula3.php
@@ -4,7 +4,7 @@
* ----------
* Author: mbishop (mbishop@esoteriq.org)
* Copyright: (c) 2009 mbishop (mbishop@esoteriq.org)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/01/21
*
* Modula-3 language file for GeSHi.
@@ -50,7 +50,7 @@ $language_data = array (
'CONST', 'DIV', 'DO', 'ELSE', 'ELSIF', 'END', 'EVAL', 'EXCEPT', 'EXCEPTION',
'EXIT', 'EXPORTS', 'FINALLY', 'FOR', 'FROM', 'GENERIC', 'IF', 'IMPORT', 'IN',
'INTERFACE', 'LOCK', 'LOOP', 'METHODS', 'MOD', 'MODULE', 'NOT', 'OBJECT', 'OF',
- 'OR', 'OVERRIDE', 'PROCEDURE', 'RAISE', 'RAISES', 'READONLY', 'RECORD', 'REF',
+ 'OR', 'OVERRIDES', 'PROCEDURE', 'RAISE', 'RAISES', 'READONLY', 'RECORD', 'REF',
'REPEAT', 'RETURN', 'REVEAL', 'ROOT', 'SET', 'THEN', 'TO', 'TRY', 'TYPE', 'TYPECASE',
'UNSAFE', 'UNTIL', 'UNTRACED', 'VALUE', 'VAR', 'WHILE', 'WITH'
),
diff --git a/plugins/wp-syntax/geshi/geshi/mpasm.php b/plugins/wp-syntax/geshi/geshi/mpasm.php
index e57f2c3f..f724a941 100644
--- a/plugins/wp-syntax/geshi/geshi/mpasm.php
+++ b/plugins/wp-syntax/geshi/geshi/mpasm.php
@@ -4,7 +4,7 @@
* ---------
* Author: Bakalex (bakalex@gmail.com)
* Copyright: (c) 2004 Bakalex, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/12/6
*
* Microchip Assembler language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/mxml.php b/plugins/wp-syntax/geshi/geshi/mxml.php
index fc1c4247..0cc8287a 100644
--- a/plugins/wp-syntax/geshi/geshi/mxml.php
+++ b/plugins/wp-syntax/geshi/geshi/mxml.php
@@ -4,7 +4,7 @@
* -------
* Author: David Spurr
* Copyright: (c) 2007 David Spurr (http://www.defusion.org.uk/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/10/04
*
* MXML language file for GeSHi. Based on the XML file by Nigel McNie
diff --git a/plugins/wp-syntax/geshi/geshi/mysql.php b/plugins/wp-syntax/geshi/geshi/mysql.php
index 873cff3d..507da2d0 100644
--- a/plugins/wp-syntax/geshi/geshi/mysql.php
+++ b/plugins/wp-syntax/geshi/geshi/mysql.php
@@ -4,7 +4,7 @@
* ---------
* Author: Marjolein Katsma (marjolein.is.back@gmail.com)
* Copyright: (c) 2008 Marjolein Katsma (http://blog.marjoleinkatsma.com/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008-12-12
*
* MySQL language file for GeSHi.
@@ -74,9 +74,9 @@ $language_data = array (
// category, or have multiple usage/meanings
'ACTION','ADD','AFTER','ALGORITHM','ALL','ALTER','ANALYZE','ANY',
'ASC','AS','BDB','BEGIN','BERKELEYDB','BINARY','BTREE','CALL',
- 'CASCADED','CASCADE','CHAIN','CHECK','COLUMNS','COLUMN','COMMENT',
- 'COMMIT','COMMITTED','CONSTRAINT','CONTAINS SQL','CONSISTENT',
- 'CONVERT','CREATE','CROSS','DATA','DATABASES',
+ 'CASCADED','CASCADE','CHAIN','CHANGE','CHECK','COLUMNS','COLUMN',
+ 'COMMENT','COMMIT','COMMITTED','CONSTRAINT','CONTAINS SQL',
+ 'CONSISTENT','CONVERT','CREATE','CROSS','DATA','DATABASES',
'DECLARE','DEFINER','DELAYED','DELETE','DESCRIBE','DESC',
'DETERMINISTIC','DISABLE','DISCARD','DISTINCTROW','DISTINCT','DO',
'DROP','DUMPFILE','DUPLICATE KEY','ENABLE','ENCLOSED BY','ENGINE',
@@ -90,10 +90,10 @@ $language_data = array (
'MASTER_SERVER_ID','MATCH','MERGE','MIDDLEINT','MODIFIES SQL DATA',
'MODIFY','MRG_MYISAM','NATURAL','NEXT','NO SQL','NO','ON',
'OPTIMIZE','OPTIONALLY','OPTION','ORDER BY','OUTER','OUTFILE','OUT',
- 'PARTIAL','PREV','PRIMARY KEY','PRIVILEGES','PROCEDURE','PURGE',
- 'QUICK','READS SQL DATA','READ','REFERENCES','RELEASE','RENAME',
- 'REPEATABLE','REQUIRE','RESTRICT','RETURNS','REVOKE',
- 'ROLLBACK','ROUTINE','RTREE','SAVEPOINT','SELECT',
+ 'PARTIAL','PARTITION','PREV','PRIMARY KEY','PRIVILEGES','PROCEDURE',
+ 'PURGE','QUICK','READS SQL DATA','READ','REFERENCES','RELEASE',
+ 'RENAME','REORGANIZE','REPEATABLE','REQUIRE','RESTRICT','RETURNS',
+ 'REVOKE','ROLLBACK','ROUTINE','RTREE','SAVEPOINT','SELECT',
'SERIALIZABLE','SESSION','SET','SHARE MODE','SHOW','SIMPLE',
'SNAPSHOT','SOME','SONAME','SQL SECURITY','SQL_BIG_RESULT',
'SQL_BUFFER_RESULT','SQL_CACHE','SQL_CALC_FOUND_ROWS',
@@ -391,15 +391,15 @@ $language_data = array (
)
),
'URLS' => array(
- 1 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
- 2 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
- 3 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
- 4 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
- 5 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
- 6 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
- 7 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
- 8 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
- 9 => 'http://search.mysql.com/search?site=refman-%35%31&amp;q={FNAME}',
+ 1 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
+ 2 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
+ 3 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
+ 4 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
+ 5 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
+ 6 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
+ 7 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
+ 8 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
+ 9 => 'http://search.oracle.com/search/search?group=MySQL&amp;q={FNAME}',
10 => 'http://dev.mysql.com/doc/refman/%35%2E%31/en/non-typed-operators.html',
11 => 'http://dev.mysql.com/doc/refman/%35%2E%31/en/non-typed-operators.html',
diff --git a/plugins/wp-syntax/geshi/geshi/nagios.php b/plugins/wp-syntax/geshi/geshi/nagios.php
new file mode 100644
index 00000000..32cbaef9
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/nagios.php
@@ -0,0 +1,225 @@
+<?php
+/*************************************************************************************
+ * nagios.php
+ * --------
+ * Author: Albéric de Pertat <alberic@depertat.net>
+ * Copyright: (c) 2012 Albéric de Pertat (https://github.com/adepertat/geshi-nagios)
+ * Release Version: 1.0.8.11
+ * Date Started: 2012/01/19
+ *
+ * Nagios language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2012/01/19 (1.0.0)
+ * - First Release
+ *
+ * TODO (updated 2012/01/19)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+ 'LANG_NAME' => 'Nagios',
+ 'COMMENT_SINGLE' => array(1 => ';', 2 => '#'),
+ 'COMMENT_MULTI' => array(),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'HARDQUOTE' => array("'", "'"),
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '\'',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'define'
+ ),
+ 2 => array(
+ 'command', 'contact', 'contactgroup', 'host', 'hostdependency',
+ 'hostescalation', 'hostextinfo', 'hostgroup', 'service',
+ 'servicedependency', 'serviceescalation',
+ 'serviceextinfo', 'servicegroup', 'timeperiod'
+ ),
+ 3 => array(
+ 'active_checks_enabled', 'passive_checks_enabled', 'alias',
+ 'display_name', 'host_name', 'address', 'hostgroups', 'parents',
+ 'hostgroup_members', 'members', 'service_description',
+ 'servicegroups', 'is_volatile', 'servicegroup_name',
+ 'servicegroup_members', 'contact_name', 'contactgroups', 'email',
+ 'pager', 'can_submit_commands', 'contactgroup_name',
+ 'contactgroup_members', 'host_notifications_enabled',
+ 'service_notifications_enabled', 'host_notification_period',
+ 'service_notification_period', 'host_notification_options',
+ 'service_notification_options', 'host_notification_commands',
+ 'service_notification_commands', 'check_command',
+ 'check_freshness', 'check_interval', 'check_period', 'contacts',
+ 'contact_groups', 'event_handler', 'event_handler_enabled',
+ 'flap_detection_enabled', 'flap_detection_options',
+ 'freshness_threshold', 'initial_state', 'low_flap_threshold',
+ 'high_flap_threshold', 'max_check_attempts',
+ 'notification_interval', 'first_notification_delay',
+ 'notification_period', 'notification_options',
+ 'notifications_enabled', 'stalking_options', 'notes', 'notes_url',
+ 'action_url', 'icon_image', 'icon_image_alt', 'vrml_image',
+ 'statusmap_image', '2d_coords', '3d_coords', 'obsess_over_host',
+ 'obsess_over_hostver_service', 'process_perf_data',
+ 'retain_status_information', 'retain_nonstatus_information',
+ 'retry_interval', 'register', 'use', 'name', 'timeperiod_name',
+ 'exclude', 'command_name', 'command_line', 'dependent_host_name',
+ 'dependent_hostgroup_name', 'dependent_service_description',
+ 'inherits_parent', 'execution_failure_criteria',
+ 'notification_failure_criteria', 'dependency_period',
+ 'first_notification', 'last_notification', 'escalation_period',
+ 'escalation_options'
+ ),
+ 4 => array(
+ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday',
+ 'sunday', 'january', 'february', 'march', 'april', 'may', 'june',
+ 'july', 'august', 'september', 'october', 'november', 'december',
+ 'day'
+ )
+ ),
+ 'SYMBOLS' => array(
+ 0 => array(
+ '{', '}', ',', '+'
+ )
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'font-weight:bold;color:#FFDCA8;',
+ 2 => 'font-weight:bold;color #FFA858;',
+ 3 => 'font-weight:bold;color:#00C0C0;',
+ 4 => 'font-weight:bold;color:#C0C0FF;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'font-weight:bold;color:#000000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => ''
+ ),
+ 'COMMENTS' => array(
+ 0 => 'color: #AAAAAA; font-style: italic;',
+ 1 => 'color: #AAAAAA; font-style: italic;',
+ 2 => 'color: #AAAAAA; font-style: italic;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #009900;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #660066;',
+ 'HARD' => 'color: #660066;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #006600;'
+ ),
+ 'REGEXPS' => array(
+ 0 => 'font-weight:bold;color:#808080;',
+ 1 => 'font-weight:bold;color:#000080;',
+ 2 => 'font-weight:bold;color:red;',
+ 3 => 'font-weight:bold;color:#808000;',
+ 4 => 'font-weight:bold;color:blue;',
+ 5 => 'font-weight:bold;color:#C0FFC0;',
+ ),
+ 'SCRIPT' => array(
+ 0 => '',
+ )
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '\\'
+ ),
+ 'REGEXPS' => array(
+ // Custom macros
+ 0 => array(
+ GESHI_SEARCH => '(\$[a-zA-Z_]+\$)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => '',
+ ),
+ // Custom macro definitions
+ 1 => array(
+ GESHI_SEARCH => '(\A|\s)(_[a-zA-Z_]+)',
+ GESHI_REPLACE => '\\2',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '\\1',
+ GESHI_AFTER => '',
+ ),
+ // $USERxx$
+ 2 => array(
+ GESHI_SEARCH => '(\$USER[0-9]+\$)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => '',
+ ),
+ // $ARGxx$
+ 3 => array(
+ GESHI_SEARCH => '(\$ARG[1-9]\$)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => '',
+ ),
+ // register 0
+ 4 => array(
+ GESHI_SEARCH => '(\bregister[\\x20\\t]+[01])',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => '',
+ ),
+ // use
+ 5 => array(
+ GESHI_SEARCH => '(use[\\x20\\t]+[^\\x20\\t]+)([\\x20\\t]*[$;#])',
+ GESHI_REPLACE => '\\2',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '\\1',
+ GESHI_AFTER => '',
+ ),
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => ''
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ 0 => false
+ ),
+ 'TAB_WIDTH' => 4,
+ 'PARSER_CONTROL' => array(
+ 'ENABLE_FLAGS' => array(
+ 'NUMBERS' => GESHI_NEVER
+ )
+ )
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/netrexx.php b/plugins/wp-syntax/geshi/geshi/netrexx.php
new file mode 100644
index 00000000..14a2d23f
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/netrexx.php
@@ -0,0 +1,163 @@
+<?php
+/*************************************************************************************
+ * netrexx.php
+ * ---------------------------------
+ * Author: Jon Wolfers (sahananda@windhorse.biz)
+ * Contributors:
+ * - Walter Pachl (pachl@chello.at)
+ * Copyright: (c) 2008 Jon Wolfers, (c) 2012 Walter Pachl
+ * Release Version: 1.0.8.11
+ * Date Started: 2008/01/07
+ *
+ * NetRexx language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2012/07/29 (1.0.0)
+ * - tried to get it syntactically right
+ *
+ * TODO (updated 2012/07/29)
+ * -------------------------
+ * - Get it working on rosettacode.org
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'NetRexx',
+ 'COMMENT_SINGLE' => array(1 => '--'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'class', 'do', 'exit', 'if', 'import', 'iterate', 'leave',
+ 'loop', 'nop', 'numeric', 'package', 'parse', 'properties',
+ 'return', 'say', 'select', 'signal', 'trace'
+ ),
+ 2 => array(
+ 'abstract', 'adapter', 'all', 'ask', 'binary', 'case',
+ 'constant', 'dependent', 'deprecated', 'extends', 'final',
+ 'implements', 'inheritable', 'interface', 'label', 'methods',
+ 'native', 'off', 'private', 'protect', 'public', 'results',
+ 'returns', 'shared', 'signals', 'source', 'static',
+ 'transient', 'unused', 'uses', 'version', 'volatile'
+ ),
+ 3 => array(
+ 'catch', 'else', 'end', 'finally', 'otherwise', 'then', 'when'
+ ),
+ 4 => array(
+ 'rc', 'result', 'self', 'sigl', 'super'
+ ),
+ 5 => array(
+ 'placeholderforoorexxdirectives'
+ ),
+ 6 => array(
+ 'abbrev', 'abs', 'b2x', 'c2d', 'c2x', 'center', 'centre',
+ 'changestr', 'compare', 'copies', 'copyindexed', 'countstr',
+ 'd2c', 'd2x', 'datatype', 'delstr', 'delword', 'exists',
+ 'formword', 'hashcode', 'insert', 'lastpos', 'left', 'lower',
+ 'max', 'min', 'noteq', 'noteqs', 'opadd', 'opand', 'opcc',
+ 'opccblank', 'opdiv', 'opdivi', 'opeq', 'opeqs', 'opgt',
+ 'opgteq', 'opgteqs', 'opgts', 'oplt', 'oplteq', 'oplteqs',
+ 'oplts', 'opminus', 'opmult', 'opnot', 'opor', 'opplus',
+ 'oppow', 'oprem', 'opsub', 'opxor', 'overlay', 'pos position',
+ 'reverse', 'right', 'sequence', 'setdigits', 'setform',
+ 'sign', 'space', 'strip', 'substr', 'subword', 'toboolean',
+ 'tobyte', 'tochar', 'todouble', 'tofloat', 'toint', 'tolong',
+ 'toshort', 'tostring', 'translate', 'trunc', 'upper',
+ 'verify', 'word', 'wordindex', 'wordlength', 'wordpos',
+ 'words', 'x2b', 'x2c', 'x2d'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '<', '>', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^', '&', ':',
+ '<', '>'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => true,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #b1b100;',
+ 2 => 'color: #ff0000; font-weight: bold;',
+ 3 => 'color: #00ff00; font-weight: bold;',
+ 4 => 'color: #0000ff; font-weight: bold;',
+ 5 => 'color: #880088; font-weight: bold;',
+ 6 => 'color: #888800; font-weight: bold;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666;',
+ 'MULTI' => 'color: #808080;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #202020;',
+ 2 => 'color: #202020;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ 6 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/newlisp.php b/plugins/wp-syntax/geshi/geshi/newlisp.php
index b2e0f600..0dc6c161 100644
--- a/plugins/wp-syntax/geshi/geshi/newlisp.php
+++ b/plugins/wp-syntax/geshi/geshi/newlisp.php
@@ -4,7 +4,7 @@
* ----------
* Author: cormullion (cormullion@mac.com) Sept 2009
* Copyright: (c) 2009 Cormullion (http://unbalanced-parentheses.nfshost.com/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/09/30
*
* newLISP language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/nsis.php b/plugins/wp-syntax/geshi/geshi/nsis.php
index 2079169d..35df9b4b 100644
--- a/plugins/wp-syntax/geshi/geshi/nsis.php
+++ b/plugins/wp-syntax/geshi/geshi/nsis.php
@@ -4,7 +4,7 @@
* --------
* Author: deguix (cevo_deguix@yahoo.com.br), Tux (http://tux.a4.cz/)
* Copyright: (c) 2005 deguix, 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/12/03
*
* Nullsoft Scriptable Install System language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/oberon2.php b/plugins/wp-syntax/geshi/geshi/oberon2.php
index 1fd99e27..b43f8140 100644
--- a/plugins/wp-syntax/geshi/geshi/oberon2.php
+++ b/plugins/wp-syntax/geshi/geshi/oberon2.php
@@ -4,7 +4,7 @@
* ----------
* Author: mbishop (mbishop@esoteriq.org)
* Copyright: (c) 2009 mbishop (mbishop@esoteriq.org)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/02/10
*
* Oberon-2 language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/objc.php b/plugins/wp-syntax/geshi/geshi/objc.php
index a6a8b236..2f5162d7 100644
--- a/plugins/wp-syntax/geshi/geshi/objc.php
+++ b/plugins/wp-syntax/geshi/geshi/objc.php
@@ -5,7 +5,7 @@
* Author: M. Uli Kusterer (witness.of.teachtext@gmx.net)
* Contributors: Quinn Taylor (quinntaylor@mac.com)
* Copyright: (c) 2008 Quinn Taylor, 2004 M. Uli Kusterer, Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* Objective-C language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/objeck.php b/plugins/wp-syntax/geshi/geshi/objeck.php
index 6bf17de1..bf9dab56 100644
--- a/plugins/wp-syntax/geshi/geshi/objeck.php
+++ b/plugins/wp-syntax/geshi/geshi/objeck.php
@@ -4,13 +4,15 @@
* --------
* Author: Randy Hollines (objeck@gmail.com)
* Copyright: (c) 2010 Randy Hollines (http://code.google.com/p/objeck-lang/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/07/01
*
* Objeck Programming Language language file for GeSHi.
*
* CHANGES
* -------
+ * 2010/07/26 (1.0.8.10)
+ * - Added new and missing keywords and symbols: 'String', 'each', '+=', '-=', '*=' and '/='.
* 2010/07/01 (1.0.8.9)
* - First Release
*
@@ -45,10 +47,10 @@ $language_data = array(
1 => array(
'virtual', 'if', 'else', 'do', 'while', 'use', 'bundle', 'native',
'static', 'public', 'private', 'class', 'function', 'method',
- 'select', 'other', 'enum', 'for', 'label', 'return', 'from'
+ 'select', 'other', 'enum', 'for', 'each', 'label', 'return', 'from'
),
2 => array(
- 'Byte', 'Int', 'Nil', 'Float', 'Char', 'Bool'
+ 'Byte', 'Int', 'Nil', 'Float', 'Char', 'Bool', 'String'
),
3 => array(
'true', 'false'
@@ -56,7 +58,7 @@ $language_data = array(
),
'SYMBOLS' => array(
1 => array(
- '(', ')', '{', '}', '[', ']', '+', '-', '*', '/', '%', '=', '<', '>', '&', '|', ':', ';', ','
+ '(', ')', '{', '}', '[', ']', '+', '-', '*', '/', '%', '=', '<', '>', '&', '|', ':', ';', ',', '+=', '-=', '*=', '/=',
)
),
'CASE_SENSITIVE' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/ocaml-brief.php b/plugins/wp-syntax/geshi/geshi/ocaml-brief.php
index f4503422..b518adf8 100644
--- a/plugins/wp-syntax/geshi/geshi/ocaml-brief.php
+++ b/plugins/wp-syntax/geshi/geshi/ocaml-brief.php
@@ -4,7 +4,7 @@
* ----------
* Author: Flaie (fireflaie@gmail.com)
* Copyright: (c) 2005 Flaie, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/08/27
*
* OCaml (Objective Caml) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/ocaml.php b/plugins/wp-syntax/geshi/geshi/ocaml.php
index 67d8a766..ac6c29bc 100644
--- a/plugins/wp-syntax/geshi/geshi/ocaml.php
+++ b/plugins/wp-syntax/geshi/geshi/ocaml.php
@@ -4,7 +4,7 @@
* ----------
* Author: Flaie (fireflaie@gmail.com)
* Copyright: (c) 2005 Flaie, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/08/27
*
* OCaml (Objective Caml) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/octave.php b/plugins/wp-syntax/geshi/geshi/octave.php
new file mode 100644
index 00000000..ccffcd97
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/octave.php
@@ -0,0 +1,515 @@
+<?php
+/*************************************************************************************
+ * octave.php
+ * -----------
+ * Author: Carnë Draug (carandraug+dev@gmail.com)
+ * Juan Pablo Carbajal (carbajal@ifi.uzh.ch)
+ * Copyright: (c) 2012 Carnë Draug
+ * (c) 2012 Juan Pablo Carbajal
+ * Release Version: 1.0.8.11
+ * Date Started: 2012/05/22
+ *
+ * GNU Octave M-file language file for GeSHi.
+ *
+ * This file was heavily based on octave.lang from gtksourceview. If bugs are
+ * found and/or fixed on this file, please send them to the gtksourceview
+ * project or e-mail them to this file authors. Thanks in advance
+ *
+ * CHANGES
+ * -------
+ * 2012/05/22 (1.0.8.11)
+ * - First Release
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'GNU Octave',
+ 'COMMENT_SINGLE' => array(1 => '#', 2 => '%'),
+ // we can't use COMMENT_MULTI since start and end of block comments need to
+ // be alone on the line (optionally, with whitespace). See COMMENT_REGEXP
+ 'COMMENT_MULTI' => array(),
+ // we can't use QUOTEMARKS, not even HARDQUOTE, see COMMENT_REGEXP
+ 'QUOTEMARKS' => array(),
+ 'ESCAPE_CHAR' => '',
+ 'COMMENT_REGEXP' => array(
+ // Single quote strings: we can't use QUOTEMARKS here since new
+ // lines will break the string. Plus, single quote strings do not even
+ // allow for continuation markers, only double quote strings allow it.
+ // Also, to do not misdetect the transpose operator ' as the start of a
+ // string we assert to not follow a variable name (letters, digits and
+ // underscores) or a closing bracket (round, square or curly) or a dot
+ // (to form the array transpose operator ".'" ).
+ 3 => "/(?<![0-9a-zA-Z_\)\]}\.])'.*?'/",
+ // Double quote strings: we also can't use QUOTEMARKS here (see single
+ // line quotes). However, with double quote strings both \ and ... can
+ // be used to make multiline strings. Continuation markers can be
+ // followed by whitespace
+ 4 => '/"(.|(\.\.\.|\\\)(\s)*?\n)*?(?<!\\\)"/',
+ // Block comments: the ms modifiers treat strings as multiple lines (to
+ // be able to use ^ and $ instead of newline and thus support block
+ // comments on the first and last line of source) and make . also match
+ // a newline
+ 5 => "/^\s*?[%#]{\s*?$.*?^\s*?[%#]}\s*?$/ms",
+ // Packaging system: comes here so that pkg can also be used in the
+ // function form. The list of pkg commands is optional to the match so
+ // that at least pkg is highlighted if new commands are implemented
+ 6 => "/\bpkg(?!\s*\()\s+((un)?install|update|(un)?load|list|(global|local)_list|describe|prefix|(re)?build)?\b/",
+ // Function handles
+ 7 => "/@([a-z_][a-z1-9_]*)?/i",
+ ),
+ 'NUMBERS' =>
+ GESHI_NUMBER_INT_BASIC |
+ GESHI_NUMBER_OCT_PREFIX |
+ GESHI_NUMBER_HEX_PREFIX |
+ GESHI_NUMBER_FLT_SCI_ZERO,
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'KEYWORDS' => array(
+ // Data types
+ 1 => array(
+ 'cell', 'char', 'double', 'uint8', 'uint16', 'uint32', 'uint64',
+ 'int8','int16', 'int32', 'int64', 'logical', 'single', 'struct'
+ ),
+ // Storage type
+ 2 => array(
+ 'global', 'persistent', 'static'
+ ),
+ // Internal variable
+ 3 => array(
+ 'ans'
+ ),
+ // Reserved words
+ 4 => array(
+ 'break', 'case', 'catch', 'continue', 'do', 'else', 'elseif', 'end',
+ 'end_try_catch', 'end_unwind_protect', 'endfor', 'endfunction',
+ 'endif', 'endparfor', 'endswitch', 'endwhile', 'for', 'function',
+ 'if', 'otherwise', 'parfor', 'return',
+ 'switch', 'try', 'until', 'unwind_protect',
+ 'unwind_protect_cleanup', 'varargin', 'varargout', 'while'
+ ),
+ // Built in
+ 5 => array(
+ 'P_tmpdir', 'abs', 'acos', 'acosh',
+ 'add_input_event_hook', 'addlistener', 'addpath', 'addproperty',
+ 'all', 'allow_noninteger_range_as_index', 'and', 'angle', 'any',
+ 'arg', 'argnames', 'argv', 'asin', 'asinh', 'assignin', 'atan',
+ 'atan2', 'atanh', 'atexit', 'autoload', 'available_graphics_toolkits',
+ 'beep_on_error', 'bitand', 'bitmax', 'bitor', 'bitshift', 'bitxor',
+ 'builtin', 'canonicalize_file_name', 'cat', 'cbrt', 'cd', 'ceil',
+ 'cell2struct', 'cellstr', 'chdir', 'class', 'clc',
+ 'clear', 'columns', 'command_line_path', 'completion_append_char',
+ 'completion_matches', 'complex', 'confirm_recursive_rmdir', 'conj',
+ 'cos', 'cosh', 'cputime', 'crash_dumps_octave_core', 'ctranspose',
+ 'cumprod', 'cumsum', 'dbclear', 'dbcont', 'dbdown', 'dbnext',
+ 'dbquit', 'dbstack', 'dbstatus', 'dbstep', 'dbstop', 'dbtype', 'dbup',
+ 'dbwhere', 'debug_on_error', 'debug_on_interrupt', 'debug_on_warning',
+ 'default_save_options', 'dellistener', 'diag', 'diary', 'diff',
+ 'disp', 'do_braindead_shortcircuit_evaluation', 'do_string_escapes',
+ 'doc_cache_file', 'drawnow', 'dup2', 'echo',
+ 'echo_executing_commands', 'edit_history','eq', 'erf', 'erfc',
+ 'erfcx', 'erfinv', 'errno', 'errno_list', 'error', 'eval', 'evalin',
+ 'exec', 'exist', 'exit', 'exp', 'expm1', 'eye', 'fclear',
+ 'fclose', 'fcntl', 'fdisp', 'feof', 'ferror', 'feval', 'fflush',
+ 'fgetl', 'fgets', 'fieldnames', 'file_in_loadpath', 'file_in_path',
+ 'filemarker', 'filesep', 'find_dir_in_path', 'finite', 'fix',
+ 'fixed_point_format', 'floor', 'fmod', 'fnmatch', 'fopen', 'fork',
+ 'format', 'formula', 'fprintf', 'fputs', 'fread', 'freport',
+ 'frewind', 'fscanf', 'fseek', 'fskipl', 'ftell', 'full', 'func2str',
+ 'functions', 'fwrite', 'gamma', 'gammaln', 'ge', 'genpath', 'get',
+ 'get_help_text', 'get_help_text_from_file', 'getegid', 'getenv',
+ 'geteuid', 'getgid', 'gethostname', 'getpgrp', 'getpid', 'getppid',
+ 'getuid', 'glob', 'gt', 'history', 'history_control', 'history_file',
+ 'history_size', 'history_timestamp_format_string', 'home', 'horzcat',
+ 'hypot', 'ifelse', 'ignore_function_time_stamp', 'imag',
+ 'inferiorto', 'info_file', 'info_program', 'inline', 'input',
+ 'intmax', 'intmin', 'ipermute',
+ 'is_absolute_filename', 'is_dq_string', 'is_function_handle',
+ 'is_rooted_relative_filename', 'is_sq_string', 'isalnum', 'isalpha',
+ 'isargout', 'isascii', 'isbool', 'iscell', 'iscellstr', 'ischar',
+ 'iscntrl', 'iscomplex', 'isdebugmode', 'isdigit', 'isempty',
+ 'isfield', 'isfinite', 'isfloat', 'isglobal', 'isgraph', 'ishandle',
+ 'isieee', 'isindex', 'isinf', 'isinteger', 'iskeyword', 'islogical',
+ 'islower', 'ismatrix', 'ismethod', 'isna', 'isnan', 'isnull',
+ 'isnumeric', 'isobject', 'isprint', 'ispunct', 'isreal', 'issorted',
+ 'isspace', 'issparse', 'isstruct', 'isupper', 'isvarname', 'isxdigit',
+ 'kbhit', 'keyboard', 'kill', 'lasterr', 'lasterror', 'lastwarn',
+ 'ldivide', 'le', 'length', 'lgamma', 'link', 'linspace',
+ 'list_in_columns', 'load', 'loaded_graphics_toolkits', 'log', 'log10',
+ 'log1p', 'log2', 'lower', 'lstat', 'lt',
+ 'make_absolute_filename', 'makeinfo_program', 'max_recursion_depth',
+ 'merge', 'methods', 'mfilename', 'minus', 'mislocked',
+ 'missing_function_hook', 'mkdir', 'mkfifo', 'mkstemp', 'mldivide',
+ 'mlock', 'mod', 'more', 'mpower', 'mrdivide', 'mtimes', 'munlock',
+ 'nargin', 'nargout', 'native_float_format', 'ndims', 'ne',
+ 'nfields', 'nnz', 'norm', 'not', 'nth_element', 'numel', 'nzmax',
+ 'octave_config_info', 'octave_core_file_limit',
+ 'octave_core_file_name', 'octave_core_file_options',
+ 'octave_tmp_file_name', 'onCleanup', 'ones',
+ 'optimize_subsasgn_calls', 'or', 'output_max_field_width',
+ 'output_precision', 'page_output_immediately', 'page_screen_output',
+ 'path', 'pathsep', 'pause', 'pclose', 'permute', 'pipe', 'plus',
+ 'popen', 'popen2', 'power', 'print_empty_dimensions',
+ 'print_struct_array_contents', 'printf', 'prod',
+ 'program_invocation_name', 'program_name', 'putenv', 'puts', 'pwd',
+ 'quit', 'rats', 'rdivide', 're_read_readline_init_file',
+ 'read_readline_init_file', 'readdir', 'readlink', 'real', 'realmax',
+ 'realmin', 'register_graphics_toolkit', 'rehash', 'rem',
+ 'remove_input_event_hook', 'rename', 'repelems', 'reset', 'reshape',
+ 'resize', 'restoredefaultpath', 'rethrow', 'rmdir', 'rmfield',
+ 'rmpath', 'round', 'roundb', 'rows', 'run_history', 'save',
+ 'save_header_format_string', 'save_precision', 'saving_history',
+ 'scanf', 'set', 'setenv', 'sighup_dumps_octave_core', 'sign',
+ 'sigterm_dumps_octave_core', 'silent_functions', 'sin',
+ 'sinh', 'size', 'size_equal', 'sizemax', 'sizeof', 'sleep', 'sort',
+ 'source', 'spalloc', 'sparse', 'sparse_auto_mutate',
+ 'split_long_rows', 'sprintf', 'sqrt', 'squeeze', 'sscanf', 'stat',
+ 'stderr', 'stdin', 'stdout', 'str2func', 'strcmp', 'strcmpi',
+ 'string_fill_char', 'strncmp', 'strncmpi', 'struct2cell',
+ 'struct_levels_to_print', 'strvcat', 'subsasgn', 'subsref', 'sum',
+ 'sumsq', 'superiorto', 'suppress_verbose_help_message', 'symlink',
+ 'system', 'tan', 'tanh', 'terminal_size', 'tic', 'tilde_expand',
+ 'times', 'tmpfile', 'tmpnam', 'toascii', 'toc', 'tolower', 'toupper',
+ 'transpose', 'typeinfo',
+ 'umask', 'uminus', 'uname', 'undo_string_escapes', 'unlink',
+ 'uplus', 'upper', 'usage', 'usleep', 'vec', 'vectorize', 'vertcat',
+ 'waitfor', 'waitpid', 'warning', 'warranty', 'who', 'whos',
+ 'whos_line_format', 'yes_or_no', 'zeros'
+ ),
+ // Octave functions
+ 6 => array(
+ 'accumarray', 'accumdim', 'acosd', 'acot', 'acotd', 'acoth', 'acsc',
+ 'acscd', 'acsch', 'addpref', 'addtodate', 'allchild', 'amd',
+ 'ancestor', 'anova', 'arch_fit', 'arch_rnd', 'arch_test',
+ 'area', 'arma_rnd', 'asctime', 'asec', 'asecd', 'asech', 'asind',
+ 'assert', 'atand', 'autoreg_matrix', 'autumn',
+ 'axes', 'axis', 'balance', 'bar', 'barh', 'bartlett', 'bartlett_test',
+ 'base2dec', 'beep', 'bessel', 'besselj', 'beta', 'betacdf',
+ 'betainc', 'betainv', 'betaln', 'betapdf', 'betarnd', 'bicg',
+ 'bicgstab', 'bicubic', 'bin2dec', 'bincoeff', 'binocdf', 'binoinv',
+ 'binopdf', 'binornd', 'bitcmp', 'bitget', 'bitset', 'blackman',
+ 'blanks', 'blkdiag', 'bone', 'box', 'brighten', 'bsxfun',
+ 'bug_report', 'bunzip2', 'bzip2', 'calendar', 'cart2pol', 'cart2sph',
+ 'cast', 'cauchy_cdf', 'cauchy_inv', 'cauchy_pdf', 'cauchy_rnd',
+ 'caxis', 'ccolamd', 'cell2mat', 'celldisp', 'cellfun',
+ 'center', 'cgs', 'chi2cdf', 'chi2inv', 'chi2pdf', 'chi2rnd',
+ 'chisquare_test_homogeneity', 'chisquare_test_independence', 'chol',
+ 'chop', 'circshift', 'cla', 'clabel', 'clf', 'clock',
+ 'cloglog', 'close', 'closereq', 'colamd', 'colloc', 'colon',
+ 'colorbar', 'colormap', 'colperm', 'colstyle', 'comet', 'comet3',
+ 'comma', 'common_size', 'commutation_matrix', 'compan',
+ 'compare_versions', 'compass', 'computer', 'cond', 'condest',
+ 'contour', 'contour3', 'contourc', 'contourf', 'contrast', 'conv',
+ 'conv2', 'convhull', 'convhulln', 'cool', 'copper', 'copyfile',
+ 'cor_test', 'corr', 'cosd', 'cot', 'cotd', 'coth', 'cov',
+ 'cplxpair', 'cross', 'csc', 'cscd', 'csch', 'cstrcat',
+ 'csvread', 'csvwrite', 'ctime', 'cumtrapz', 'curl', 'cylinder',
+ 'daspect', 'daspk', 'dasrt', 'dassl', 'date', 'datenum', 'datestr',
+ 'datetick', 'datevec', 'dblquad', 'deal', 'deblank', 'debug',
+ 'dec2base', 'dec2bin', 'dec2hex', 'deconv', 'del2', 'delaunay',
+ 'delaunay3', 'delaunayn', 'delete', 'demo', 'det', 'detrend',
+ 'diffpara', 'diffuse', 'dir', 'discrete_cdf', 'discrete_inv',
+ 'discrete_pdf', 'discrete_rnd', 'display', 'divergence',
+ 'dlmread', 'dlmwrite', 'dmperm', 'doc', 'dos', 'dot', 'dsearch',
+ 'dsearchn', 'dump_prefs', 'duplication_matrix', 'durbinlevinson',
+ 'edit', 'eig', 'eigs', 'ellipsoid', 'empirical_cdf', 'empirical_inv',
+ 'empirical_pdf', 'empirical_rnd', 'eomday', 'errorbar',
+ 'etime', 'etreeplot', 'example', 'expcdf', 'expinv', 'expm', 'exppdf',
+ 'exprnd', 'ezcontour', 'ezcontourf', 'ezmesh', 'ezmeshc', 'ezplot',
+ 'ezplot3', 'ezpolar', 'ezsurf', 'ezsurfc', 'f_test_regression',
+ 'fact', 'factor', 'factorial', 'fail', 'fcdf', 'feather', 'fft',
+ 'fft2', 'fftconv', 'fftfilt', 'fftn', 'fftshift', 'fftw', 'figure',
+ 'fileattrib', 'fileparts', 'fileread', 'fill', 'filter', 'filter2',
+ 'find', 'findall', 'findobj', 'findstr', 'finv', 'flag', 'flipdim',
+ 'fliplr', 'flipud', 'fminbnd', 'fminunc', 'fpdf', 'fplot',
+ 'fractdiff', 'freqz', 'freqz_plot', 'frnd', 'fsolve',
+ 'fullfile', 'fzero', 'gamcdf', 'gaminv', 'gammainc',
+ 'gampdf', 'gamrnd', 'gca', 'gcbf', 'gcbo', 'gcd', 'gcf',
+ 'gen_doc_cache', 'genvarname', 'geocdf', 'geoinv', 'geopdf', 'geornd',
+ 'get_first_help_sentence', 'getappdata', 'getfield', 'getgrent',
+ 'getpref', 'getpwent', 'getrusage', 'ginput', 'givens', 'glpk',
+ 'gls', 'gmap40', 'gmres', 'gnuplot_binary', 'gplot',
+ 'gradient', 'graphics_toolkit', 'gray', 'gray2ind', 'grid',
+ 'griddata', 'griddata3', 'griddatan', 'gtext', 'guidata',
+ 'guihandles', 'gunzip', 'gzip', 'hadamard', 'hamming', 'hankel',
+ 'hanning', 'help', 'hess', 'hex2dec', 'hex2num', 'hggroup', 'hidden',
+ 'hilb', 'hist', 'histc', 'hold', 'hot', 'hotelling_test',
+ 'hotelling_test_2', 'housh', 'hsv', 'hsv2rgb', 'hurst', 'hygecdf',
+ 'hygeinv', 'hygepdf', 'hygernd', 'idivide', 'ifftshift', 'image',
+ 'imagesc', 'imfinfo', 'imread', 'imshow', 'imwrite', 'ind2gray',
+ 'ind2rgb', 'index', 'info', 'inpolygon', 'inputname', 'int2str',
+ 'interp1', 'interp1q', 'interp2', 'interp3', 'interpft', 'interpn',
+ 'intersect', 'inv', 'invhilb', 'iqr',
+ 'is_leap_year', 'is_valid_file_id',
+ 'isa', 'isappdata', 'iscolumn', 'isdefinite', 'isdeployed', 'isdir',
+ 'isequal', 'isequalwithequalnans', 'isfigure', 'ishermitian',
+ 'ishghandle', 'ishold', 'isletter', 'ismac', 'ismember', 'isocolors',
+ 'isonormals', 'isosurface', 'ispc', 'ispref', 'isprime', 'isprop',
+ 'isrow', 'isscalar', 'issquare', 'isstrprop', 'issymmetric',
+ 'isunix', 'isvector', 'jet', 'kendall', 'kolmogorov_smirnov_cdf',
+ 'kolmogorov_smirnov_test', 'kolmogorov_smirnov_test_2', 'kron',
+ 'kruskal_wallis_test', 'krylov', 'kurtosis', 'laplace_cdf',
+ 'laplace_inv', 'laplace_pdf', 'laplace_rnd', 'lcm', 'legend',
+ 'legendre', 'license', 'lin2mu', 'line', 'linkprop', 'list_primes',
+ 'loadaudio', 'loadobj', 'logistic_cdf', 'logistic_inv',
+ 'logistic_pdf', 'logistic_regression', 'logistic_rnd', 'logit',
+ 'loglog', 'loglogerr', 'logm', 'logncdf', 'logninv', 'lognpdf',
+ 'lognrnd', 'logspace', 'lookfor', 'lookup', 'ls', 'ls_command',
+ 'lsode', 'lsqnonneg', 'lu', 'luinc', 'magic', 'mahalanobis', 'manova',
+ 'mat2str', 'matlabroot', 'matrix_type', 'max', 'mcnemar_test',
+ 'md5sum', 'mean', 'meansq', 'median', 'menu', 'mesh', 'meshc',
+ 'meshgrid', 'meshz', 'mex', 'mexext', 'mgorth', 'mkoctfile', 'mkpp',
+ 'mode', 'moment', 'movefile', 'mpoles', 'mu2lin', 'namelengthmax',
+ 'nargchk', 'narginchk', 'nargoutchk', 'nbincdf', 'nbininv', 'nbinpdf',
+ 'nbinrnd', 'nchoosek', 'ndgrid', 'newplot', 'news', 'nextpow2',
+ 'nonzeros', 'normcdf', 'normest', 'norminv', 'normpdf', 'normrnd',
+ 'now', 'nproc', 'nthargout', 'nthroot', 'ntsc2rgb', 'null', 'num2str',
+ 'ocean', 'ols', 'onenormest', 'optimget', 'optimset', 'orderfields',
+ 'orient', 'orth', 'pack', 'paren', 'pareto', 'parseparams', 'pascal',
+ 'patch', 'pathdef', 'pbaspect', 'pcg', 'pchip', 'pcolor', 'pcr',
+ 'peaks', 'periodogram', 'perl', 'perms', 'pie', 'pie3',
+ 'pink', 'pinv', 'pkg', 'planerot', 'playaudio', 'plot', 'plot3',
+ 'plotmatrix', 'plotyy', 'poisscdf', 'poissinv', 'poisspdf',
+ 'poissrnd', 'pol2cart', 'polar', 'poly', 'polyaffine', 'polyarea',
+ 'polyder', 'polyfit', 'polygcd', 'polyint', 'polyout',
+ 'polyreduce', 'polyval', 'polyvalm', 'postpad', 'pow2', 'powerset',
+ 'ppder', 'ppint', 'ppjumps', 'ppplot', 'ppval', 'pqpnonneg',
+ 'prctile', 'prepad', 'primes', 'print', 'printAllBuiltins',
+ 'print_usage', 'prism', 'probit', 'profexplore', 'profile',
+ 'profshow', 'prop_test_2', 'python', 'qp', 'qqplot', 'qr', 'quad',
+ 'quadcc', 'quadgk', 'quadl', 'quadv', 'quantile', 'quiver', 'quiver3',
+ 'qz', 'qzhess', 'rainbow', 'rand', 'randi', 'range', 'rank', 'ranks',
+ 'rat', 'rcond', 'reallog', 'realpow', 'realsqrt', 'record',
+ 'rectangle', 'rectint', 'recycle', 'refresh', 'refreshdata', 'regexp',
+ 'regexptranslate', 'repmat', 'residue', 'rgb2hsv',
+ 'rgb2ind', 'rgb2ntsc', 'ribbon', 'rindex', 'rmappdata', 'rmpref',
+ 'roots', 'rose', 'rosser', 'rot90', 'rotdim', 'rref', 'run',
+ 'run_count', 'run_test', 'rundemos', 'runlength', 'runtests',
+ 'saveas', 'saveaudio', 'saveobj', 'savepath', 'scatter',
+ 'scatter3', 'schur', 'sec', 'secd', 'sech', 'semicolon', 'semilogx',
+ 'semilogxerr', 'semilogy', 'semilogyerr', 'setappdata', 'setaudio',
+ 'setdiff', 'setfield', 'setpref', 'setxor', 'shading',
+ 'shg', 'shift', 'shiftdim', 'sign_test', 'sinc', 'sind',
+ 'sinetone', 'sinewave', 'skewness', 'slice', 'sombrero', 'sortrows',
+ 'spaugment', 'spconvert', 'spdiags', 'spearman', 'spectral_adf',
+ 'spectral_xdf', 'specular', 'speed', 'spencer', 'speye', 'spfun',
+ 'sph2cart', 'sphere', 'spinmap', 'spline', 'spones', 'spparms',
+ 'sprand', 'sprandn', 'sprandsym', 'spring', 'spstats', 'spy', 'sqp',
+ 'sqrtm', 'stairs', 'statistics', 'std', 'stdnormal_cdf',
+ 'stdnormal_inv', 'stdnormal_pdf', 'stdnormal_rnd', 'stem', 'stem3',
+ 'stft', 'str2double', 'str2num', 'strcat', 'strchr',
+ 'strfind', 'strjust', 'strmatch', 'strread', 'strsplit', 'strtok',
+ 'strtrim', 'strtrunc', 'structfun', 'sub2ind',
+ 'subplot', 'subsindex', 'subspace', 'substr', 'substruct', 'summer',
+ 'surf', 'surface', 'surfc', 'surfl', 'surfnorm', 'svd', 'svds',
+ 'swapbytes', 'syl', 'symbfact', 'symrcm',
+ 'symvar', 'synthesis', 't_test', 't_test_2', 't_test_regression',
+ 'table', 'tand', 'tar', 'tcdf', 'tempdir', 'tempname', 'test', 'text',
+ 'textread', 'textscan', 'time', 'tinv', 'title', 'toeplitz', 'tpdf',
+ 'trace', 'trapz', 'treelayout', 'treeplot', 'tril', 'trimesh',
+ 'triplequad', 'triplot', 'trisurf', 'trnd', 'tsearch', 'tsearchn',
+ 'type', 'typecast', 'u_test', 'uicontextmenu', 'uicontrol',
+ 'uigetdir', 'uigetfile', 'uimenu', 'uipanel', 'uipushtool',
+ 'uiputfile', 'uiresume', 'uitoggletool', 'uitoolbar', 'uiwait',
+ 'unidcdf', 'unidinv', 'unidpdf', 'unidrnd', 'unifcdf', 'unifinv',
+ 'unifpdf', 'unifrnd', 'unimplemented', 'union', 'unique', 'unix',
+ 'unmkpp', 'unpack', 'untabify', 'untar', 'unwrap', 'unzip',
+ 'urlwrite', 'usejava', 'validatestring', 'vander', 'var',
+ 'var_test', 'vech', 'ver', 'version', 'view', 'voronoi', 'voronoin',
+ 'waitbar', 'waitforbuttonpress', 'warning_ids', 'wavread', 'wavwrite',
+ 'wblcdf', 'wblinv', 'wblpdf', 'wblrnd', 'weekday',
+ 'welch_test', 'what', 'which',
+ 'white', 'whitebg', 'wienrnd', 'wilcoxon_test', 'wilkinson', 'winter',
+ 'xlabel', 'xlim', 'xor', 'ylabel', 'ylim', 'yulewalker', 'z_test',
+ 'z_test_2', 'zip', 'zlabel', 'zlim', 'zscore', 'airy', 'arrayfun',
+ 'besselh', 'besseli', 'besselk', 'bessely', 'bitpack', 'bitunpack',
+ 'blkmm', 'cellindexmat', 'cellslices', 'chol2inv', 'choldelete',
+ 'cholinsert', 'cholinv', 'cholshift', 'cholupdate', 'convn',
+ 'csymamd', 'cummax', 'cummin', 'daspk_options', 'dasrt_options',
+ 'dassl_options', 'endgrent', 'endpwent', 'etree', 'getgrgid',
+ 'getgrnam', 'getpwnam', 'getpwuid', 'gmtime', 'gui_mode', 'ifft',
+ 'ifft2', 'ifftn', 'ind2sub', 'inverse', 'localtime', 'lsode_options',
+ 'luupdate', 'mat2cell', 'min', 'mktime', 'mouse_wheel_zoom',
+ 'num2cell', 'num2hex', 'qrdelete', 'qrinsert', 'qrshift', 'qrupdate',
+ 'quad_options', 'rande', 'randg', 'randn', 'randp', 'randperm',
+ 'regexpi', 'regexprep', 'rsf2csf', 'setgrent', 'setpwent', 'sprank',
+ 'strftime', 'strptime', 'strrep', 'svd_driver', 'symamd', 'triu',
+ 'urlread'
+ ),
+ // Private builtin
+ 7 => array(
+ '__accumarray_max__', '__accumarray_min__', '__accumarray_sum__',
+ '__accumdim_sum__', '__builtins__', '__calc_dimensions__',
+ '__current_scope__', '__display_tokens__', '__dump_symtab_info__',
+ '__end__', '__get__', '__go_axes__', '__go_axes_init__',
+ '__go_delete__', '__go_execute_callback__', '__go_figure__',
+ '__go_figure_handles__', '__go_handles__', '__go_hggroup__',
+ '__go_image__', '__go_line__', '__go_patch__', '__go_surface__',
+ '__go_text__', '__go_uicontextmenu__', '__go_uicontrol__',
+ '__go_uimenu__', '__go_uipanel__', '__go_uipushtool__',
+ '__go_uitoggletool__', '__go_uitoolbar__', '__gud_mode__',
+ '__image_pixel_size__', '__is_handle_visible__', '__isa_parent__',
+ '__keywords__', '__lexer_debug_flag__', '__list_functions__',
+ '__operators__', '__parent_classes__', '__parser_debug_flag__',
+ '__pathorig__', '__profiler_data__', '__profiler_enable__',
+ '__profiler_reset__', '__request_drawnow__', '__sort_rows_idx__',
+ '__token_count__', '__varval__', '__version_info__', '__which__'
+ ),
+ // Private Octave functions
+ 8 => array(
+ '__all_opts__', '__contourc__', '__delaunayn__', '__dispatch__',
+ '__dsearchn__', '__finish__', '__fltk_uigetfile__',
+ '__glpk__', '__gnuplot_drawnow__', '__init_fltk__',
+ '__init_gnuplot__', '__lin_interpn__', '__magick_read__',
+ '__makeinfo__', '__pchip_deriv__', '__plt_get_axis_arg__', '__qp__',
+ '__voronoi__', '__fltk_maxtime__', '__fltk_redraw__', '__ftp__',
+ '__ftp_ascii__', '__ftp_binary__', '__ftp_close__', '__ftp_cwd__',
+ '__ftp_delete__', '__ftp_dir__', '__ftp_mget__', '__ftp_mkdir__',
+ '__ftp_mode__', '__ftp_mput__', '__ftp_pwd__', '__ftp_rename__',
+ '__ftp_rmdir__', '__magick_finfo__', '__magick_format_list__',
+ '__magick_write__'
+ ),
+ // Builtin Global Variables
+ 9 => array(
+ 'EDITOR', 'EXEC_PATH', 'F_DUPFD', 'F_GETFD', 'F_GETFL', 'F_SETFD',
+ 'F_SETFL', 'IMAGE_PATH', 'OCTAVE_HOME',
+ 'OCTAVE_VERSION', 'O_APPEND', 'O_ASYNC', 'O_CREAT', 'O_EXCL',
+ 'O_NONBLOCK', 'O_RDONLY', 'O_RDWR', 'O_SYNC', 'O_TRUNC', 'O_WRONLY',
+ 'PAGER', 'PAGER_FLAGS', 'PS1', 'PS2', 'PS4', 'SEEK_CUR', 'SEEK_END',
+ 'SEEK_SET', 'SIG', 'S_ISBLK', 'S_ISCHR', 'S_ISDIR', 'S_ISFIFO',
+ 'S_ISLNK', 'S_ISREG', 'S_ISSOCK', 'WCONTINUE', 'WCOREDUMP',
+ 'WEXITSTATUS', 'WIFCONTINUED', 'WIFEXITED', 'WIFSIGNALED',
+ 'WIFSTOPPED', 'WNOHANG', 'WSTOPSIG', 'WTERMSIG', 'WUNTRACED'
+ ),
+ // Constant functions
+ 10 => array (
+ 'e', 'eps', 'inf', 'Inf', 'nan', 'NaN', 'NA', 'pi', 'i', 'I', 'j',
+ 'J', 'true', 'false'
+ ),
+ ),
+ 'SYMBOLS' => array(
+ // Comparison & logical
+ 0 => array(
+ '!', '!=', '&', '&&','|', '||', '~', '~=',
+ '<', '<=', '==', '>', '>='
+ ),
+ // Aritmethical
+ 1 => array(
+ '*', '**', '+', '++', '-', '--', '/', "\\","'"
+ ),
+ // Elementwise arithmetical
+ 2 => array(
+ '.*', '.**','./', '.^', '^',".\\",".'"
+ ),
+ // Arithmetical & assignation
+ 3 => array(
+ '*=','+=','-=','/=','\=','**=','^=',
+ '.*=','.+=','.-=','./=','.\=','.**=','.^=','='
+ ),
+ // Indexer
+ 4 => array(
+ ':'
+ ),
+ // Delimiters
+ 5 => array(
+ ',', '...', ';'
+ ),
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => true,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ 5 => true,
+ 6 => true,
+ 7 => true,
+ 8 => true,
+ 9 => true,
+ 10 => true,
+ ),
+ 'URLS' => array(
+ 1 => 'http://octave.sourceforge.net/octave/function/{FNAME}.html',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => 'http://octave.sourceforge.net/octave/function/{FNAME}.html',
+ 6 => 'http://octave.sourceforge.net/octave/function/{FNAME}.html',
+ 7 => '',
+ 8 => '',
+ 9 => 'http://octave.sourceforge.net/octave/function/{FNAME}.html',
+ 10 => 'http://octave.sourceforge.net/octave/function/{FNAME}.html',
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.',
+ ),
+ 'REGEXPS' => array(),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(),
+ 'STYLES' => array(
+ 'COMMENTS' => array(
+ 1 => 'color: #0000FF; font-style: italic;', // single quote strings
+ 2 => 'color: #0000FF; font-style: italic;', // double quote strings
+ 3 => 'color: #FF00FF; font-style: italic;', // single quote strings
+ 4 => 'color: #FF00FF; font-style: italic;', // double quote strings
+ 5 => 'color: #0000FF; font-style: italic;', // block comments
+ 6 => 'color: #996600; font-weight:bold;', // packaging system
+ 7 => 'color: #006600; font-weight:bold;', // function handles
+ 'MULTI' => 'color: #0000FF; font-style: italic;',
+ ),
+ 'KEYWORDS' => array(
+ 1 => 'color: #2E8B57; font-weight:bold;', // Data types
+ 2 => 'color: #2E8B57;', // Storage type
+ 3 => 'color: #0000FF; font-weight:bold;', // Internal variable
+ 4 => 'color: #990000; font-weight:bold;', // Reserved words
+ 5 => 'color: #008A8C; font-weight:bold;', // Built-in
+ 6 => 'color: #008A8C;', // Octave functions
+ 9 => 'color: #000000; font-weight:bold;', // Builtin Global Variables
+ 10 => 'color: #008A8C; font-weight:bold;', // Constant functions
+ ),
+ 'ESCAPE_CHAR' => array(),
+ 'BRACKETS' => array(
+ 0 => 'color: #080;',
+ ),
+ 'STRINGS' => array(
+ // strings were specified on the COMMENT_REGEXP section
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;',
+ GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+ GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+ GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+ ),
+ 'METHODS' => array(),
+ 'SYMBOLS' => array(
+ 0 => 'color: #FF9696; font-weight:bold;', // Comparison & logical
+ 1 => 'color: #CC0000; font-weight:bold;', // Aritmethical
+ 2 => 'color: #993333; font-weight:bold;', // Elementwise arithmetical
+ 3 => 'color: #FF0000; font-weight:bold;', // Arithmetical & assignation
+ 4 => 'color: #33F;', // Indexer
+ 5 => 'color: #33F;', // Delimiters
+ ),
+ 'REGEXPS' => array(),
+ 'SCRIPT' => array(),
+ )
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/oobas.php b/plugins/wp-syntax/geshi/geshi/oobas.php
index 6418059d..ff75af65 100644
--- a/plugins/wp-syntax/geshi/geshi/oobas.php
+++ b/plugins/wp-syntax/geshi/geshi/oobas.php
@@ -4,7 +4,7 @@
* ---------
* Author: Roberto Rossi (rsoftware@altervista.org)
* Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/30
*
* OpenOffice.org Basic language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/oorexx.php b/plugins/wp-syntax/geshi/geshi/oorexx.php
new file mode 100644
index 00000000..62c6cc46
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/oorexx.php
@@ -0,0 +1,171 @@
+<?php
+/*************************************************************************************
+ * oorexx.php
+ * ---------------------------------
+ * Author: Jon Wolfers (sahananda@windhorse.biz)
+ * Contributors:
+ * - Walter Pachl (pachl@chello.at)
+ * Copyright: (c) 2008 Jon Wolfers, (c) 2012 Walter Pachl
+ * Release Version: 1.0.8.11
+ * Date Started: 2008/01/07
+ *
+ * ooRexx language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2012/07/29 (1.0.0)
+ * - tried to get it syntactically right
+ *
+ * TODO (updated 2012/07/29)
+ * -------------------------
+ * - Get it working on rosettacode.org
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'ooRexx',
+ 'COMMENT_SINGLE' => array(1 => '--'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'address', 'arg', 'attribute', 'call', 'constant', 'do',
+ 'drop', 'exit', 'if',
+ 'interpret', 'iterate', 'leave', 'loop', 'nop', 'numeric',
+ 'parse', 'procedure', 'pull', 'push', 'queue',
+ 'raise', 'reply', 'return', 'say', 'select', 'signal',
+ 'use'
+ ),
+ 2 => array(
+ 'abstract', 'any', 'arguments', 'array', 'by',
+ 'continue', 'digits', 'engineering', 'error',
+ 'expose', 'external', 'failure', 'for', 'forever',
+ 'forward', 'get', 'guard', 'guarded', 'halt',
+ 'inherit', 'library', 'lostdigits', 'message',
+ 'metaclass', 'mixinclass', 'name', 'nomethod', 'nostring',
+ 'notready', 'novalue', 'off', 'on', 'options', 'over',
+ 'private', 'protected', 'public', 'scientific', 'set',
+ 'source', 'subclass', 'syntax', 'to', 'unguarded',
+ 'unprotected', 'until', 'user',
+ 'version', 'while', 'with'
+ ),
+ 3 => array(
+ 'else', 'end', 'otherwise', 'then', 'when'
+ ),
+ 4 => array(
+ 'rc', 'result', 'self', 'sigl', 'super'
+ ),
+ 5 => array(
+ '::attribute', '::class', '::constant', '::method',
+ '::optins', '::requires', '::routine'
+ ),
+ 6 => array(
+ 'abbrev', 'abs', 'beep', 'bitand', 'bitor',
+ 'bitxor', 'b2x', 'center', 'centre', 'changestr', 'charin',
+ 'charout', 'chars', 'compare', 'condition', 'copies',
+ 'countstr', 'c2d', 'c2x', 'datatype', 'date', 'delstr',
+ 'delword', 'directory', 'd2c', 'd2x', 'endlocal',
+ 'errortext', 'filespec', 'form', 'format', 'fuzz', 'insert',
+ 'lastpos', 'left', 'length', 'linein', 'lineout', 'lines',
+ 'lower', 'max', 'min', 'overlay', 'pos', 'qualify', 'queued',
+ 'random', 'reverse', 'right', 'rxfuncadd', 'rxfuncdrop',
+ 'rxfuncquery', 'rxqueue', 'setlocal', 'sign', 'sourceline',
+ 'space', 'stream', 'strip', 'substr', 'subword', 'symbol',
+ 'time', 'trace', 'translate', 'trunc', 'upper', 'userid',
+ 'value', 'var', 'verify', 'word', 'wordindex', 'wordlength',
+ 'wordpos', 'words', 'xrange', 'x2b', 'x2c', 'x2d'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '<', '>', '[', ']', '=', '+', '-', '*', '/', '!', '%', '^', '&', ':',
+ '<', '>'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => true,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #b1b100;',
+ 2 => 'color: #ff0000; font-weight: bold;',
+ 3 => 'color: #00ff00; font-weight: bold;',
+ 4 => 'color: #0000ff; font-weight: bold;',
+ 5 => 'color: #880088; font-weight: bold;',
+ 6 => 'color: #888800; font-weight: bold;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666;',
+ 'MULTI' => 'color: #808080;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #202020;',
+ 2 => 'color: #202020;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ 6 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/oracle11.php b/plugins/wp-syntax/geshi/geshi/oracle11.php
index 8444d004..16259e69 100644
--- a/plugins/wp-syntax/geshi/geshi/oracle11.php
+++ b/plugins/wp-syntax/geshi/geshi/oracle11.php
@@ -6,7 +6,7 @@
* Contributions:
* - Updated for 11i by Simon Redhead
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* Oracle 11i language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/oracle8.php b/plugins/wp-syntax/geshi/geshi/oracle8.php
index 7bd1343f..145bda40 100644
--- a/plugins/wp-syntax/geshi/geshi/oracle8.php
+++ b/plugins/wp-syntax/geshi/geshi/oracle8.php
@@ -4,7 +4,7 @@
* -----------
* Author: Guy Wicks (Guy.Wicks@rbs.co.uk)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* Oracle 8 language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/oxygene.php b/plugins/wp-syntax/geshi/geshi/oxygene.php
index a079c849..bc2ee656 100644
--- a/plugins/wp-syntax/geshi/geshi/oxygene.php
+++ b/plugins/wp-syntax/geshi/geshi/oxygene.php
@@ -4,7 +4,7 @@
* ----------
* Author: Carlo Kok (ck@remobjects.com), J�rja Norbert (jnorbi@vipmail.hu), Benny Baumann (BenBE@omorphia.de)
* Copyright: (c) 2004 J�rja Norbert, Benny Baumann (BenBE@omorphia.de), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/01/11
*
* Delphi Prism (Oxygene) language file for GeSHi.
@@ -12,6 +12,8 @@
*
* CHANGES
* -------
+ * 2012/06/28 (1.0.8.11)
+ * - Added "write" keyword for properties
* 2010/01/11 (1.0.0)
* - First Release
*
@@ -66,7 +68,7 @@ $language_data = array (
'Implies', 'Select', 'Order', 'By', 'Desc', 'Asc', 'Group', 'Join', 'Take',
'Skip', 'Concat', 'Union', 'Reverse', 'Distinct', 'Into', 'Equals', 'params',
'sequence', 'index', 'notify', 'Parallel', 'create', 'array', 'Queryable', 'Aspect',
- 'volatile'
+ 'volatile', 'write'
),
3 => array(
'chr', 'ord', 'inc', 'dec', 'assert', 'iff', 'assigned','futureAssigned', 'length', 'low', 'high', 'typeOf', 'sizeOf', 'disposeAndNil', 'Coalesce', 'unquote'
diff --git a/plugins/wp-syntax/geshi/geshi/oz.php b/plugins/wp-syntax/geshi/geshi/oz.php
index 23be8d67..d24561bf 100644
--- a/plugins/wp-syntax/geshi/geshi/oz.php
+++ b/plugins/wp-syntax/geshi/geshi/oz.php
@@ -4,7 +4,7 @@
* --------
* Author: Wolfgang Meyer (Wolfgang.Meyer@gmx.net)
* Copyright: (c) 2010 Wolfgang Meyer
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/01/03
*
* Oz language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/parasail.php b/plugins/wp-syntax/geshi/geshi/parasail.php
new file mode 100644
index 00000000..864eba1e
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/parasail.php
@@ -0,0 +1,133 @@
+<?php
+/*************************************************************************************
+ * parasail.php
+ * -------
+ * Author: T. Taft (taft@adacore.com)
+ * Copyright: (c) 2012 AdaCore (http://adacore.com/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2012/08/02
+ *
+ * ParaSail language file for GeSHi.
+ *
+ * Words are from SciTe configuration file
+ *
+ * CHANGES
+ * -------
+ * 2012/08/02 (1.0.0)
+ * - First Release
+ *
+ * TODO (updated 2012/08/02)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'ParaSail',
+ 'COMMENT_SINGLE' => array(1 => '//'),
+ 'COMMENT_MULTI' => array('{' => '}'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"'),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'all', 'block', 'case', 'continue', 'each',
+ 'else', 'elsif', 'exit', 'for',
+ 'forward', 'if', 'loop', 'return', 'reverse', 'some',
+ 'then', 'until', 'while', 'with'
+ ),
+ 2 => array(
+ 'abs', 'and','in', 'mod', 'not', 'null', 'or', 'rem', 'xor'
+ ),
+ 3 => array(
+ 'abstract', 'class',
+ 'concurrent', 'const',
+ 'end', 'extends', 'exports',
+ 'func', 'global', 'implements', 'import',
+ 'interface', 'is', 'lambda', 'locked',
+ 'new', 'of', 'op', 'optional',
+ 'private', 'queued', 'ref',
+ 'separate', 'type', 'var',
+ )
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '[', ']', '<', '>'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #00007f;',
+ 2 => 'color: #0000ff;',
+ 3 => 'color: #46aa03; font-weight:bold;',
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #adadad; font-style: italic;',
+ 'MULTI' => 'color: #808080; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #7f007f;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #202020;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/parigp.php b/plugins/wp-syntax/geshi/geshi/parigp.php
new file mode 100644
index 00000000..c9c73095
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/parigp.php
@@ -0,0 +1,277 @@
+<?php
+/*************************************************************************************
+ * parigp.php
+ * --------
+ * Author: Charles R Greathouse IV (charles@crg4.com)
+ * Copyright: 2011 Charles R Greathouse IV (http://math.crg4.com/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2011/05/11
+ *
+ * PARI/GP language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2011/07/09 (1.0.8.11)
+ * - First Release
+ *
+ * TODO (updated 2011/07/09)
+ * -------------------------
+ *
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+ 'LANG_NAME' => 'PARI/GP',
+ 'COMMENT_SINGLE' => array(1 => '\\\\'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"'),
+ 'ESCAPE_CHAR' => '\\',
+ 'NUMBERS' => array(
+ # Integers
+ 1 => GESHI_NUMBER_INT_BASIC,
+ # Reals
+ 2 => GESHI_NUMBER_FLT_SCI_ZERO
+ ),
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'addprimes','bestappr','bezout','bezoutres','bigomega','binomial',
+ 'chinese','content','contfrac','contfracpnqn','core','coredisc',
+ 'dirdiv','direuler','dirmul','divisors','eulerphi','factor',
+ 'factorback','factorcantor','factorff','factorial','factorint',
+ 'factormod','ffgen','ffinit','fflog','fforder','ffprimroot',
+ 'fibonacci','gcd','hilbert','isfundamental','ispower','isprime',
+ 'ispseudoprime','issquare','issquarefree','kronecker','lcm',
+ 'moebius','nextprime','numbpart','numdiv','omega','partitions',
+ 'polrootsff','precprime','prime','primepi','primes','qfbclassno',
+ 'qfbcompraw','qfbhclassno','qfbnucomp','qfbnupow','qfbpowraw',
+ 'qfbprimeform','qfbred','qfbsolve','quadclassunit','quaddisc',
+ 'quadgen','quadhilbert','quadpoly','quadray','quadregulator',
+ 'quadunit','removeprimes','sigma','sqrtint','stirling',
+ 'sumdedekind','zncoppersmith','znlog','znorder','znprimroot',
+ 'znstar','Col','List','Mat','Mod','Pol','Polrev','Qfb','Ser','Set',
+ 'Str','Strchr','Strexpand','Strtex','Vec','Vecrev','Vecsmall',
+ 'binary','bitand','bitneg','bitnegimply','bitor','bittest','bitxor',
+ 'ceil','centerlift','component','conj','conjvec','denominator',
+ 'floor','frac','imag','length','lift','norm','norml2','numerator',
+ 'numtoperm','padicprec','permtonum','precision','random','real',
+ 'round','simplify','sizebyte','sizedigit','truncate','valuation',
+ 'variable','ellL1','elladd','ellak','ellan','ellanalyticrank',
+ 'ellap','ellbil','ellchangecurve','ellchangepoint','ellconvertname',
+ 'elldivpol','elleisnum','elleta','ellgenerators','ellglobalred',
+ 'ellgroup','ellheight','ellheightmatrix','ellidentify','ellinit',
+ 'ellisoncurve','ellj','elllocalred','elllog','elllseries',
+ 'ellminimalmodel','ellmodulareqn','ellorder','ellordinate',
+ 'ellpointtoz','ellpow','ellrootno','ellsearch','ellsigma','ellsub',
+ 'elltaniyama','elltatepairing','elltors','ellweilpairing','ellwp',
+ 'ellzeta','ellztopoint','bnfcertify','bnfcompress',
+ 'bnfdecodemodule','bnfinit','bnfisintnorm','bnfisnorm',
+ 'bnfisprincipal','bnfissunit','bnfisunit','bnfnarrow','bnfsignunit',
+ 'bnfsunit','bnrL1','bnrclassno','bnrclassnolist','bnrconductor',
+ 'bnrconductorofchar','bnrdisc','bnrdisclist','bnrinit',
+ 'bnrisconductor','bnrisprincipal','bnrrootnumber','bnrstark',
+ 'dirzetak','factornf','galoisexport','galoisfixedfield',
+ 'galoisgetpol','galoisidentify','galoisinit','galoisisabelian',
+ 'galoisisnormal','galoispermtopol','galoissubcyclo',
+ 'galoissubfields','galoissubgroups','idealadd','idealaddtoone',
+ 'idealappr','idealchinese','idealcoprime','idealdiv','idealfactor',
+ 'idealfactorback','idealfrobenius','idealhnf','idealintersect',
+ 'idealinv','ideallist','ideallistarch','ideallog','idealmin',
+ 'idealmul','idealnorm','idealpow','idealprimedec','idealramgroups',
+ 'idealred','idealstar','idealtwoelt','idealval','matalgtobasis',
+ 'matbasistoalg','modreverse','newtonpoly','nfalgtobasis','nfbasis',
+ 'nfbasistoalg','nfdetint','nfdisc','nfeltadd','nfeltdiv',
+ 'nfeltdiveuc','nfeltdivmodpr','nfeltdivrem','nfeltmod','nfeltmul',
+ 'nfeltmulmodpr','nfeltnorm','nfeltpow','nfeltpowmodpr',
+ 'nfeltreduce','nfeltreducemodpr','nfelttrace','nfeltval','nffactor',
+ 'nffactorback','nffactormod','nfgaloisapply','nfgaloisconj',
+ 'nfhilbert','nfhnf','nfhnfmod','nfinit','nfisideal','nfisincl',
+ 'nfisisom','nfkermodpr','nfmodprinit','nfnewprec','nfroots',
+ 'nfrootsof1','nfsnf','nfsolvemodpr','nfsubfields','polcompositum',
+ 'polgalois','polred','polredabs','polredord','poltschirnhaus',
+ 'rnfalgtobasis','rnfbasis','rnfbasistoalg','rnfcharpoly',
+ 'rnfconductor','rnfdedekind','rnfdet','rnfdisc','rnfeltabstorel',
+ 'rnfeltdown','rnfeltreltoabs','rnfeltup','rnfequation',
+ 'rnfhnfbasis','rnfidealabstorel','rnfidealdown','rnfidealhnf',
+ 'rnfidealmul','rnfidealnormabs','rnfidealnormrel',
+ 'rnfidealreltoabs','rnfidealtwoelt','rnfidealup','rnfinit',
+ 'rnfisabelian','rnfisfree','rnfisnorm','rnfisnorminit','rnfkummer',
+ 'rnflllgram','rnfnormgroup','rnfpolred','rnfpolredabs',
+ 'rnfpseudobasis','rnfsteinitz','subgrouplist','zetak','zetakinit',
+ 'plot','plotbox','plotclip','plotcolor','plotcopy','plotcursor',
+ 'plotdraw','ploth','plothraw','plothsizes','plotinit','plotkill',
+ 'plotlines','plotlinetype','plotmove','plotpoints','plotpointsize',
+ 'plotpointtype','plotrbox','plotrecth','plotrecthraw','plotrline',
+ 'plotrmove','plotrpoint','plotscale','plotstring','psdraw',
+ 'psploth','psplothraw','O','deriv','diffop','eval','factorpadic',
+ 'intformal','padicappr','padicfields','polchebyshev','polcoeff',
+ 'polcyclo','poldegree','poldisc','poldiscreduced','polhensellift',
+ 'polhermite','polinterpolate','polisirreducible','pollead',
+ 'pollegendre','polrecip','polresultant','polroots','polrootsmod',
+ 'polrootspadic','polsturm','polsubcyclo','polsylvestermatrix',
+ 'polsym','poltchebi','polzagier','serconvol','serlaplace',
+ 'serreverse','subst','substpol','substvec','taylor','thue',
+ 'thueinit','break','for','fordiv','forell','forprime','forstep',
+ 'forsubgroup','forvec','if','next','return','until','while',
+ 'Strprintf','addhelp','alarm','alias','allocatemem','apply',
+ 'default','error','extern','externstr','getheap','getrand',
+ 'getstack','gettime','global','input','install','kill','print1',
+ 'print','printf','printtex','quit','read','readvec','select',
+ 'setrand','system','trap','type','version','warning','whatnow',
+ 'write1','write','writebin','writetex','divrem','lex','max','min',
+ 'shift','shiftmul','sign','vecmax','vecmin','derivnum','intcirc',
+ 'intfouriercos','intfourierexp','intfouriersin','intfuncinit',
+ 'intlaplaceinv','intmellininv','intmellininvshort','intnum',
+ 'intnuminit','intnuminitgen','intnumromb','intnumstep','prod',
+ 'prodeuler','prodinf','solve','sum','sumalt','sumdiv','suminf',
+ 'sumnum','sumnumalt','sumnuminit','sumpos','Euler','I','Pi','abs',
+ 'acos','acosh','agm','arg','asin','asinh','atan','atanh','bernfrac',
+ 'bernreal','bernvec','besselh1','besselh2','besseli','besselj',
+ 'besseljh','besselk','besseln','cos','cosh','cotan','dilog','eint1',
+ 'erfc','eta','exp','gamma','gammah','hyperu','incgam','incgamc',
+ 'lngamma','log','polylog','psi','sin','sinh','sqr','sqrt','sqrtn',
+ 'tan','tanh','teichmuller','theta','thetanullk','weber','zeta',
+ 'algdep','charpoly','concat','lindep','listcreate','listinsert',
+ 'listkill','listpop','listput','listsort','matadjoint',
+ 'matcompanion','matdet','matdetint','matdiagonal','mateigen',
+ 'matfrobenius','mathess','mathilbert','mathnf','mathnfmod',
+ 'mathnfmodid','matid','matimage','matimagecompl','matindexrank',
+ 'matintersect','matinverseimage','matisdiagonal','matker',
+ 'matkerint','matmuldiagonal','matmultodiagonal','matpascal',
+ 'matrank','matrix','matrixqz','matsize','matsnf','matsolve',
+ 'matsolvemod','matsupplement','mattranspose','minpoly','qfgaussred',
+ 'qfjacobi','qflll','qflllgram','qfminim','qfperfection','qfrep',
+ 'qfsign','setintersect','setisset','setminus','setsearch','cmp',
+ 'setunion','trace','vecextract','vecsort','vector','vectorsmall',
+ 'vectorv','ellheegner'
+ ),
+
+ 2 => array(
+ 'void','bool','negbool','small','int',/*'real',*/'mp','var','lg','pol',
+ 'vecsmall','vec','list','str','genstr','gen','typ'
+ ),
+
+ 3 => array(
+ 'TeXstyle','breakloop','colors','compatible','datadir','debug',
+ 'debugfiles','debugmem','echo','factor_add_primes','factor_proven',
+ 'format','graphcolormap','graphcolors','help','histfile','histsize',
+ 'lines','linewrap',/*'log',*/'logfile','new_galois_format','output',
+ 'parisize','path','prettyprinter','primelimit','prompt_cont',
+ 'prompt','psfile','readline','realprecision','recover','secure',
+ 'seriesprecision',/*'simplify',*/'strictmatch','timer'
+ ),
+
+ 4 => array(
+ 'alarmer','archer','errpile','gdiver','impl','syntaxer','invmoder',
+ 'overflower','talker','typeer','user'
+ )
+ ),
+ 'SYMBOLS' => array(
+ 1 => array(
+ '(',')','{','}','[',']','+','-','*','/','%','=','<','>','!','^','&','|','?',';',':',',','\\','\''
+ )
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #0000ff;',
+ 2 => 'color: #e07022;',
+ 3 => 'color: #00d2d2;',
+ 4 => 'color: #00d2d2;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #008000;',
+ 'MULTI' => 'color: #008000;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #111111; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #002222;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #800080;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #666666;',
+ 1 => 'color: #666666;',
+ 2 => 'color: #666666;'
+ ),
+ 'METHODS' => array(
+ 0 => 'color: #004000;'
+ ),
+ 'SYMBOLS' => array(
+ 1 => 'color: #339933;'
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color: #e07022', # Should be the same as keyword group 2
+ 1 => 'color: #555555'
+ ),
+ 'SCRIPT' => array()
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ 0 => array( # types marked on variables
+ GESHI_SEARCH => '(?<!\\\\ )"(t_(?:INT|REAL|INTMOD|FRAC|FFELT|COMPLEX|PADIC|QUAD|POLMOD|POL|SER|RFRAC|QFR|QFI|VEC|COL|MAT|LIST|STR|VECSMALL|CLOSURE))"',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '"',
+ GESHI_AFTER => '"'
+ ),
+ 1 => array( # literal variables
+ GESHI_SEARCH => '(?<!\\\\)(\'[a-zA-Z][a-zA-Z0-9_]*)',
+ GESHI_REPLACE => '\\1',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => ''
+ )
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ 2 => array(
+ '[a-zA-Z][a-zA-Z0-9_]*:' => ''
+ ),
+ 3 => array(
+ 'default(' => ''
+ ),
+ 4 => array(
+ 'trap(' => ''
+ ),
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/pascal.php b/plugins/wp-syntax/geshi/geshi/pascal.php
index 769566f6..de5ca871 100644
--- a/plugins/wp-syntax/geshi/geshi/pascal.php
+++ b/plugins/wp-syntax/geshi/geshi/pascal.php
@@ -4,7 +4,7 @@
* ----------
* Author: Tux (tux@inamil.cz)
* Copyright: (c) 2004 Tux (http://tux.a4.cz/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/26
*
* Pascal language file for GeSHi.
@@ -50,12 +50,13 @@
$language_data = array (
'LANG_NAME' => 'Pascal',
'COMMENT_SINGLE' => array(1 => '//'),
- 'COMMENT_MULTI' => array('{' => '}','(*' => '*)'),
+ 'COMMENT_MULTI' => array('(*' => '*)', '{' => '}'),
+ //Compiler directives
+ 'COMMENT_REGEXP' => array(2 => '/\\{\\$.*?}|\\(\\*\\$.*?\\*\\)/U'),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
- 'QUOTEMARKS' => array('"'),
- 'HARDQUOTE' => array("'", "'"),
- 'HARDESCAPE' => array("''"),
- 'ESCAPE_CHAR' => '\\',
+ 'QUOTEMARKS' => array("'"),
+ 'ESCAPE_CHAR' => '',
+
'KEYWORDS' => array(
1 => array(
'absolute','asm','assembler','begin','break','case','catch','cdecl',
@@ -67,7 +68,7 @@ $language_data = array (
'or','overload','override','private','procedure','program',
'property','protected','public','published','raise','repeat',
'resourcestring','shl','shr','stdcall','stored','switch','then',
- 'to','try','type','unit','until','uses','var','while','xor'
+ 'to','try','type','unit','until','uses','var','while','with','xor'
),
2 => array(
'nil', 'false', 'true',
@@ -83,9 +84,6 @@ $language_data = array (
'record','set','shortint','smallint','string','union','word'
),
),
- 'SYMBOLS' => array(
- ',', ':', '=', '+', '-', '*', '/'
- ),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
@@ -93,6 +91,12 @@ $language_data = array (
3 => false,
4 => false,
),
+ 'SYMBOLS' => array(
+ 0 => array('(', ')', '[', ']'),
+ 1 => array('.', ',', ':', ';'),
+ 2 => array('@', '^'),
+ 3 => array('=', '+', '-', '*', '/')
+ ),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #000000; font-weight: bold;',
@@ -101,30 +105,35 @@ $language_data = array (
4 => 'color: #000066; font-weight: bold;'
),
'COMMENTS' => array(
- 1 => 'color: #666666; font-style: italic;',
- 'MULTI' => 'color: #666666; font-style: italic;'
+ 1 => 'color: #808080; font-style: italic;',
+ 2 => 'color: #008000; font-style: italic;',
+ 'MULTI' => 'color: #808080; font-style: italic;'
),
'ESCAPE_CHAR' => array(
- 0 => 'color: #000099; font-weight: bold;',
- 'HARD' => 'color: #000099; font-weight: bold;'
+ 0 => 'color: #ff0000; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #009900;'
),
'STRINGS' => array(
0 => 'color: #ff0000;',
- 'HARD' => 'color: #ff0000;'
+ //'HARD' => 'color: #ff0000;'
),
'NUMBERS' => array(
0 => 'color: #cc66cc;'
),
'METHODS' => array(
- 1 => 'color: #0066ee;'
- ),
- 'SYMBOLS' => array(
- 0 => 'color: #339933;'
+ 1 => 'color: #006600;'
),
'REGEXPS' => array(
+ 0 => 'color: #0000cc;',
+ 1 => 'color: #ff0000;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #000066;',
+ 1 => 'color: #000066;',
+ 2 => 'color: #000066;',
+ 3 => 'color: #000066;'
),
'SCRIPT' => array(
)
@@ -140,6 +149,10 @@ $language_data = array (
1 => '.'
),
'REGEXPS' => array(
+ //Hex numbers
+ 0 => '\$[0-9a-fA-F]+',
+ //Characters
+ 1 => '\#(?:\$[0-9a-fA-F]{1,2}|\d{1,3})'
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
@@ -149,4 +162,4 @@ $language_data = array (
'TAB_WIDTH' => 4
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/pcre.php b/plugins/wp-syntax/geshi/geshi/pcre.php
index b0bd2970..13a2e024 100644
--- a/plugins/wp-syntax/geshi/geshi/pcre.php
+++ b/plugins/wp-syntax/geshi/geshi/pcre.php
@@ -4,7 +4,7 @@
* --------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2010 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/05/22
*
* PCRE language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/per.php b/plugins/wp-syntax/geshi/geshi/per.php
index 797bcab9..c42ddb58 100644
--- a/plugins/wp-syntax/geshi/geshi/per.php
+++ b/plugins/wp-syntax/geshi/geshi/per.php
@@ -4,7 +4,7 @@
* --------
* Author: Lars Gersmann (lars.gersmann@gmail.com)
* Copyright: (c) 2007 Lars Gersmann
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/06/03
*
* Per (forms) (FOURJ's Genero 4GL) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/perl.php b/plugins/wp-syntax/geshi/geshi/perl.php
index e66b52f6..309ebd86 100644
--- a/plugins/wp-syntax/geshi/geshi/perl.php
+++ b/plugins/wp-syntax/geshi/geshi/perl.php
@@ -4,7 +4,7 @@
* --------
* Author: Andreas Gohr (andi@splitbrain.org), Ben Keen (ben.keen@gmail.com)
* Copyright: (c) 2004 Andreas Gohr, Ben Keen (http://www.benjaminkeen.org/), Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/20
*
* Perl language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/perl6.php b/plugins/wp-syntax/geshi/geshi/perl6.php
index 57b8514f..706eabcb 100644
--- a/plugins/wp-syntax/geshi/geshi/perl6.php
+++ b/plugins/wp-syntax/geshi/geshi/perl6.php
@@ -4,7 +4,7 @@
* ---------
* Author: Kodi Arfer (kodiarfer {at} warpmail {period} net); forked from perl.php 1.0.8 by Andreas Gohr (andi@splitbrain.org), Ben Keen (ben.keen@gmail.com)
* Copyright: (c) 2009 Kodi Arfer, (c) 2004 Andreas Gohr, Ben Keen (http://www.benjaminkeen.org/), Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/11/07
*
* Perl 6 language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/pf.php b/plugins/wp-syntax/geshi/geshi/pf.php
index 26cfdcf5..818e11bc 100644
--- a/plugins/wp-syntax/geshi/geshi/pf.php
+++ b/plugins/wp-syntax/geshi/geshi/pf.php
@@ -4,7 +4,7 @@
* --------
* Author: David Berard (david@nfrance.com)
* Copyright: (c) 2010 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/10/16
* Based on bash.php
*
diff --git a/plugins/wp-syntax/geshi/geshi/php-brief.php b/plugins/wp-syntax/geshi/geshi/php-brief.php
index 945ea8be..a4804b4d 100644
--- a/plugins/wp-syntax/geshi/geshi/php-brief.php
+++ b/plugins/wp-syntax/geshi/geshi/php-brief.php
@@ -4,7 +4,7 @@
* -------------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/02
*
* PHP (brief version) language file for GeSHi.
@@ -169,7 +169,7 @@ $language_data = array (
),
'REGEXPS' => array(
//Variables
- 0 => "[\\$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*"
+ 0 => "[\\$]+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"
),
'STRICT_MODE_APPLIES' => GESHI_MAYBE,
'SCRIPT_DELIMITERS' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/php.php b/plugins/wp-syntax/geshi/geshi/php.php
index a7e8a584..2827457b 100644
--- a/plugins/wp-syntax/geshi/geshi/php.php
+++ b/plugins/wp-syntax/geshi/geshi/php.php
@@ -4,7 +4,7 @@
* --------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/20
*
* PHP language file for GeSHi.
@@ -96,8 +96,9 @@ $language_data = array(
),
2 => array(
'&amp;new','&lt;/script&gt;','&lt;?php','&lt;script language',
- 'class','const','declare','extends','function','global','interface',
- 'namespace','new','private','protected','public','self','use','var'
+ 'abstract','class','const','declare','extends','function','global',
+ 'interface','namespace','new','private','protected','public','self',
+ 'use','var'
),
3 => array(
'abs','acos','acosh','addcslashes','addslashes','aggregate',
@@ -1061,7 +1062,7 @@ $language_data = array(
),
'REGEXPS' => array(
//Variables
- 0 => "[\\$]{1,2}[a-zA-Z_][a-zA-Z0-9_]*"
+ 0 => "[\\$]+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"
),
'STRICT_MODE_APPLIES' => GESHI_MAYBE,
'SCRIPT_DELIMITERS' => array(
@@ -1083,22 +1084,24 @@ $language_data = array(
"(?>'(?>[^'\\\\]|\\\\'|\\\\\\\|\\\\)*')|".
"(?>\"(?>[^\"\\\\]|\\\\\"|\\\\\\\\|\\\\)*\")|".
"(?>\\/\\*(?>[^\\*]|(?!\\*\\/)\\*)*\\*\\/)|".
- "\\/\\/(?>.*?$)|".
+ "\\/\\/(?>.*?(?:\\?>|$))|".
+ "#(?>.*?(?:\\?>|$))|".
"\\/(?=[^*\\/])|".
"<(?!<<)|".
"<<<(?P<phpdoc>\w+)\s.*?\s\k<phpdoc>".
- ")*(?P<end>\\?>|\Z)/sm",
+ ")*?(?P<end>\\?>|\Z)/sm",
5 => "/(?P<start><%)(?:".
"(?>[^\"'%\\/<]+)|".
"%(?!>)|".
"(?>'(?>[^'\\\\]|\\\\'|\\\\\\\|\\\\)*')|".
"(?>\"(?>[^\\\"\\\\]|\\\\\"|\\\\\\\\|\\\\)*\")|".
"(?>\\/\\*(?>[^\\*]|(?!\\*\\/)\\*)*\\*\\/)|".
- "\\/\\/(?>.*?$)|".
+ "\\/\\/(?>.*?(?:%>|$))|".
+ "#(?>.*?(?:%>|$))|".
"\\/(?=[^*\\/])|".
"<(?!<<)|".
"<<<(?P<phpdoc>\w+)\s.*?\s\k<phpdoc>".
- ")*(?P<end>%>)/sm",
+ ")*?(?P<end>%>|\Z)/sm",
),
'HIGHLIGHT_STRICT_BLOCK' => array(
0 => true,
@@ -1111,4 +1114,4 @@ $language_data = array(
'TAB_WIDTH' => 4
);
-?> \ No newline at end of file
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/pic16.php b/plugins/wp-syntax/geshi/geshi/pic16.php
index 776a86d2..46d7ac94 100644
--- a/plugins/wp-syntax/geshi/geshi/pic16.php
+++ b/plugins/wp-syntax/geshi/geshi/pic16.php
@@ -4,7 +4,7 @@
* -------
* Author: Phil Mattison (mattison@ohmikron.com)
* Copyright: (c) 2008 Ohmikron Corp. (http://www.ohmikron.com/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/07/30
*
* PIC16 Assembler language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/pike.php b/plugins/wp-syntax/geshi/geshi/pike.php
index bc2843b0..743f711b 100644
--- a/plugins/wp-syntax/geshi/geshi/pike.php
+++ b/plugins/wp-syntax/geshi/geshi/pike.php
@@ -4,7 +4,7 @@
* --------
* Author: Rick E. (codeblock@eighthbit.net)
* Copyright: (c) 2009 Rick E.
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/12/10
*
* Pike language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/pixelbender.php b/plugins/wp-syntax/geshi/geshi/pixelbender.php
index 8cf0529d..7b29ee6c 100644
--- a/plugins/wp-syntax/geshi/geshi/pixelbender.php
+++ b/plugins/wp-syntax/geshi/geshi/pixelbender.php
@@ -4,7 +4,7 @@
* ----------------
* Author: Richard Olsson (r@richardolsson.se)
* Copyright: (c) 2008 Richard Olsson (richardolsson.se)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/11/16
*
* Pixel Bender 1.0 language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/pli.php b/plugins/wp-syntax/geshi/geshi/pli.php
new file mode 100644
index 00000000..c2998514
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/pli.php
@@ -0,0 +1,200 @@
+<?php
+/*************************************************************************************
+ * pli.php
+ * --------
+ * Author: Robert AH Prins (robert@prino.org)
+ * Copyright: (c) 2011 Robert AH Prins (http://hitchwiki.org/en/User:Prino)
+ * Release Version: 1.0.8.11
+ * Date Started: 2011/02/09
+ *
+ * PL/I language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2011/02/09 (1.0.8.10)
+ * - First Release - machine(ish) generated by http://rosettacode.org/geshi/
+ *
+ * TODO (updated 2011/02/09)
+ * -------------------------
+ *
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+ 'LANG_NAME' => 'PL/I',
+ 'COMMENT_SINGLE' => array(),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"', '\''),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'abnormal', 'abs', 'acos', 'acosf', 'add', 'addbuff', 'addr',
+ 'addrdata', 'alias', 'aligned', 'all', 'alloc', 'allocate',
+ 'allocation', 'allocn', 'allocsize', 'any', 'anycondition', 'area',
+ 'ascii', 'asin', 'asinf', 'asm', 'asmtdli', 'assembler',
+ 'assignable', 'atan', 'atand', 'atanf', 'atanh', 'attach',
+ 'attention', 'attn', 'auto', 'automatic', 'availablearea',
+ 'backwards', 'based', 'begin', 'bigendian', 'bin', 'binary',
+ 'binaryvalue', 'bind', 'binvalue', 'bit', 'bitloc', 'bitlocation',
+ 'bkwd', 'blksize', 'bool', 'buf', 'buffered', 'buffers', 'bufnd',
+ 'bufni', 'bufoff', 'bufsp', 'builtin', 'bx', 'by', 'byaddr', 'byte',
+ 'byvalue', 'b4', 'call', 'cast', 'cds', 'ceil', 'center',
+ 'centerleft', 'centerright', 'centre', 'centreleft', 'centreright',
+ 'char', 'character', 'charg', 'chargraphic', 'charval', 'check',
+ 'checkstg', 'close', 'cmpat', 'cobol', 'col', 'collate', 'column',
+ 'comment', 'compare', 'compiledate', 'compiletime', 'completion',
+ 'complex', 'cond', 'condition', 'conjg', 'conn', 'connected',
+ 'consecutive', 'controlled', 'conv', 'conversion', 'copy', 'cos',
+ 'cosd', 'cosf', 'cosh', 'count', 'counter', 'cpln', 'cplx', 'cs',
+ 'cstg', 'ctl', 'ctlasa', 'ctl360', 'currentsize', 'currentstorage',
+ 'data', 'datafield', 'date', 'datetime', 'days', 'daystodate',
+ 'daystosecs', 'db', 'dcl', 'dec', 'decimal', 'declare', 'def',
+ 'default', 'define', 'defined', 'delay', 'delete', 'descriptor',
+ 'descriptors', 'detach', 'dft', 'dim', 'dimacross', 'dimension',
+ 'direct', 'display', 'divide', 'do', 'downthru', 'edit', 'else',
+ 'empty', 'end', 'endfile', 'endpage', 'entry', 'entryaddr', 'env',
+ 'environment', 'epsilon', 'erf', 'erfc', 'error', 'event', 'excl',
+ 'exclusive', 'exit', 'exp', 'expf', 'exponent', 'exports', 'ext',
+ 'external', 'fb', 'fbs', 'fetch', 'file', 'fileddint', 'fileddtest',
+ 'fileddword', 'fileid', 'fileopen', 'fileread', 'fileseek',
+ 'filetell', 'filewrite', 'finish', 'first', 'fixed', 'fixedbin',
+ 'fixeddec', 'fixedoverflow', 'float', 'floatbin', 'floatdec',
+ 'floor', 'flush', 'fofl', 'format', 'fortran', 'free', 'from',
+ 'fromalien', 'fs', 'gamma', 'generic', 'genkey', 'get', 'getenv',
+ 'go', 'goto', 'graphic', 'gx', 'handle', 'hbound', 'hex', 'hexadec',
+ 'heximage', 'high', 'huge', 'iand', 'ieee', 'ieor', 'if', 'ignore',
+ 'imag', 'in', 'index', 'indexarea', 'indexed', 'init', 'initial',
+ 'inline', 'inonly', 'inot', 'inout', 'input', 'int', 'inter',
+ 'internal', 'into', 'invalidop', 'ior', 'irred', 'irreducible',
+ 'isfinite', 'isigned', 'isinf', 'isll', 'ismain', 'isnan',
+ 'isnormal', 'isrl', 'iszero', 'iunsigned', 'key', 'keyed',
+ 'keyfrom', 'keylength', 'keyloc', 'keyto', 'label', 'last',
+ 'lbound', 'leave', 'left', 'length', 'like', 'limited', 'line',
+ 'lineno', 'linesize', 'linkage', 'list', 'littleendian', 'loc',
+ 'locate', 'location', 'log', 'logf', 'loggamma', 'log10', 'log10f',
+ 'log2', 'low', 'lowercase', 'lower2', 'maccol', 'maclmar',
+ 'macname', 'macrmar', 'main', 'max', 'maxexp', 'maxlength',
+ 'memconvert', 'memcu12', 'memcu14', 'memcu21', 'memcu24', 'memcu41',
+ 'memcu42', 'memindex', 'memsearch', 'memsearchr', 'memverify',
+ 'memverifyr', 'min', 'minexp', 'mod', 'mpstr', 'multiply', 'name',
+ 'native', 'ncp', 'new', 'nocharg', 'nochargraphic', 'nocheck',
+ 'nocmpat', 'noconv', 'noconversion', 'nodescriptor', 'noexecops',
+ 'nofixedoverflow', 'nofofl', 'noinline', 'nolock', 'nomap',
+ 'nomapin', 'nomapout', 'nonasgn', 'nonassignable', 'nonconnected',
+ 'nonnative', 'noofl', 'nooverflow', 'norescan', 'normal', 'nosize',
+ 'nostrg', 'nostringrange', 'nostringsize', 'nostrz', 'nosubrg',
+ 'nosubscriptrange', 'noufl', 'nounderflow', 'nowrite', 'nozdiv',
+ 'nozerodivide', 'null', 'offset', 'offsetadd', 'offsetdiff',
+ 'offsetsubtract', 'offsetvalue', 'ofl', 'omitted', 'on', 'onarea',
+ 'onchar', 'oncode', 'oncondcond', 'oncondid', 'oncount', 'onfile',
+ 'ongsource', 'onkey', 'online', 'onloc', 'onoffset', 'onsource',
+ 'onsubcode', 'onwchar', 'onwsource', 'open', 'optional', 'options',
+ 'order', 'ordinal', 'ordinalname', 'ordinalpred', 'ordinalsucc',
+ 'other', 'otherwise', 'outonly', 'output', 'overflow', 'package',
+ 'packagename', 'page', 'pageno', 'pagesize', 'parameter', 'parmset',
+ 'password', 'pending', 'pic', 'picspec', 'picture', 'places',
+ 'pliascii', 'plicanc', 'plickpt', 'plidelete', 'plidump',
+ 'pliebcdic', 'plifill', 'plifree', 'plimove', 'pliover', 'plirest',
+ 'pliretc', 'pliretv', 'plisaxa', 'plisaxb', 'plisaxc', 'plisaxd',
+ 'plisrta', 'plisrtb', 'plisrtc', 'plisrtd', 'plitdli', 'plitran11',
+ 'plitran12', 'plitran21', 'plitran22', 'pointer', 'pointeradd',
+ 'pointerdiff', 'pointersubtract', 'pointervalue', 'poly', 'pos',
+ 'position', 'prec', 'precision', 'pred', 'present', 'print',
+ 'priority', 'proc', 'procedure', 'procedurename', 'procname',
+ 'prod', 'ptr', 'ptradd', 'ptrdiff', 'ptrsubtract', 'ptrvalue',
+ 'put', 'putenv', 'quote', 'radix', 'raise2', 'random', 'range',
+ 'rank', 'read', 'real', 'record', 'recsize', 'recursive', 'red',
+ 'reducible', 'reentrant', 'refer', 'regional', 'reg12', 'release',
+ 'rem', 'reorder', 'repattern', 'repeat', 'replaceby2', 'reply',
+ 'reread', 'rescan', 'reserved', 'reserves', 'resignal', 'respec',
+ 'retcode', 'return', 'returns', 'reuse', 'reverse', 'revert',
+ 'rewrite', 'right', 'round', 'rounddec', 'samekey', 'scalarvarying',
+ 'scale', 'search', 'searchr', 'secs', 'secstodate', 'secstodays',
+ 'select', 'seql', 'sequential', 'serialize4', 'set', 'sign',
+ 'signal', 'signed', 'sin', 'sind', 'sinf', 'sinh', 'sis', 'size',
+ 'skip', 'snap', 'sourcefile', 'sourceline', 'sqrt', 'sqrtf',
+ 'stackaddr', 'statement', 'static', 'status', 'stg', 'stmt', 'stop',
+ 'storage', 'stream', 'strg', 'string', 'stringrange', 'stringsize',
+ 'structure', 'strz', 'subrg', 'subscriptrange', 'substr',
+ 'subtract', 'succ', 'sum', 'suppress', 'sysin', 'sysnull',
+ 'sysparm', 'sysprint', 'system', 'sysversion', 'tally', 'tan',
+ 'tand', 'tanf', 'tanh', 'task', 'then', 'thread', 'threadid',
+ 'time', 'tiny', 'title', 'to', 'total', 'tpk', 'tpm', 'transient',
+ 'translate', 'transmit', 'trim', 'trkofl', 'trunc', 'type', 'ufl',
+ 'ulength', 'ulength16', 'ulength8', 'unal', 'unaligned',
+ 'unallocated', 'unbuf', 'unbuffered', 'undefinedfile', 'underflow',
+ 'undf', 'unlock', 'unsigned', 'unspec', 'until', 'update', 'upos',
+ 'uppercase', 'upthru', 'usubstr', 'usurrogate', 'uvalid', 'uwidth',
+ 'valid', 'validdate', 'value', 'var', 'varglist', 'vargsize',
+ 'variable', 'varying', 'varyingz', 'vb', 'vbs', 'verify', 'verifyr',
+ 'vs', 'vsam', 'wait', 'wchar', 'wcharval', 'weekday', 'when',
+ 'whigh', 'while', 'widechar', 'wlow', 'write', 'xmlchar', 'y4date',
+ 'y4julian', 'y4year', 'zdiv', 'zerodivide'
+ )
+ ),
+ 'SYMBOLS' => array(
+ 1 => array(
+ '+', '-', '*', '/', '=', '<', '>', '&', '^', '|', ':', '(', ')', ';', ','
+ )
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #b1b100;'
+ ),
+ 'COMMENTS' => array(
+ 'MULTI' => 'color: #666666; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #009900;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #0000ff;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;',
+ ),
+ 'METHODS' => array(
+ 0 => 'color: #004000;'
+ ),
+ 'SYMBOLS' => array(
+ 1 => 'color: #339933;'
+ ),
+ 'REGEXPS' => array(),
+ 'SCRIPT' => array()
+ ),
+ 'URLS' => array(1 => ''),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(1 => '.'),
+ 'REGEXPS' => array(),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(),
+ 'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/plsql.php b/plugins/wp-syntax/geshi/geshi/plsql.php
index 1a9378cd..09f90a22 100644
--- a/plugins/wp-syntax/geshi/geshi/plsql.php
+++ b/plugins/wp-syntax/geshi/geshi/plsql.php
@@ -4,7 +4,7 @@
* -------
* Author: Victor Engmark <victor.engmark@gmail.com>
* Copyright: (c) 2006 Victor Engmark (http://l0b0.net/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/10/26
*
* Oracle 9.2 PL/SQL language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/postgresql.php b/plugins/wp-syntax/geshi/geshi/postgresql.php
index c0decd0c..662fdd76 100644
--- a/plugins/wp-syntax/geshi/geshi/postgresql.php
+++ b/plugins/wp-syntax/geshi/geshi/postgresql.php
@@ -5,7 +5,7 @@
* Author: Christophe Chauvet (christophe_at_kryskool_dot_org)
* Contributors: Leif Biberg Kristensen <leif_at_solumslekt_dot_org> 2010-05-03
* Copyright: (c) 2007 Christophe Chauvet (http://kryskool.org/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/07/20
*
* PostgreSQL language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/povray.php b/plugins/wp-syntax/geshi/geshi/povray.php
index a0939bbd..c0ce35ca 100644
--- a/plugins/wp-syntax/geshi/geshi/povray.php
+++ b/plugins/wp-syntax/geshi/geshi/povray.php
@@ -4,7 +4,7 @@
* --------
* Author: Carl Fürstenberg (azatoth@gmail.com)
* Copyright: © 2007 Carl Fürstenberg
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/07/11
*
* Povray language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/powerbuilder.php b/plugins/wp-syntax/geshi/geshi/powerbuilder.php
index c694bdb9..d3fcf615 100644
--- a/plugins/wp-syntax/geshi/geshi/powerbuilder.php
+++ b/plugins/wp-syntax/geshi/geshi/powerbuilder.php
@@ -4,7 +4,7 @@
* ------
* Author: Doug Porter (powerbuilder.geshi@gmail.com)
* Copyright: (c) 2009 Doug Porter
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/07/13
*
* PowerBuilder (PowerScript) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/powershell.php b/plugins/wp-syntax/geshi/geshi/powershell.php
index 37747af4..bd78d739 100644
--- a/plugins/wp-syntax/geshi/geshi/powershell.php
+++ b/plugins/wp-syntax/geshi/geshi/powershell.php
@@ -4,7 +4,7 @@
* ---------------------------------
* Author: Frode Aarebrot (frode@aarebrot.net)
* Copyright: (c) 2008 Frode Aarebrot (http://www.aarebrot.net)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/06/20
*
* PowerShell language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/proftpd.php b/plugins/wp-syntax/geshi/geshi/proftpd.php
new file mode 100644
index 00000000..330db4b2
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/proftpd.php
@@ -0,0 +1,374 @@
+<?php
+/*************************************************************************************
+ * proftpd.php
+ * ----------
+ * Author: Benny Baumann (BenBE@geshi.org)
+ * Copyright: (c) 2010 Benny Baumann (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.11
+ * Date Started: 2011/01/25
+ *
+ * ProFTPd language file for GeSHi.
+ * Words are scraped from their documentation
+ *
+ * CHANGES
+ * -------
+ * 2004/08/05 (1.0.8.10)
+ * - First Release
+ *
+ * TODO (updated 2011/01/25)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'ProFTPd configuration',
+ 'COMMENT_SINGLE' => array(1 => '#'),
+ 'COMMENT_MULTI' => array(),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ /*keywords*/
+ 1 => array(
+ //mod_auth
+ 'AccessDenyMsg', 'AccessGrantMsg', 'AnonRejectePasswords',
+ 'AnonRequirePassword', 'AuthAliasOnly', 'AuthUsingAlias',
+ 'CreateHome', 'DefaultChdir', 'DefaultRoot', 'GroupPassword',
+ 'LoginPasswordPrompt', 'MaxClients', 'MaxClientsPerClass',
+ 'MaxClientsPerHost', 'MaxClientsPerUser', 'MaxConnectionsPerHost',
+ 'MaxHostsPerUser', 'MaxLoginAttempts', 'RequireValidShell',
+ 'RootLogin', 'RootRevoke', 'TimeoutLogin', 'TimeoutSession',
+ 'UseFtpUsers', 'UserAlias', 'UserDirRoot', 'UserPassword',
+
+ //mod_auth_file
+ 'AuthGroupFile', 'AuthUserFile',
+
+ //mod_auth_pam
+ 'AuthPAM', 'AuthPAMConfig',
+
+ //mod_auth_unix
+ 'PersistentPasswd',
+
+ //mod_ban
+ 'BanControlsACLs', 'BanEngine', 'BanLog', 'BanMessage', 'BanOnEvent',
+ 'BanTable',
+
+ //mod_cap
+ 'CapabilitiesEngine', 'CapabilitiesSet',
+
+ //mod_core
+ 'Allow', 'AllowAll', 'AllowClass', 'AllowFilter',
+ 'AllowForeignAddress', 'AllowGroup', 'AllowOverride',
+ 'AllowRetrieveRestart', 'AllowStoreRestart', 'AllowUser',
+ 'AnonymousGroup', 'AuthOrder', 'Bind', 'CDPath', 'Class', 'Classes',
+ 'CommandBufferSize', 'DebugLevel', 'DefaultAddress',
+ 'DefaultServer', 'DefaultTransferMode', 'DeferWelcome', 'Define',
+ 'Deny', 'DenyAll', 'DenyClass', 'DenyFilter', 'DenyGroup',
+ 'DenyUser', 'DisplayChdir', 'DisplayConnect', 'DisplayFirstChdir',
+ 'DisplayGoAway', 'DisplayLogin', 'DisplayQuit', 'From', 'Group',
+ 'GroupOwner', 'HideFiles', 'HideGroup', 'HideNoAccess', 'HideUser',
+ 'IdentLookups', 'IgnoreHidden', 'Include', 'MasqueradeAddress',
+ 'MaxConnectionRate', 'MaxInstances', 'MultilineRFC2228', 'Order',
+ 'PassivePorts', 'PathAllowFilter', 'PathDenyFilter', 'PidFile',
+ 'Port', 'RLimitCPU', 'RLimitMemory', 'RLimitOpenFiles', 'Satisfy',
+ 'ScoreboardFile', 'ServerAdmin', 'ServerIdent', 'ServerName',
+ 'ServerType', 'SetEnv', 'SocketBindTight', 'SocketOptions',
+ 'SyslogFacility', 'SyslogLevel', 'tcpBackLog', 'tcpNoDelay',
+ 'TimeoutIdle', 'TimeoutLinger', 'TimesGMT', 'TransferLog', 'Umask',
+ 'UnsetEnv', 'UseIPv6', 'User', 'UseReverseDNS', 'UserOwner',
+ 'UseUTF8', 'WtmpLog',
+
+ //mod_ctrls_admin
+ 'AdminControlsACLs', 'AdminControlsEngine',
+
+ //mod_delay
+ 'DelayEngine', 'DelayTable',
+
+ //mod_dynmasq
+ 'DynMasqRefresh',
+
+ //mod_exec
+ 'ExecBeforeCommand', 'ExecEngine', 'ExecEnviron', 'ExecLog',
+ 'ExecOnCommand', 'ExecOnConnect', 'ExecOnError', 'ExecOnEvent',
+ 'ExecOnExit', 'ExecOnRestart', 'ExecOptions', 'ExecTimeout',
+
+ //mod_ldap
+ 'LDAPAliasDereference', 'LDAPAttr', 'LDAPAuthBinds',
+ 'LDAPDefaultAuthScheme', 'LDAPDefaultGID', 'LDAPDefaultUID',
+ 'LDAPDNInfo', 'LDAPDoAuth', 'LDAPDoGIDLookups',
+ 'LDAPDoQuotaLookups', 'LDAPDoUIDLookups',
+ 'LDAPForceGeneratedHomedir', 'LDAPForceHomedirOnDemand',
+ 'LDAPGenerateHomedir', 'LDAPGenerateHomedirPrefix',
+ 'LDAPGenerateHomedirPrefixNoUsername', 'LDAPHomedirOnDemand',
+ 'LDAPHomedirOnDemandPrefix', 'LDAPHomedirOnDemandPrefixNoUsername',
+ 'LDAPHomedirOnDemandSuffix', 'LDAPNegativeCache',
+ 'LDAPProtocolVersion', 'LDAPQueryTimeout', 'LDAPSearchScope',
+ 'LDAPServer',
+
+ //mod_load
+ 'MaxLoad',
+
+ //mod_log
+ 'AllowLogSymlinks', 'ExtendedLog', 'LogFormat', 'ServerLog',
+ 'SystemLog',
+
+ //mod_ls'
+ 'DirFakeGroup', 'DirFakeMode', 'DirFakeUser', 'ListOptions',
+ 'ShowSymlinks', 'UseGlobbing',
+
+ //mod_quotatab
+ 'QuotaDirectoryTally', 'QuotaDisplayUnits', 'QuotaEngine',
+ 'QuotaExcludeFilter', 'QuotaLimitTable', 'QuotaLock', 'QuotaLog',
+ 'QuotaOptions', 'QuotaShowQuotas', 'QuotaTallyTable',
+
+ //mod_quotatab_file
+
+ //mod_quotatab_ldap
+
+ //mod_quotatab_sql
+
+ //mod_radius
+ 'RadiusAcctServer', 'RadiusAuthServer', 'RadiusEngine',
+ 'RadiusGroupInfo', 'RadiusLog', 'RadiusNASIdentifier',
+ 'RadiusQuotaInfo', 'RadiusRealm', 'RadiusUserInfo', 'RadiusVendor',
+
+ //mod_ratio
+ 'AnonRatio', 'ByteRatioErrMsg', 'CwdRatioMsg', 'FileRatioErrMsg',
+ 'GroupRatio', 'HostRatio', 'LeechRatioMsg', 'RatioFile', 'Ratios',
+ 'RatioTempFile', 'SaveRatios', 'UserRatio',
+
+ //mod_readme
+ 'DisplayReadme',
+
+ //mod_rewrite
+ 'RewriteCondition', 'RewriteEngine', 'RewriteLock', 'RewriteLog',
+ 'RewriteMap', 'RewriteRule',
+
+ //mod_sftp
+ 'SFTPAcceptEnv', 'SFTPAuthMethods', 'SFTPAuthorizedHostKeys',
+ 'SFTPAuthorizedUserKeys', 'SFTPCiphers', 'SFTPClientMatch',
+ 'SFTPCompression', 'SFTPCryptoDevice', 'SFTPDHParamFile',
+ 'SFTPDigests', 'SFTPDisplayBanner', 'SFTPEngine', 'SFTPExtensions',
+ 'SFTPHostKey', 'SFTPKeyBlacklist', 'SFTPKeyExchanges', 'SFTPLog',
+ 'SFTPMaxChannels', 'SFTPOptions', 'SFTPPassPhraseProvider',
+ 'SFTPRekey', 'SFTPTrafficPolicy',
+
+ //mod_sftp_pam
+ 'SFTPPAMEngine', 'SFTPPAMOptions', 'SFTPPAMServiceName',
+
+ //mod_sftp_sql
+
+ //mod_shaper
+ 'ShaperAll', 'ShaperControlsACLs', 'ShaperEngine', 'ShaperLog',
+ 'ShaperSession', 'ShaperTable',
+
+ //mod_sql
+ 'SQLAuthenticate', 'SQLAuthTypes', 'SQLBackend', 'SQLConnectInfo',
+ 'SQLDefaultGID', 'SQLDefaultHomedir', 'SQLDefaultUID', 'SQLEngine',
+ 'SQLGroupInfo', 'SQLGroupWhereClause', 'SQLHomedirOnDemand',
+ 'SQLLog', 'SQLLogFile', 'SQLMinID', 'SQLMinUserGID',
+ 'SQLMinUserUID', 'SQLNamedQuery', 'SQLNegativeCache', 'SQLOptions',
+ 'SQLRatios', 'SQLRatioStats', 'SQLShowInfo', 'SQLUserInfo',
+ 'SQLUserWhereClause',
+
+ //mod_sql_passwd
+ 'SQLPasswordEncoding', 'SQLPasswordEngine', 'SQLPasswordSaltFile',
+ 'SQLPasswordUserSalt',
+
+ //mod_tls
+ 'TLSCACertificateFile', 'TLSCACertificatePath',
+ 'TLSCARevocationFile', 'TLSCARevocationPath',
+ 'TLSCertificateChainFile', 'TLSCipherSuite', 'TLSControlsACLs',
+ 'TLSCryptoDevice', 'TLSDHParamFile', 'TLSDSACertificateFile',
+ 'TLSDSACertificateKeyFile', 'TLSEngine', 'TLSLog', 'TLSOptions',
+ 'TLSPKCS12File', 'TLSPassPhraseProvider', 'TLSProtocol',
+ 'TLSRandomSeed', 'TLSRenegotiate', 'TLSRequired',
+ 'TLSRSACertificateFile', 'TLSRSACertificateKeyFile',
+ 'TLSSessionCache', 'TLSTimeoutHandshake', 'TLSVerifyClient',
+ 'TLSVerifyDepth', 'TLSVerifyOrder',
+
+ //mod_tls_shmcache
+
+ //mod_unique_id
+ 'UniqueIDEngine',
+
+ //mod_wrap
+ 'TCPAccessFiles', 'TCPAccessSyslogLevels', 'TCPGroupAccessFiles',
+ 'TCPServiceName', 'TCPUserAccessFiles',
+
+ //mod_wrap2
+ 'WrapAllowMsg', 'WrapDenyMsg', 'WrapEngine', 'WrapGroupTables',
+ 'WrapLog', 'WrapServiceName', 'WrapTables', 'WrapUserTables',
+
+ //mod_wrap2_file
+
+ //mod_wrap2_sql
+
+ //mod_xfer
+ 'AllowOverwrite', 'DeleteAbortedStores', 'DisplayFileTransfer',
+ 'HiddenStor', 'HiddenStores', 'MaxRetrieveFileSize',
+ 'MaxStoreFileSize', 'StoreUniquePrefix', 'TimeoutNoTransfer',
+ 'TimeoutStalled', 'TransferRate', 'UseSendfile',
+
+ //unknown
+ 'ScoreboardPath', 'ScoreboardScrub'
+ ),
+ /*keywords 3*/
+ 3 => array(
+ //mod_core
+ 'Anonymous',
+ 'Class',
+ 'Directory',
+ 'IfDefine',
+ 'IfModule',
+ 'Limit',
+ 'VirtualHost',
+
+ //mod_ifsession
+ 'IfClass', 'IfGroup', 'IfUser',
+
+ //mod_version
+ 'IfVersion'
+ ),
+ /*permissions*/
+ 4 => array(
+ //mod_core
+ 'ALL',
+ 'CDUP',
+ 'CMD',
+ 'CWD',
+ 'DELE',
+ 'DIRS',
+ 'LOGIN',
+ 'MKD',
+ 'READ',
+ 'RETR',
+ 'RMD',
+ 'RNFR',
+ 'RNTO',
+ 'STOR',
+ 'WRITE',
+ 'XCWD',
+ 'XMKD',
+ 'XRMD',
+
+ //mod_copy
+ 'SITE_CPFR', 'SITE_CPTO',
+
+ //mod_quotatab
+ 'SITE_QUOTA',
+
+ //mod_site
+ 'SITE_HELP', 'SITE_CHMOD', 'SITE_CHGRP',
+
+ //mod_site_misc
+ 'SITE_MKDIR', 'SITE_RMDIR', 'SITE_SYMLINK', 'SITE_UTIME',
+ ),
+ /*keywords 2*/
+ 2 => array(
+ 'all','on','off','yes','no',
+ 'standalone', 'inetd',
+ 'default', 'auth', 'write',
+ 'internet', 'local', 'limit', 'ip',
+ 'from'
+ ),
+ ),
+ 'SYMBOLS' => array(
+ '+', '-'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #00007f;',
+ 2 => 'color: #0000ff;',
+ 3 => 'color: #000000; font-weight:bold;',
+ 4 => 'color: #000080; font-weight:bold;',
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #adadad; font-style: italic;',
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #339933;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #7f007f;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #008000;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => 'http://www.google.com/search?hl=en&amp;q={FNAMEL}+site:www.proftpd.org+inurl:docs&amp;btnI=I%27m%20Feeling%20Lucky',
+ 2 => '',
+ 3 => 'http://www.google.com/search?hl=en&amp;q={FNAMEL}+site:www.proftpd.org+inurl:docs&amp;btnI=I%27m%20Feeling%20Lucky',
+ 4 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'PARSER_CONTROL' => array(
+ 'ENABLE_FLAGS' => array(
+ 'BRACKETS' => GESHI_NEVER,
+ 'SYMBOLS' => GESHI_NEVER
+ ),
+ 'KEYWORDS' => array(
+ 2 => array(
+ 'DISALLOWED_BEFORE' => '(?<=\s)(?<!=)',
+ 'DISALLOWED_AFTER' => '(?!\+)(?!\w)',
+ ),
+ 3 => array(
+ 'DISALLOWED_BEFORE' => '(?<=&lt;|&lt;\/)',
+ 'DISALLOWED_AFTER' => '(?=\s|\/|&gt;)',
+ ),
+ 4 => array(
+ 'DISALLOWED_BEFORE' => '(?<=\s)(?<!=)',
+ 'DISALLOWED_AFTER' => '(?!\+)(?=\/|(?:\s+\w+)*\s*&gt;)',
+ )
+ )
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/progress.php b/plugins/wp-syntax/geshi/geshi/progress.php
index 3816e589..79900261 100644
--- a/plugins/wp-syntax/geshi/geshi/progress.php
+++ b/plugins/wp-syntax/geshi/geshi/progress.php
@@ -4,7 +4,7 @@
* --------
* Author: Marco Aurelio de Pasqual (marcop@hdi.com.br)
* Copyright: (c) 2008 Marco Aurelio de Pasqual, Benny Baumann (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/07/11
*
* Progress language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/prolog.php b/plugins/wp-syntax/geshi/geshi/prolog.php
index 74884974..a106a4e4 100644
--- a/plugins/wp-syntax/geshi/geshi/prolog.php
+++ b/plugins/wp-syntax/geshi/geshi/prolog.php
@@ -4,7 +4,7 @@
* --------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/10/02
*
* Prolog language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/properties.php b/plugins/wp-syntax/geshi/geshi/properties.php
index ba91639f..e1317b22 100644
--- a/plugins/wp-syntax/geshi/geshi/properties.php
+++ b/plugins/wp-syntax/geshi/geshi/properties.php
@@ -4,7 +4,7 @@
* --------
* Author: Edy Hinzen
* Copyright: (c) 2009 Edy Hinzen
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/04/03
*
* Property language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/providex.php b/plugins/wp-syntax/geshi/geshi/providex.php
index d6aab00f..1e735bd0 100644
--- a/plugins/wp-syntax/geshi/geshi/providex.php
+++ b/plugins/wp-syntax/geshi/geshi/providex.php
@@ -4,7 +4,7 @@
* ----------
* Author: Jeff Wilder (jeff@coastallogix.com)
* Copyright: (c) 2008 Coastal Logix (http://www.coastallogix.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/10/18
*
* ProvideX language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/purebasic.php b/plugins/wp-syntax/geshi/geshi/purebasic.php
index c3cfc086..d78ffe97 100644
--- a/plugins/wp-syntax/geshi/geshi/purebasic.php
+++ b/plugins/wp-syntax/geshi/geshi/purebasic.php
@@ -4,7 +4,7 @@
* -------
* Author: GuShH
* Copyright: (c) 2009 Gustavo Julio Fiorenza
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 13/06/2009
*
* PureBasic language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/pycon.php b/plugins/wp-syntax/geshi/geshi/pycon.php
new file mode 100644
index 00000000..ac2b34d0
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/pycon.php
@@ -0,0 +1,64 @@
+<?php
+/*************************************************************************************
+ * python.php
+ * ----------
+ * Author: Roberto Rossi (rsoftware@altervista.org)
+ * Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.11
+ * Date Started: 2004/08/30
+ *
+ * Python language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2008/12/18
+ * - Added missing functions and keywords. Also added two new Python 3.0 types. SF#2441839
+ * 2005/05/26
+ * - Modifications by Tim (tim@skreak.com): added more keyword categories, tweaked colors
+ * 2004/11/27 (1.0.1)
+ * - Added support for multiple object splitters
+ * 2004/08/30 (1.0.0)
+ * - First Release
+ *
+ * TODO (updated 2004/11/27)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+//This
+require(dirname(__FILE__).'/python.php');
+
+$language_data['LANG_NAME'] = 'Python (console mode)';
+
+$language_data['STRICT_MODE_APPLIES'] = GESHI_ALWAYS;
+$language_data['SCRIPT_DELIMITERS'][-1] = '/^(>>>).*?$(?:\n\.\.\..*?$)*($)/m';
+$language_data['HIGHLIGHT_STRICT_BLOCK'][-1] = true;
+
+$language_data['STYLES']['SCRIPT'][-1] = 'color: #222222;';
+
+if(!isset($language_data['COMMENT_REGEXP'])) {
+ $language_data['COMMENT_REGEXP'] = array();
+}
+
+$language_data['COMMENT_REGEXP'][-1] = '/(?:^|\A\s)(?:>>>|\.\.\.)/m';
+$language_data['STYLES']['COMMENTS'][-1] = 'color: #444444;';
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/pys60.php b/plugins/wp-syntax/geshi/geshi/pys60.php
new file mode 100644
index 00000000..59c67fac
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/pys60.php
@@ -0,0 +1,273 @@
+<?php
+/**************************************************************************************
+ * pys60.php
+ * ----------
+ * Author: Sohan Basak (ronnie.basak96 @gmail.com)
+ * Copyright: (c) 2012 Sohan Basak (http://tothepower.tk), Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
+ * Release Version: 1.0.8.11
+ * Date Started: 2012/05/03
+ *
+ * Python for S60 language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * No Changes Till Date
+ *
+ * The python.php file is extended to pys60.php with required modifications
+ *
+ * NOTES
+ *
+ * -I have kept the ":" in Reserved chars, so that it gets highlighted differently than brackets and/or symbols
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'Python for S60',
+ 'COMMENT_SINGLE' => array(1 => '#'),
+ 'COMMENT_MULTI' => array(),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"', "'", '"""',"'''",'""','""'),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+
+ /*
+ ** Set 1: reserved words
+ ** http://python.org/doc/current/ref/keywords.html
+ */
+ 1 => array(
+ 'and', 'del', 'for', 'is', 'raise', 'assert', 'elif', 'from', 'lambda', 'return', 'break',
+ 'else', 'global', 'not', 'try', 'class', 'except', 'if', 'or', 'while', 'continue', 'exec',
+ 'import', 'pass', 'yield', 'def', 'finally', 'in', 'print', "<<", ">>", "as"
+ ),
+
+ /*
+ ** Set 2: builtins
+ ** http://python.org/doc/current/lib/built-in-funcs.html
+ */
+ 2 => array(
+ '__import__', 'abs', 'basestring', 'bool', 'callable', 'chr', 'classmethod', 'cmp',
+ 'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile',
+ 'file', 'filter', 'float', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help',
+ 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'list', 'locals',
+ 'long', 'map', 'max', 'min', 'object', 'oct', 'open', 'ord', 'pow', 'property', 'range',
+ 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
+ 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode',
+ 'vars', 'xrange', 'zip',
+ // Built-in constants: http://python.org/doc/current/lib/node35.html
+ 'False', 'True', 'None', 'NotImplemented', 'Ellipsis',
+ // Built-in Exceptions: http://python.org/doc/current/lib/module-exceptions.html
+ 'Exception', 'StandardError', 'ArithmeticError', 'LookupError', 'EnvironmentError',
+ 'AssertionError', 'AttributeError', 'EOFError', 'FloatingPointError', 'IOError',
+ 'ImportError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'MemoryError', 'NameError',
+ 'NotImplementedError', 'OSError', 'OverflowError', 'ReferenceError', 'RuntimeError',
+ 'StopIteration', 'SyntaxError', 'SystemError', 'SystemExit', 'TypeError',
+ 'UnboundlocalError', 'UnicodeError', 'UnicodeEncodeError', 'UnicodeDecodeError',
+ 'UnicodeTranslateError', 'ValueError', 'WindowsError', 'ZeroDivisionError', 'Warning',
+ 'UserWarning', 'DeprecationWarning', 'PendingDeprecationWarning', 'SyntaxWarning',
+ 'RuntimeWarning', 'FutureWarning',
+ //Symbian Errors
+ "SymbianError", "KernelError",
+ // self: this is a common python convention (but not a reserved word)
+ 'self'
+ ),
+
+ /*
+ ** Set 3: standard library
+ ** http://python.org/doc/current/lib/modindex.html
+ */
+ 3 => array(
+ '__builtin__', '__future__', '__main__', '_winreg', 'aifc', 'AL', 'al', 'anydbm',
+ 'array', 'asynchat', 'asyncore', 'atexit', 'audioop', 'base64', 'BaseHTTPServer',
+ 'Bastion', 'binascii', 'binhex', 'bisect', 'bsddb', 'bz2', 'calendar', 'cd', 'cgi',
+ 'CGIHTTPServer', 'cgitb', 'chunk', 'cmath', 'cmd', 'code', 'codecs', 'codeop',
+ 'collections', 'colorsys', 'commands', 'compileall', 'compiler',
+ 'ConfigParser', 'Cookie', 'cookielib', 'copy', 'copy_reg', 'cPickle', 'crypt',
+ 'cStringIO', 'csv', 'curses', 'datetime', 'dbhash', 'dbm', 'decimal', 'DEVICE',
+ 'difflib', 'dircache', 'dis', 'distutils', 'dl', 'doctest', 'DocXMLRPCServer', 'dumbdbm',
+ 'dummy_thread', 'dummy_threading', 'email', 'encodings', 'errno', 'exceptions', 'fcntl',
+ 'filecmp', 'fileinput', 'FL', 'fl', 'flp', 'fm', 'fnmatch', 'formatter', 'fpectl',
+ 'fpformat', 'ftplib', 'gc', 'gdbm', 'getopt', 'getpass', 'gettext', 'GL', 'gl', 'glob',
+ 'gopherlib', 'grp', 'gzip', 'heapq', 'hmac', 'hotshot', 'htmlentitydefs', 'htmllib',
+ 'HTMLParser', 'httplib', 'imageop', 'imaplib', 'imgfile', 'imghdr', 'imp', 'inspect',
+ 'itertools', 'jpeg', 'keyword', 'linecache', 'locale', 'logging', 'mailbox', 'mailcap',
+ 'marshal', 'math', 'md5', 'mhlib', 'mimetools', 'mimetypes', 'MimeWriter', 'mimify',
+ 'mmap', 'msvcrt', 'multifile', 'mutex', 'netrc', 'new', 'nis', 'nntplib', 'operator',
+ 'optparse', 'os', 'ossaudiodev', 'parser', 'pdb', 'pickle', 'pickletools', 'pipes',
+ 'pkgutil', 'platform', 'popen2', 'poplib', 'posix', 'posixfile', 'pprint', 'profile',
+ 'pstats', 'pty', 'pwd', 'py_compile', 'pyclbr', 'pydoc', 'Queue', 'quopri', 'random',
+ 're', 'readline', 'resource', 'rexec', 'rgbimg', 'rlcompleter',
+ 'robotparser', 'sched', 'ScrolledText', 'select', 'sets', 'sgmllib', 'sha', 'shelve',
+ 'shlex', 'shutil', 'signal', 'SimpleHTTPServer', 'SimpleXMLRPCServer', 'site', 'smtpd',
+ 'smtplib', 'sndhdr', 'socket', 'SocketServer', 'stat', 'statcache', 'statvfs', 'string',
+ 'StringIO', 'stringprep', 'struct', 'subprocess', 'sunau', 'SUNAUDIODEV', 'sunaudiodev',
+ 'symbol', 'sys', 'syslog', 'tabnanny', 'tarfile', 'telnetlib', 'tempfile', 'termios',
+ 'test', 'textwrap', 'thread', 'threading', 'time', 'timeit', 'Tix', 'Tkinter', 'token',
+ 'tokenize', 'traceback', 'tty', 'turtle', 'types', 'unicodedata', 'unittest', 'urllib2',
+ 'urllib', 'urlparse', 'user', 'UserDict', 'UserList', 'UserString', 'uu', 'warnings',
+ 'wave', 'weakref', 'webbrowser', 'whichdb', 'whrandom', 'winsound', 'xdrlib', 'xml',
+ 'xmllib', 'xmlrpclib', 'zipfile', 'zipimport', 'zlib', "os.path", "sys.path",
+
+ //PythonS60 Standard Library
+ //http://pys60.garage.maemo.org/doc/s60/
+ //These are the standard modules in the archive
+
+ "appuifw", "globalui","e32", "telephone", "aosocket", "btsocket",
+ "sysinfo","camera","graphics","keycapture","key_codes","topwindow", "gles",
+ "glcanvas","sensor", "audio","messaging", "inbox","location","positioning",
+ "contacts", "e32calendar", "e32db","e32dbm","logs","scriptext",
+ "series60_console",
+
+ //These are external but very often usable modules
+
+ "appuifw2","ArchetypeUI","elementtree","lightblue",
+ "activaprofile","Adjustor","akntextutils","aosocketnativenew",
+ "appreciation","applicationmanager","appswitch","atextit","bt_teror","btconsole",
+ "btswitch","cElementTree","cenrep","cerealizer","cl_gui","clipboard",
+ "clipboard_CHN","debugger","decompile2",
+ "dir_iter","download","easydb","ECenrep","Edit_find","efeature","elocation","envy",
+ "EProfile","erestart","error","esyagent","Execwap","exprofile","fastcamera",
+ "feature","fgimage","filebrowser","firmware","fold","fonts","fraction","FTP",
+ "ftplibnew","fy_manager","fy_menu","gles_utils","gps_location","hack",
+ "HTML2TXT","iapconnect","icon_image","image_decoder",
+ "ini","interactive_console","inting","key_modifiers","key_tricks","keypress",
+ "landmarks","lite_fm","locationacq","locationrequestor",
+ "logo","markupbase","mbm","mbm2","minidb","miniinfo","MISC",
+ "misty","Msg","ntpath","odict","Paintbox","pathinfo","pexif","pickcolor",
+ "powlite_fm","powlite_fm2","powlite_fm3","powlite_fme","prgbar","prodb",
+ "profileengine","progressbar","progressbartw","progressnotes",
+ "ProgressBarTW2","proshivka","py_upload","pyConnection","PyFileMan",
+ "pykeylock","PyPyc","pyqq","pys60crypto","pys60usb","rfc822",
+ "RUSOS","scmk","scrollpage","SISFIELDS","SISFIELD","sisfile",
+ "SISINFO","sisreader","Sistools","smidi","smsreject","speechy","sre_compile",
+ "sre_constants","sre_parse","sre","sysagent","syslang","TextMan",
+ "textrenderer","TextWrap","topwind","tsocket","uikludge","uikludges","uitricks",
+ "walkfile","wallpaper","wfm_lite",
+ "wif_keys","wif","window","wlanmgmt","wlantools","wt_color","wt_requesters",
+ "zhkey",
+
+ //These are recent additions
+ "miffile"
+ ),
+
+ /*
+ ** Set 4: special methods
+ ** http://python.org/doc/current/ref/specialnames.html
+ */
+ 4 => array(
+ ///*
+ //// Iterator types: http://python.org/doc/current/lib/typeiter.html
+ //'__iter__', 'next',
+ //// String types: http://python.org/doc/current/lib/string-methods.html
+ //'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs',
+ //'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle',
+ //'isupper', 'join', 'ljust', 'lower', 'lstrip', 'replace', 'rfind', 'rindex', 'rjust',
+ //'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title',
+ //'translate', 'upper', 'zfill',
+ // */
+
+ // Basic customization: http://python.org/doc/current/ref/customization.html
+ '__new__', '__init__', '__del__', '__repr__', '__str__',
+ '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__cmp__', '__rcmp__',
+ '__hash__', '__nonzero__', '__unicode__', '__dict__',
+ // Attribute access: http://python.org/doc/current/ref/attribute-access.html
+ '__setattr__', '__delattr__', '__getattr__', '__getattribute__', '__get__', '__set__',
+ '__delete__', '__slots__',
+ // Class creation, callable objects
+ '__metaclass__', '__call__',
+ // Container types: http://python.org/doc/current/ref/sequence-types.html
+ '__len__', '__getitem__', '__setitem__', '__delitem__', '__iter__', '__contains__',
+ '__getslice__', '__setslice__', '__delslice__',
+ // Numeric types: http://python.org/doc/current/ref/numeric-types.html
+ '__abs__','__add__','__and__','__coerce__','__div__','__divmod__','__float__',
+ '__hex__','__iadd__','__isub__','__imod__','__idiv__','__ipow__','__iand__',
+ '__ior__','__ixor__', '__ilshift__','__irshift__','__invert__','__int__',
+ '__long__','__lshift__',
+ '__mod__','__mul__','__neg__','__oct__','__or__','__pos__','__pow__',
+ '__radd__','__rdiv__','__rdivmod__','__rmod__','__rpow__','__rlshift__','__rrshift__',
+ '__rshift__','__rsub__','__rmul__','__rand__','__rxor__','__ror__',
+ '__sub__','__xor__'
+ )
+
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '[', ']', '{', '}', '*', '&', '%', '!', ';', '<', '>', '?', '`'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => true,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #006000;font-weight:bold;', // Reserved
+ 2 => 'color: #800950;font-size:105%', // Built-ins + self
+ 3 => 'color: #003399;font-size:106%', // Standard lib
+ 4 => 'color: #0000cd;' // Special methods
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #808080; font-style:italic;font-size:92%',
+ 'MULTI' => 'color: #808080; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #930; font-weight: bold;font-size:105%'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: maroon;font-size:102%;padding:2px'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #666;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #2356F8;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: navy;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #66ccFF;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ )
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/python.php b/plugins/wp-syntax/geshi/geshi/python.php
index 0db4632d..ec9b17e6 100644
--- a/plugins/wp-syntax/geshi/geshi/python.php
+++ b/plugins/wp-syntax/geshi/geshi/python.php
@@ -4,7 +4,7 @@
* ----------
* Author: Roberto Rossi (rsoftware@altervista.org)
* Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/30
*
* Python language file for GeSHi.
@@ -49,8 +49,13 @@ $language_data = array (
'COMMENT_MULTI' => array(),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
//Longest quotemarks ALWAYS first
- 'QUOTEMARKS' => array('"""', '"', "'"),
+ 'QUOTEMARKS' => array('"""', "'''", '"', "'"),
'ESCAPE_CHAR' => '\\',
+ 'NUMBERS' =>
+ GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_BIN_PREFIX_0B |
+ GESHI_NUMBER_OCT_PREFIX_0O | GESHI_NUMBER_HEX_PREFIX |
+ GESHI_NUMBER_FLT_NONSCI | GESHI_NUMBER_FLT_NONSCI_F |
+ GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
'KEYWORDS' => array(
/*
@@ -60,7 +65,7 @@ $language_data = array (
1 => array(
'and', 'del', 'for', 'is', 'raise', 'assert', 'elif', 'from', 'lambda', 'return', 'break',
'else', 'global', 'not', 'try', 'class', 'except', 'if', 'or', 'while', 'continue', 'exec',
- 'import', 'pass', 'yield', 'def', 'finally', 'in', 'print', 'with', 'as'
+ 'import', 'pass', 'yield', 'def', 'finally', 'in', 'print', 'with', 'as', 'nonlocal'
),
/*
@@ -172,7 +177,9 @@ $language_data = array (
)
),
'SYMBOLS' => array(
- '(', ')', '[', ']', '{', '}', '*', '&', '%', '!', ';', '<', '>', '?', '`'
+ '<', '>', '=', '!', '<=', '>=', //·comparison·operators
+ '~', '@', //·unary·operators
+ ';', ',' //·statement·separator
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
@@ -234,4 +241,4 @@ $language_data = array (
)
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/q.php b/plugins/wp-syntax/geshi/geshi/q.php
index fa3717cf..ade9928d 100644
--- a/plugins/wp-syntax/geshi/geshi/q.php
+++ b/plugins/wp-syntax/geshi/geshi/q.php
@@ -4,7 +4,7 @@
* -----
* Author: Ian Roddis (ian.roddis@proteanmind.net)
* Copyright: (c) 2008 Ian Roddis (http://proteanmind.net)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/01/21
*
* q/kdb+ language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/qbasic.php b/plugins/wp-syntax/geshi/geshi/qbasic.php
index e7d12fff..3345e3c6 100644
--- a/plugins/wp-syntax/geshi/geshi/qbasic.php
+++ b/plugins/wp-syntax/geshi/geshi/qbasic.php
@@ -4,7 +4,7 @@
* ----------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/20
*
* QBasic/QuickBASIC language file for GeSHi.
@@ -62,6 +62,10 @@ $language_data = array (
'CASE_KEYWORDS' => GESHI_CAPS_UPPER,
'QUOTEMARKS' => array('"'),
'ESCAPE_CHAR' => '',
+ 'NUMBERS' =>
+ GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_FLT_NONSCI |
+ GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT |
+ GESHI_NUMBER_FLT_SCI_ZERO,
'KEYWORDS' => array(
1 => array(
'DO', 'LOOP', 'WHILE', 'WEND', 'THEN', 'ELSE', 'ELSEIF', 'IF',
diff --git a/plugins/wp-syntax/geshi/geshi/rails.php b/plugins/wp-syntax/geshi/geshi/rails.php
index 1982c678..65ddee88 100644
--- a/plugins/wp-syntax/geshi/geshi/rails.php
+++ b/plugins/wp-syntax/geshi/geshi/rails.php
@@ -4,7 +4,7 @@
* ---------
* Author: Moises Deniz
* Copyright: (c) 2005 Moises Deniz
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/03/21
*
* Ruby (with Ruby on Rails Framework) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/rebol.php b/plugins/wp-syntax/geshi/geshi/rebol.php
index 02ec8deb..ea86c21c 100644
--- a/plugins/wp-syntax/geshi/geshi/rebol.php
+++ b/plugins/wp-syntax/geshi/geshi/rebol.php
@@ -4,7 +4,7 @@
* --------
* Author: Lecanu Guillaume (Guillaume@LyA.fr)
* Copyright: (c) 2004-2005 Lecanu Guillaume (Guillaume@LyA.fr)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/12/22
*
* Rebol language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/reg.php b/plugins/wp-syntax/geshi/geshi/reg.php
index 2e0dd33a..157b2bd2 100644
--- a/plugins/wp-syntax/geshi/geshi/reg.php
+++ b/plugins/wp-syntax/geshi/geshi/reg.php
@@ -4,7 +4,7 @@
* -------
* Author: Sean Hanna (smokingrope@gmail.com)
* Copyright: (c) 2006 Sean Hanna
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 03/15/2006
*
* Microsoft Registry Editor language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/rexx.php b/plugins/wp-syntax/geshi/geshi/rexx.php
new file mode 100644
index 00000000..b3cb9322
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/rexx.php
@@ -0,0 +1,162 @@
+<?php
+/*************************************************************************************
+ * rexx.php
+ * ---------------------------------
+ * Author: Jon Wolfers (sahananda@windhorse.biz)
+ * Contributors:
+ * - Walter Pachl (pachl@chello.at)
+ * Copyright: (c) 2008 Jon Wolfers, (c) 2012 Walter Pachl
+ * Release Version: 1.0.8.11
+ * Date Started: 2008/01/07
+ *
+ * Rexx language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2012/07/29 (1.0.0)
+ * - tried to get it syntactically right
+ *
+ * TODO (updated 2012/07/29)
+ * -------------------------
+ * - Get it working on rosettacode.org
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'rexx',
+ 'COMMENT_SINGLE' => array(1 => '--'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'address', 'arg', 'attribute', 'call', 'constant', 'do',
+ 'drop', 'exit', 'forward', 'if',
+ 'interpret', 'iterate', 'leave', 'loop', 'nop', 'numeric',
+ 'options', 'parse', 'procedure', 'pull', 'push', 'queue',
+ 'raise', 'return', 'say', 'select', 'signal', 'trace'
+ ),
+ 2 => array(
+ 'by', 'digits', 'engineering', 'error', 'expose',
+ 'failure', 'for', 'forever', 'form', 'fuzz', 'halt',
+ 'name', 'novalue', 'off', 'on', 'over', 'scientific', 'source',
+ 'syntax', 'to', 'until', 'upper', 'version',
+ 'while', 'with'
+ ),
+ 3 => array(
+ 'else', 'end', 'otherwise', 'then', 'when'
+ ),
+ 4 => array(
+ 'rc', 'result', 'sigl'
+ ),
+ 5 => array(
+ 'placeholderforoorexxdirectives'
+ ),
+ 6 => array(
+ 'abbrev', 'abs', 'beep', 'bitand', 'bitor',
+ 'bitxor', 'b2x', 'center', 'centre', 'changestr', 'charin',
+ 'charout', 'chars', 'compare', 'condition', 'copies',
+ 'countstr', 'c2d', 'c2x', 'datatype', 'date', 'delstr',
+ 'delword', 'directory', 'd2c', 'd2x', 'endlocal',
+ 'errortext', 'filespec', 'format', 'insert',
+ 'lastpos', 'left', 'length', 'linein', 'lineout', 'lines',
+ 'lower', 'max', 'min', 'overlay', 'pos', 'queued', 'random',
+ 'reverse', 'right', 'rxfuncadd', 'rxfuncdrop', 'rxfuncquery',
+ 'rxqueue', 'setlocal', 'sign', 'sourceline', 'space',
+ 'stream', 'strip', 'substr', 'subword', 'symbol', 'time',
+ 'translate', 'trunc', 'userid', 'value',
+ 'var', 'verify', 'word', 'wordindex', 'wordlength', 'wordpos',
+ 'words', 'xrange', 'x2b', 'x2c', 'x2d'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '<', '>', '=', '+', '-', '*', '**', '/', '|', '%', '^', '&', ':'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => true,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #b1b100;',
+ 2 => 'color: #ff0000; font-weight: bold;',
+ 3 => 'color: #00ff00; font-weight: bold;',
+ 4 => 'color: #0000ff; font-weight: bold;',
+ 5 => 'color: #880088; font-weight: bold;',
+ 6 => 'color: #888800; font-weight: bold;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666;',
+ 'MULTI' => 'color: #808080;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #202020;',
+ 2 => 'color: #202020;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ 6 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/robots.php b/plugins/wp-syntax/geshi/geshi/robots.php
index 838eddbc..0b75f711 100644
--- a/plugins/wp-syntax/geshi/geshi/robots.php
+++ b/plugins/wp-syntax/geshi/geshi/robots.php
@@ -4,7 +4,7 @@
* --------
* Author: Christian Lescuyer (cl@goelette.net)
* Copyright: (c) 2006 Christian Lescuyer http://xtian.goelette.info
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/02/17
*
* robots.txt language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/rpmspec.php b/plugins/wp-syntax/geshi/geshi/rpmspec.php
index 7f2a8e5d..fd6a561f 100644
--- a/plugins/wp-syntax/geshi/geshi/rpmspec.php
+++ b/plugins/wp-syntax/geshi/geshi/rpmspec.php
@@ -4,7 +4,7 @@
* ---------------------------------
* Author: Paul Grinberg (gri6507 TA unity-linux TOD org)
* Copyright: (c) 2010 Paul Grinberg
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/04/27
*
* RPM Spec language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/rsplus.php b/plugins/wp-syntax/geshi/geshi/rsplus.php
index ef09b238..e8a4e722 100644
--- a/plugins/wp-syntax/geshi/geshi/rsplus.php
+++ b/plugins/wp-syntax/geshi/geshi/rsplus.php
@@ -5,8 +5,9 @@
* Author: Ron Fredericks (ronf@LectureMaker.com)
* Contributors:
* - Benilton Carvalho (beniltoncarvalho@gmail.com)
+ * - Fernando Henrique Ferraz Pereira da Rosa (mentus@gmail.com)
* Copyright: (c) 2009 Ron Fredericks (http://www.LectureMaker.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/03/28
*
* R language file for GeSHi.
@@ -440,18 +441,17 @@ $language_data = array (
0 => 'color:#A020F0;'
),
'SCRIPT' => array(
- 0 => ''
- )
+ 0 => '' )
),
'URLS' => array(
1 => '',
- 2 => 'http://astrostatistics.psu.edu/su07/R/html/graphics/html/{FNAME}.html', // http://sekhon.berkeley.edu/library/graphics/html/{FNAME}.html
- 3 => 'http://astrostatistics.psu.edu/su07/R/html/stats/html/Normal.html', // http://sekhon.berkeley.edu/library/stats/html/Normal.html
- 4 => 'http://astrostatistics.psu.edu/su07/R/html/stats/html/{FNAME}.html', // http://sekhon.berkeley.edu/library/stats/html/{FNAME}.html
- 5 => 'http://astrostatistics.psu.edu/su07/R/html/stats/html/summary.lm.html', // http://sekhon.berkeley.edu/library/stats/html/summary.lm.html
- 6 => 'http://astrostatistics.psu.edu/su07/R/html/base/html/Log.html', // http://sekhon.berkeley.edu/library/base/html/Log.html
- 7 => '',
- 8 => ''
+ 2 => 'http://stat.ethz.ch/R-manual/R-devel/library/base/html/{FNAME}.html', // Base Package
+ 3 => 'http://stat.ethz.ch/R-manual/R-devel/library/datasets/html/{FNAME}.html', // Datasets
+ 4 => 'http://stat.ethz.ch/R-manual/R-devel/library/graphics/html/{FNAME}.html', // Graphics Package
+ 5 => 'http://stat.ethz.ch/R-manual/R-devel/library/grDevices/html/{FNAME}.html', // grDevices
+ 6 => 'http://stat.ethz.ch/R-manual/R-devel/library/methods/html/{FNAME}.html', // methods
+ 7 => 'http://stat.ethz.ch/R-manual/R-devel/library/stats/html/{FNAME}.html', // stats
+ 8 => 'http://stat.ethz.ch/R-manual/R-devel/library/utils/html/{FNAME}.html' // utils
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/ruby.php b/plugins/wp-syntax/geshi/geshi/ruby.php
index 69e395e1..f6eb1b1e 100644
--- a/plugins/wp-syntax/geshi/geshi/ruby.php
+++ b/plugins/wp-syntax/geshi/geshi/ruby.php
@@ -4,7 +4,7 @@
* --------
* Author: Moises Deniz
* Copyright: (c) 2007 Moises Deniz
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/03/21
*
* Ruby language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/sas.php b/plugins/wp-syntax/geshi/geshi/sas.php
index ba1f85ad..dbf95a14 100644
--- a/plugins/wp-syntax/geshi/geshi/sas.php
+++ b/plugins/wp-syntax/geshi/geshi/sas.php
@@ -4,7 +4,7 @@
* -------
* Author: Galen Johnson (solitaryr@gmail.com)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/12/27
*
* SAS language file for GeSHi. Based on the sas vim file.
@@ -44,7 +44,7 @@
$language_data = array (
'LANG_NAME' => 'SAS',
'COMMENT_SINGLE' => array(),
- 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_MULTI' => array('/*' => '*/', '*' => ';'),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array("'", '"'),
'ESCAPE_CHAR' => '\\',
@@ -287,4 +287,4 @@ $language_data = array (
)
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/scala.php b/plugins/wp-syntax/geshi/geshi/scala.php
index 58e7d234..405f59de 100644
--- a/plugins/wp-syntax/geshi/geshi/scala.php
+++ b/plugins/wp-syntax/geshi/geshi/scala.php
@@ -4,7 +4,7 @@
* ----------
* Author: Franco Lombardo (franco@francolombardo.net)
* Copyright: (c) 2008 Franco Lombardo, Benny Baumann
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/02/08
*
* Scala language file for GeSHi.
@@ -41,9 +41,20 @@ $language_data = array (
'LANG_NAME' => 'Scala',
'COMMENT_SINGLE' => array(1 => '//'),
'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_REGEXP' => array(2 => "/\\'(?!\w\\'|\\\\)\w+(?=\s)/"),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
- 'QUOTEMARKS' => array("'", '"'),
+ 'QUOTEMARKS' => array("'",'"'),
'ESCAPE_CHAR' => '\\',
+ 'ESCAPE_REGEXP' => array(
+ //Simple Single Char Escapes
+ 1 => "#\\\\[nfrtv\$\"\n\\\\]#i",
+ //Hexadecimal Char Specs
+ 2 => "#\\\\x[\da-fA-F]{1,2}#i",
+ //Hexadecimal Char Specs (unicode)
+ 3 => "#\\\\u[\da-fA-F]{1,4}#",
+ //Hexadecimal Char Specs (Extended Unicode)
+ 4 => "#\\\\U[\da-fA-F]{1,8}#",
+ ),
'KEYWORDS' => array(
1 => array(
'abstract', 'case', 'catch', 'class', 'def',
@@ -75,11 +86,16 @@ $language_data = array (
2 => 'color: #9999cc; font-weight: bold;',
),
'COMMENTS' => array(
- 1=> 'color: #008000; font-style: italic;',
+ 1 => 'color: #008000; font-style: italic;',
+ 2 => 'color: #CC66FF;',
'MULTI' => 'color: #00ff00; font-style: italic;'
),
'ESCAPE_CHAR' => array(
- 0 => 'color: #0000ff; font-weight: bold;'
+ 0 => 'color: #6666ff; font-weight: bold;',
+ 1 => 'color: #6666ff; font-weight: bold;',
+ 2 => 'color: #5555ff; font-weight: bold;',
+ 3 => 'color: #4444ff; font-weight: bold;',
+ 4 => 'color: #3333ff; font-weight: bold;'
),
'BRACKETS' => array(
0 => 'color: #F78811;'
@@ -119,4 +135,4 @@ $language_data = array (
)
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/scheme.php b/plugins/wp-syntax/geshi/geshi/scheme.php
index 72589141..a84b9080 100644
--- a/plugins/wp-syntax/geshi/geshi/scheme.php
+++ b/plugins/wp-syntax/geshi/geshi/scheme.php
@@ -4,7 +4,7 @@
* ----------
* Author: Jon Raphaelson (jonraphaelson@gmail.com)
* Copyright: (c) 2005 Jon Raphaelson, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/30
*
* Scheme language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/scilab.php b/plugins/wp-syntax/geshi/geshi/scilab.php
index b2636c73..f011497d 100644
--- a/plugins/wp-syntax/geshi/geshi/scilab.php
+++ b/plugins/wp-syntax/geshi/geshi/scilab.php
@@ -4,7 +4,7 @@
* --------
* Author: Christophe David (geshi@christophedavid.org)
* Copyright: (c) 2008 Christophe David (geshi@christophedavid.org)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/08/04
*
* SciLab language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/sdlbasic.php b/plugins/wp-syntax/geshi/geshi/sdlbasic.php
index 9bb8058d..381161fd 100644
--- a/plugins/wp-syntax/geshi/geshi/sdlbasic.php
+++ b/plugins/wp-syntax/geshi/geshi/sdlbasic.php
@@ -4,7 +4,7 @@
* ------------
* Author: Roberto Rossi
* Copyright: (c) 2005 Roberto Rossi (http://rsoftware.altervista.org)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/08/19
*
* sdlBasic (http://sdlbasic.sf.net) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/smalltalk.php b/plugins/wp-syntax/geshi/geshi/smalltalk.php
index f8b30168..5b61bada 100644
--- a/plugins/wp-syntax/geshi/geshi/smalltalk.php
+++ b/plugins/wp-syntax/geshi/geshi/smalltalk.php
@@ -4,7 +4,7 @@
* --------
* Author: Bananeweizen (Bananeweizen@gmx.de)
* Copyright: (c) 2005 Bananeweizen (www.bananeweizen.de)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/03/27
*
* Smalltalk language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/smarty.php b/plugins/wp-syntax/geshi/geshi/smarty.php
index 1f9f0219..86e9d44c 100644
--- a/plugins/wp-syntax/geshi/geshi/smarty.php
+++ b/plugins/wp-syntax/geshi/geshi/smarty.php
@@ -4,7 +4,7 @@
* ----------
* Author: Alan Juden (alan@judenware.org)
* Copyright: (c) 2004 Alan Juden, Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/07/10
*
* Smarty template language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/spark.php b/plugins/wp-syntax/geshi/geshi/spark.php
new file mode 100644
index 00000000..0284a1a4
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/spark.php
@@ -0,0 +1,132 @@
+<?php
+/*************************************************************************************
+ * ada.php
+ * -------
+ * Author: Phil Thornley (tux@inmail.cz)
+ * Copyright: (c) 2004 Phil Thornley (http://www.sparksure.com)
+ * Release Version: 1.0.8.11
+ * Date Started: 2010/08/22
+ *
+ * SPARK language file for GeSHi.
+ *
+ * Created by modifying Ada file version 1.0.2
+ * Words are from SciTe configuration file
+ *
+ * CHANGES
+ * -------
+ * 2010/08/28 (1.0.0)
+ * - First Release
+ *
+ * TODO (updated 2010/08/22)
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'SPARK',
+ 'COMMENT_SINGLE' => array(1 => '--', 2 => '--#'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"'),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'begin', 'declare', 'do', 'else', 'elsif', 'exception', 'for', 'if',
+ 'is', 'loop', 'while', 'then', 'end', 'select', 'case', 'until',
+ 'goto', 'return'
+ ),
+ 2 => array(
+ 'abs', 'and', 'at', 'mod', 'not', 'or', 'rem', 'xor'
+ ),
+ 3 => array(
+ 'abort', 'abstract', 'accept', 'access', 'aliased', 'all', 'array',
+ 'body', 'constant', 'delay', 'delta', 'digits', 'entry', 'exit',
+ 'function', 'generic', 'in', 'interface', 'limited', 'new', 'null',
+ 'of', 'others', 'out', 'overriding', 'package', 'pragma', 'private',
+ 'procedure', 'protected', 'raise', 'range', 'record', 'renames',
+ 'requeue', 'reverse', 'separate', 'subtype', 'synchronized',
+ 'tagged', 'task', 'terminate', 'type', 'use', 'when', 'with'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '(', ')'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #00007f;',
+ 2 => 'color: #0000ff;',
+ 3 => 'color: #46aa03; font-weight:bold;',
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #adadad; font-style: italic;',
+ 2 => 'color: #adadad; font-style: italic; font-weight: bold;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #7f007f;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #202020;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #66cc66;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/sparql.php b/plugins/wp-syntax/geshi/geshi/sparql.php
new file mode 100644
index 00000000..282165a0
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/sparql.php
@@ -0,0 +1,155 @@
+<?php
+/*************************************************************************************
+ * sparql.php
+ * -------
+ * Author: Karima Rafes (karima.rafes@bordercloud.com)
+ * Copyright: (c) 2011 Bourdercloud.com
+ * Release Version: 1.0.8.11
+ * Date Started: 2011/11/05
+ *
+ * SPARQL language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2011/11/05 (1.0.0)
+ * - First Release
+ *
+ * TODO
+ * ----
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'SPARQL',
+ 'COMMENT_SINGLE' => array('#'),
+ 'COMMENT_MULTI' => array('/*' => '*/' ),
+ 'COMMENT_REGEXP' => array(
+ //IRI (it's not a comment ;)
+ 1 => "/<[^> ]*>/i"
+ ),
+ 'CASE_KEYWORDS' => 1,
+ 'QUOTEMARKS' => array("'", '"', '`'),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'BASE','PREFIX','SELECT','DISTINCT','REDUCED','CONSTRUCT','DESCRIBE','ASK','FROM',
+ 'NAMED','WHERE','ORDER','BY','ASC','DESC','LIMIT','OFFSET','OPTIONAL','GRAPH',
+ 'UNION','FILTER','STR','LANG','LANGMATCHES','DATATYPE','BOUND','SAMETERM',
+ 'ISIRI','ISURI','ISBLANK',
+ 'ISLITERAL','REGEX','SUBSTR','TRUE',
+ 'FALSE','LOAD','CLEAR',
+ 'DROP','ADD','MOVE','COPY',
+ 'CREATE','DELETE','INSERT',
+ 'USING','SILENT','DEFAULT','ALL',
+ 'DATA','WITH','INTO','TO',
+ 'AS','GROUP','HAVING','UNDEF',
+ 'BINDINGS','SERVICE','BIND','MINUS_KEYWORD',
+ 'IRI','URI', 'BNODE',
+ 'RAND','ABS','CEIL','FLOOR','ROUND',
+ 'CONCAT','STRLEN',
+ 'UCASE','LCASE','ENCODE_FOR_URI',
+ 'CONTAINS','STRSTARTS',
+ 'STRENDS','STRBEFORE',
+ 'STRAFTER','REPLACE',
+ 'YEAR','MONTH',
+ 'DAY','HOURS',
+ 'MINUTES','SECONDS',
+ 'TIMEZONE','TZ',
+ 'NOW','MD5',
+ 'SHA1','SHA224',
+ 'SHA256','SHA384',
+ 'SHA512','COALESCE',
+ 'IF','STRLANG','STRDT',
+ 'ISNUMERIC','COUNT',
+ 'SUM','MIN',
+ 'MAX','AVG','SAMPLE',
+ 'GROUP_CONCAT ','NOT',
+ 'IN','EXISTS','SEPARATOR'
+ )
+ ),
+ 'REGEXPS' => array(
+ //Variables without braces
+ 1 => "\\?[a-zA-Z_][a-zA-Z0-9_]*",
+ //prefix
+ 2 => "[a-zA-Z_.\\-0-9]*:",
+ //tag lang
+ 3 => "@[^ .)}]*",
+ ),
+ 'SYMBOLS' => array(
+ 0 => array(
+ '{', '}' , '.', ';'
+ ),
+ 1 => array(
+ '^^',
+ '<=','>=','!=','=','<','>','|',
+ '&&','||',
+ '(',')','[', ']',
+ '+','-','*','!','/'
+ ),
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #993333; font-weight: bold;'
+ ),
+ 'COMMENTS' => array(
+ 0 => 'color: #808080; font-style: italic;',
+ 1 => 'color: #000078;',
+ //2 => 'color: #808080; font-style: italic;',
+ 'MULTI' => 'color: #808080; font-style: italic;',
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(),
+ 'STRINGS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #FF63C3;'
+ ),
+ 'METHODS' => array(
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #0000FF;',
+ 1 => 'color: #FF8000; font-weight: bold;'
+ ),
+ 'SCRIPT' => array(),
+ 'REGEXPS' => array(
+ 1 => 'color: #007800;',
+ 2 => 'color: #780078;',
+ 3 => 'color: #005078;'
+ )
+ ),
+ 'URLS' => array(
+ 1 => ''
+ ),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(),
+ 'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/sql.php b/plugins/wp-syntax/geshi/geshi/sql.php
index 4d1d5192..4d08a51f 100644
--- a/plugins/wp-syntax/geshi/geshi/sql.php
+++ b/plugins/wp-syntax/geshi/geshi/sql.php
@@ -6,7 +6,7 @@
* Contributors:
* - Jürgen Thomas (Juergen.Thomas@vs-polis.de)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* SQL language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/stonescript.php b/plugins/wp-syntax/geshi/geshi/stonescript.php
new file mode 100644
index 00000000..2844e885
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/stonescript.php
@@ -0,0 +1,307 @@
+<?php
+/*************************************************************************************
+ * stonescript.php
+ * --------
+ * Author: Archimmersion ( based on ruby.php by Moises Deniz )
+ * Copyright: (c) 2011 Archimmersion ( http://www.archimmersion.com )
+ * Release Version: 1.0.8.11
+ * Date Started: 2011/03/30
+ *
+ * StoneScript language file for GeSHi.
+ *
+ * StonesCript is a Lua based script language for the ShiVa3D game engine ( http://www.stonetrip.com )
+ *
+ * More information can be found at http://www.stonetrip.com/developer/doc/api/introduction
+ *
+ * CHANGES
+ * -------
+ * 2011/04/18 (1.0.8.11)
+ * - Initial release
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'StoneScript',
+ 'COMMENT_SINGLE' => array(1 => "--"),
+ 'COMMENT_MULTI' => array("--[[" => "]]"),
+ 'COMMENT_REGEXP' => array(
+ 4 => '/<<\s*?(\w+)\\n.*?\\n\\1(?![a-zA-Z0-9])/si',
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"', '`','\''),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ // Blue - General Keywords
+ 1 => array(
+ 'and', 'begin', 'break', 'do', 'else', 'elseif', 'end',
+ 'for', 'if', 'in', 'while', 'next', 'not', 'or', 'redo',
+ 'then', 'unless', 'until', 'when', 'false', 'nil', 'self',
+ 'true', 'local', 'this', 'return',
+ ),
+ // Dark Blue - Main API names
+ 2 => array(
+ 'animation', 'application', 'cache', 'camera', 'debug',
+ 'dynamics', 'group', 'hashtable', 'hud', 'input', 'light',
+ 'log', 'math', 'mesh', 'microphone', 'music', 'navigation',
+ 'network', 'object', 'pixelmap', 'projector', 'scene',
+ 'sensor', 'server', 'session', 'sfx', 'shape', 'sound',
+ 'string', 'system', 'table', 'user', 'video', 'xml',
+ // Plugin API names
+ 'plasma', 'watersim',
+ 'winDirectories',
+ 'ActionSheet', 'Alert', 'Mail', 'Picker', 'StatusBar',
+ ),
+ // Constants
+ // Can be commented out if performance is crucial -> then these keywords will appear in a slightly lighter color
+ 3 => array(
+ //Animation
+ 'kPlaybackModeLoop', 'kPlaybackModeLoopMirrored', 'kPlaybackModeLoopReversed',
+ 'kPlaybackModeOnce', 'kPlaybackModeOnceReversed',
+ //Application - Environment
+ 'kStatusLoading', 'kStatusReady', 'kStatusSaving', // 'kStatusNone'
+ //Application - Options
+ 'kOptionAudioMasterVolume', 'kOptionAutomaticVirtualKeyboard', 'kOptionDynamicShadowsBufferCount',
+ 'kOptionDynamicShadowsBufferSize', 'kOptionDynamicShadowsConstantSampling', 'kOptionDynamicShadowsPCFSampleCount',
+ 'kOptionDynamicShadowsQuality', 'kOptionDynamicShadowsScreenSpaceBlur', 'kOptionFullscreen',
+ 'kOptionFullscreenHeight', 'kOptionFullscreenWidth', 'kOptionHardwareOcclusion',
+ 'kOptionMaxEventBouncesPerFrame', 'kOptionNetworkStreams', 'kOptionNetworkStreamsUseBrowser',
+ 'kOptionPrioritizeEventBounces', 'kOptionRenderingEnabled', 'kOptionShadersQuality',
+ 'kOptionSwapInterval', 'kOptionTerrainsQuality', 'kOptionTexturesAnisotropyLevel',
+ 'kOptionTexturesMipmapBias', 'kOptionTexturesQuality', 'kOptionViewportRotation',
+ //Application - Resource Types
+ 'kResourceTypeAnimBank', 'kResourceTypeFont', 'kResourceTypeHUD',
+ 'kResourceTypeMaterial', 'kResourceTypeMesh', 'kResourceTypeParticle',
+ 'kResourceTypePixelMap', 'kResourceTypeSoundBank', 'kResourceTypeTexture',
+ 'kResourceTypeTextureClip', 'kResourceTypeTrail',
+ //Cache
+ 'kPropertyHeight', 'kPropertySize', 'kPropertyWidth',
+ //Dynamics
+ 'kAxisX', 'kAxisY', 'kAxisZ',
+ 'kTypeBox', 'kTypeCapsule', 'kTypeSphere',
+ //HUD
+ 'kAddressingModeClamp', 'kAddressingModeRepeat', 'kAlignCenter', 'kAlignJustify','kAlignLeft', 'kAlignRight',
+ 'kAlignTop', 'kBlendModeAdd', 'kBlendModeDefault', 'kBlendModeModulate', 'kCaseFixed', 'kCaseVariable',
+ 'kCommandTypeCallAction', 'kCommandTypeCopyCheckStateToRegister', 'kCommandTypeCopyEditTextToRegister',
+ 'kCommandTypeCopyListItemTextToRegister', 'kCommandTypeCopyListLastSelectedItemToRegister',
+ 'kCommandTypeCopyProgressValueToRegister', 'kCommandTypeCopySliderValueToRegister', 'kCommandTypeCopyTagToRegister',
+ 'kCommandTypeEnterModalMode', 'kCommandTypeInterpolateBackgroundColor', 'kCommandTypeInterpolateBorderColor',
+ 'kCommandTypeInterpolateForegroundColor', 'kCommandTypeInterpolateHeight', 'kCommandTypeInterpolateOpacity',
+ 'kCommandTypeInterpolatePosition', 'kCommandTypeInterpolateProgressValue', 'kCommandTypeInterpolateRotation',
+ 'kCommandTypeInterpolateSize', 'kCommandTypeInterpolateWidth', 'kCommandTypeLeaveModalMode',
+ 'kCommandTypeMatchScreenSpaceBottomLeftCorner', 'kCommandTypeMatchScreenSpaceBottomRightCorner',
+ 'kCommandTypeMatchScreenSpaceCenter', 'kCommandTypeMatchScreenSpaceHeight', 'kCommandTypeMatchScreenSpaceTopLeftCorner',
+ 'kCommandTypeMatchScreenSpaceTopRightCorner', 'kCommandTypeMatchScreenSpaceWidth', 'kCommandTypePauseMovie',
+ 'kCommandTypePauseSound', 'kCommandTypePauseTimer', 'kCommandTypePlayMovie', 'kCommandTypePlaySound',
+ 'kCommandTypePlaySoundLoop', 'kCommandTypeResumeSound', 'kCommandTypeSendEventToUser', 'kCommandTypeSetActive',
+ 'kCommandTypeSetBackgroundColor', 'kCommandTypeSetBackgroundImage', 'kCommandTypeSetBackgroundImageUVOffset',
+ 'kCommandTypeSetBackgroundImageUVScale', 'kCommandTypeSetBorderColor', 'kCommandTypeSetButtonText',
+ 'kCommandTypeSetCheckState', 'kCommandTypeSetCheckText', 'kCommandTypeSetCursorPosition', 'kCommandTypeSetCursorVisible',
+ 'kCommandTypeSetEditText', 'kCommandTypeSetFocus', 'kCommandTypeSetForegroundColor', 'kCommandTypeSetHeight',
+ 'kCommandTypeSetLabelText', 'kCommandTypeSetOpacity', 'kCommandTypeSetPosition', 'kCommandTypeSetRotation',
+ 'kCommandTypeSetSize', 'kCommandTypeSetVisible', 'kCommandTypeSetWidth', 'kCommandTypeSleep', 'kCommandTypeStartTimer',
+ 'kCommandTypeStopAction', 'kCommandTypeStopMovie', 'kCommandTypeStopSound', 'kCommandTypeStopTimer',
+ 'kComponentTypeButton', 'kComponentTypeCheck', 'kComponentTypeContainer', 'kComponentTypeEdit', 'kComponentTypeLabel',
+ 'kComponentTypeList', 'kComponentTypeMovie', 'kComponentTypePicture', 'kComponentTypePixelMap', 'kComponentTypeProgress',
+ 'kComponentTypeRenderMap', 'kComponentTypeSlider', 'kCursorShapeCross', 'kCursorShapeDefault', 'kCursorShapeHandPointing',
+ 'kCursorShapeIBeam', 'kCursorShapeNone', 'kCursorShapeWaiting', 'kDirectionLeftToRight', 'kDirectionRightToLeft',
+ 'kEncodingASCII', 'kEncodingUTF8', 'kEventTypeGainFocus', 'kEventTypeLooseFocus', 'kEventTypeMouseEnter',
+ 'kEventTypeMouseLeave', 'kFillModeSolid', 'kInterpolatorTypeLinear', 'kInterpolatorTypePower2', 'kInterpolatorTypePower3',
+ 'kInterpolatorTypePower4', 'kInterpolatorTypeRoot2', 'kInterpolatorTypeRoot3', 'kInterpolatorTypeRoot4',
+ 'kInterpolatorTypeSpring1', 'kInterpolatorTypeSpring2', 'kInterpolatorTypeSpring3', 'kInterpolatorTypeSpring4',
+ 'kInterpolatorTypeSpring5', 'kInterpolatorTypeSpring6',
+ 'kOriginBottom', 'kOriginBottomLeft', 'kOriginBottomRight', 'kOriginCenter', 'kOriginLeft', 'kOriginRight',
+ 'kOriginTop', 'kOriginTopLeft', 'kOriginTopRight', 'kProgressTypeBottomToTop', 'kProgressTypeLeftToRight',
+ 'kProgressTypeRightToLeft', 'kProgressTypeTopToBottom', 'kRuntimeValueCallArgument0', 'kRuntimeValueCallArgument1',
+ 'kRuntimeValueCallArgument2', 'kRuntimeValueCallArgument3', 'kRuntimeValueCurrentUser', 'kRuntimeValueCurrentUserMainCamera',
+ 'kRuntimeValueRegister0', 'kRuntimeValueRegister1', 'kRuntimeValueRegister2', 'kRuntimeValueRegister3',
+ 'kShapeTypeEllipsoid', 'kShapeTypeRectangle', 'kShapeTypeRoundRectangle', 'kSliderTypeBottomToTop',
+ 'kSliderTypeLeftToRight', 'kSliderTypeRightToLeft', 'kSliderTypeTopToBottom', 'kWaveTypeConstant',
+ 'kWaveTypeSawtooth', 'kWaveTypeSawtoothInv', 'kWaveTypeSinus', 'kWaveTypeSinusNoise', 'kWaveTypeSquare', 'kWaveTypeTriangle',
+ //Input
+ 'kJoypadTypeIPhone', 'kJoypadTypeNone', 'kJoypadTypePhone', 'kJoypadTypeStandard', 'kJoypadTypeWiimote',
+ 'kKey0', 'kKey1', 'kKey2', 'kKey3', 'kKey4', 'kKey5', 'kKey6', 'kKey7', 'kKey8', 'kKey9', 'kKeyA', 'kKeyB',
+ 'kKeyBackspace', 'kKeyC', 'kKeyD', 'kKeyDelete', 'kKeyDown', 'kKeyE', 'kKeyEnd', 'kKeyEscape', 'kKeyF',
+ 'kKeyF1', 'kKeyF10', 'kKeyF11', 'kKeyF12', 'kKeyF2', 'kKeyF3', 'kKeyF4', 'kKeyF5', 'kKeyF6', 'kKeyF7',
+ 'kKeyF8', 'kKeyF9', 'kKeyG', 'kKeyH', 'kKeyHome', 'kKeyI', 'kKeyInsert', 'kKeyJ', 'kKeyK', 'kKeyL',
+ 'kKeyLAlt', 'kKeyLControl', 'kKeyLeft', 'kKeyLShift', 'kKeyM', 'kKeyN', 'kKeyO', 'kKeyP', 'kKeyPageDown',
+ 'kKeyPageUp', 'kKeyQ', 'kKeyR', 'kKeyRAlt', 'kKeyRControl', 'kKeyReturn', 'kKeyRight', 'kKeyRShift',
+ 'kKeyS', 'kKeySpace', 'kKeyT', 'kKeyTab', 'kKeyU', 'kKeyUp', 'kKeyV', 'kKeyW', 'kKeyX', 'kKeyY',
+ 'kKeyZ', 'kJoypadButtonPSPCircle', 'kJoypadButtonPSPCross', 'kJoypadButtonPSPDown', 'kJoypadButtonPSPL',
+ 'kJoypadButtonPSPLeft', 'kJoypadButtonPSPR', 'kJoypadButtonPSPRight', 'kJoypadButtonPSPSelect',
+ 'kJoypadButtonPSPSquare', 'kJoypadButtonPSPStart', 'kJoypadButtonPSPTriangle', 'kJoypadButtonPSPUp',
+ 'kJoypadTypePSP', 'kJoypadButtonWiimoteA', 'kJoypadButtonWiimoteB', 'kJoypadButtonWiimoteC',
+ 'kJoypadButtonWiimoteDown', 'kJoypadButtonWiimoteHome', 'kJoypadButtonWiimoteLeft',
+ 'kJoypadButtonWiimoteMinus', 'kJoypadButtonWiimoteOne', 'kJoypadButtonWiimotePlus',
+ 'kJoypadButtonWiimoteRight', 'kJoypadButtonWiimoteTwo', 'kJoypadButtonWiimoteUp', 'kJoypadButtonWiimoteZ',
+ //Light
+ 'kTypeDirectional', 'kTypePoint',
+ //Math
+ 'kEpsilon', 'kInfinity', 'kPi',
+ //Mesh
+ 'kLockModeRead', 'kLockModeWrite', 'kLockReadWrite',
+ //Network
+ 'kBluetoothServerPort', 'kDefaultServerPort', 'kStatusAuthenticated', 'kStatusSearchFinished', // 'kStatusNone', 'kStatusPending',
+ //Object
+ 'kControllerTypeAI', 'kControllerTypeAnimation', 'kControllerTypeAny', 'kControllerTypeDynamics',
+ 'kControllerTypeNavigation', 'kControllerTypeSound', 'kGlobalSpace', 'kLocalSpace', 'kParentSpace',
+ 'kTransformOptionInheritsParentRotation', 'kTransformOptionInheritsParentScale', 'kTransformOptionInheritsParentTranslation',
+ 'kTransformOptionTranslationAffectedByParentRotation', 'kTransformOptionTranslationAffectedByParentScale', 'kTypeCamera',
+ 'kTypeCollider', 'kTypeDummy', 'kTypeGroup', 'kTypeLight', 'kTypeOccluder', 'kTypeProjector', 'kTypeReflector',
+ 'kTypeSensor', 'kTypeSfx', 'kTypeShape',
+ //Pixelmap
+ 'kBlendModeDecal', 'kBlendModeReplace', 'kFillModeBrush', 'kFillModeNone', 'kPenModeBrush', // 'kFillModeSolid',
+ 'kPenModeNone', 'kPenModeSolid',
+ //Projector
+ 'kMapTypeMovie', 'kMapTypePixelMap', 'kMapTypeRenderMap', 'kMapTypeTexture', 'kMapTypeTextureClip',
+ //Scene
+ 'kFilteringModeBilinear', 'kFilteringModeNearest', 'kFilteringModeTrilinear', // 'kAddressingModeClamp', 'kAddressingModeRepeat',
+ 'kSkyBoxFaceBack', 'kSkyBoxFaceBottom', 'kSkyBoxFaceFront', 'kSkyBoxFaceLeft', 'kSkyBoxFaceRight', 'kSkyBoxFaceTop',
+ //Sensor
+ 'kShapeTypeBox', 'kShapeTypeSphere',
+ //Server
+ 'kStatusConnected', 'kStatusNone', 'kStatusPending',
+ //Session - duplicate keywords
+ //'kStatusConnected', 'kStatusNone', 'kStatusPending',
+ //Shape
+ 'kMapTypeUnknown', 'kCurveTypeBezier', 'kCurveTypeBSpline', 'kCurveTypeCatmullRom', 'kCurveTypePolyLine',
+ // 'kMapTypeMovie', 'kMapTypePixelMap', 'kMapTypeRenderMap', 'kMapTypeTexture', 'kMapTypeTextureClip',
+
+ //System
+ 'kOSType3DS', 'kOSTypeBada', 'kOSTypeBrew', 'kOSTypePalm', 'kOSTypePS3',
+ 'kClientTypeEditor', 'kClientTypeEmbedded', 'kClientTypeStandalone',
+ 'kGPUCapabilityBloomFilterSupport', 'kGPUCapabilityContrastFilterSupport', 'kGPUCapabilityDepthBlurFilterSupport',
+ 'kGPUCapabilityDistortionFilterSupport', 'kGPUCapabilityDynamicShadowsSupport', 'kGPUCapabilityHardwareOcclusionSupport',
+ 'kGPUCapabilityHardwareRenderingSupport', 'kGPUCapabilityMonochromeFilterSupport', 'kGPUCapabilityMotionBlurFilterSupport',
+ 'kGPUCapabilityPixelShaderSupport', 'kGPUCapabilityVelocityBlurFilterSupport', 'kGPUCapabilityVertexShaderSupport',
+ 'kLanguageAlbanian', 'kLanguageArabic', 'kLanguageBulgarian', 'kLanguageCatalan', 'kLanguageCzech', 'kLanguageDanish',
+ 'kLanguageDutch', 'kLanguageEnglish', 'kLanguageFinnish', 'kLanguageFrench', 'kLanguageGerman', 'kLanguageGreek',
+ 'kLanguageHebrew', 'kLanguageHungarian', 'kLanguageIcelandic', 'kLanguageItalian', 'kLanguageJapanese', 'kLanguageKorean',
+ 'kLanguageNorwegian', 'kLanguagePolish', 'kLanguagePortuguese', 'kLanguageRomanian', 'kLanguageRussian',
+ 'kLanguageSerboCroatian', 'kLanguageSlovak', 'kLanguageSpanish', 'kLanguageSwedish', 'kLanguageThai',
+ 'kLanguageTurkish', 'kLanguageUnknown', 'kLanguageUrdu', 'kOSTypeAndroid', 'kOSTypeAngstrom', 'kOSTypeIPhone',
+ 'kOSTypeLinux', 'kOSTypeMac', 'kOSTypePSP', 'kOSTypeSymbian', 'kOSTypeWii', 'kOSTypeWindows', 'kOSTypeWindowsCE',
+ ),
+ // Not used yet
+ 4 => array(
+ 'dummycommand',
+ ),
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '[', ']', '{', '}', '%', '&', '*', '|', '/', '<', '>',
+ '+', '-', '=>', '<<'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => true,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color:#0000FF; font-weight:bold;',
+ 2 => 'color:#000088; font-weight:bold;',
+ 3 => 'color:#C088C0; font-weight:bold;',
+ 4 => 'color:#00FEFE; font-weight:bold;',
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color:#008000; font-style:italic;',
+ 4 => 'color: #cc0000; font-style: italic;',
+ 'MULTI' => 'color:#008000; font-style:italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color:#000099;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color:#000000; font-weight:bold;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color:#888800;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color:#AA0000;'
+ ),
+ // names after "."
+ 'METHODS' => array(
+ 1 => 'color:#FF00FF; font-weight:bold;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color:#000000; font-weight:bold;'
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color:#ff6633; font-weight:bold;',
+ 1 => 'color:#0066ff; font-weight:bold;',
+ 2 => 'color:#6666ff; font-weight:bold;',
+ 3 => 'color:#ff3333; font-weight:bold;'
+ ),
+ 'SCRIPT' => array(
+ 0 => '',
+ 1 => '',
+ 2 => '',
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.'
+ ),
+ 'REGEXPS' => array(
+ 0 => array(//Variables
+ GESHI_SEARCH => "([[:space:]])(\\$[a-zA-Z_][a-zA-Z0-9_]*)",
+ GESHI_REPLACE => '\\2',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '\\1',
+ GESHI_AFTER => ''
+ ),
+ 1 => array(//Arrays
+ GESHI_SEARCH => "([[:space:]])(@[a-zA-Z_][a-zA-Z0-9_]*)",
+ GESHI_REPLACE => '\\2',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '\\1',
+ GESHI_AFTER => ''
+ ),
+ 2 => "([A-Z][a-zA-Z0-9_]*::)+[A-Z][a-zA-Z0-9_]*",//Static OOP symbols
+ 3 => array(
+ GESHI_SEARCH => "([[:space:]]|\[|\()(:[a-zA-Z_][a-zA-Z0-9_]*)",
+ GESHI_REPLACE => '\\2',
+ GESHI_MODIFIERS => '',
+ GESHI_BEFORE => '\\1',
+ GESHI_AFTER => ''
+ )
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_MAYBE,
+ 'SCRIPT_DELIMITERS' => array(
+ 0 => array(
+ '<%' => '%>'
+ )
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ 0 => true,
+ ),
+ 'TAB_WIDTH' => 2
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/systemverilog.php b/plugins/wp-syntax/geshi/geshi/systemverilog.php
index c30b9768..f2ba92b1 100644
--- a/plugins/wp-syntax/geshi/geshi/systemverilog.php
+++ b/plugins/wp-syntax/geshi/geshi/systemverilog.php
@@ -4,7 +4,7 @@
* -------
* Author: Sean O'Boyle
* Copyright: (C) 2008 IntelligentDV
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/06/25
*
* SystemVerilog IEEE 1800-2009(draft8) language file for GeSHi.
@@ -52,9 +52,9 @@
* Project: SyntaxFiles
*
* File: systemverilog.php
- * $LastChangedBy: seanoboyle $
- * $LastChangedDate: 2009-07-22 22:20:25 -0700 (Wed, 22 Jul 2009) $
- * $LastChangedRevision: 17 $
+ * $LastChangedBy: benbe $
+ * $LastChangedDate: 2012-08-18 01:56:20 +0200 (Sa, 18. Aug 2012) $
+ * $LastChangedRevision: 2542 $
*
************************************************************************/
diff --git a/plugins/wp-syntax/geshi/geshi/tcl.php b/plugins/wp-syntax/geshi/geshi/tcl.php
index 64da1fe2..4dd7be87 100644
--- a/plugins/wp-syntax/geshi/geshi/tcl.php
+++ b/plugins/wp-syntax/geshi/geshi/tcl.php
@@ -4,7 +4,7 @@
* ---------------------------------
* Author: Reid van Melle (rvanmelle@gmail.com)
* Copyright: (c) 2004 Reid van Melle (sorry@nowhere)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/05/05
*
* TCL/iTCL language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/teraterm.php b/plugins/wp-syntax/geshi/geshi/teraterm.php
index 5b29c1eb..f125642d 100644
--- a/plugins/wp-syntax/geshi/geshi/teraterm.php
+++ b/plugins/wp-syntax/geshi/geshi/teraterm.php
@@ -4,23 +4,29 @@
* --------
* Author: Boris Maisuradze (boris at logmett.com)
* Copyright: (c) 2008 Boris Maisuradze (http://logmett.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/09/26
*
* Tera Term Macro language file for GeSHi.
*
*
- * This version of ttl.php was created for Tera Term 4.60 and LogMeTT 2.9.4.
+ * This version of teraterm.php was created for Tera Term 4.62 and LogMeTT 2.9.4.
* Newer versions of these application can contain additional Macro commands
- * and/or keywords that are not listed here. The latest release of ttl.php
+ * and/or keywords that are not listed here. The latest release of teraterm.php
* can be downloaded from Download section of LogMeTT.com
*
* CHANGES
* -------
- * 2008/09/26 (1.0.8)
+ * 2008/09/26 (1.0.0)
* - First Release for Tera Term 4.60 and below.
+ * 2009/03/22 (1.1.0)
+ * - First Release for Tera Term 4.62 and below.
+ * 2009/04/25 (1.1.1)
+ * - Second Release for Tera Term 4.62 and below.
+ * 2010/09/12 (1.1.2)
+ * - Second Release for Tera Term 4.67, LogMeTT 2.97, TTLEditor 1.2.1 and below.
*
- * TODO (updated 2008/09/26)
+ * TODO (updated 2010/09/12)
* -------------------------
* *
*
@@ -57,27 +63,29 @@ $language_data = array (
'Beep',
'BplusRecv',
'BplusSend',
- 'Break', // (version 4.53 or later)
+ 'Break',
'Call',
- 'CallMenu', // (version 4.56 or later)
+ 'CallMenu',
'ChangeDir',
'ClearScreen',
- 'Clipb2Var', //(version 4.46 or later)
+ 'Clipb2Var',
'ClosesBox',
'CloseTT',
'Code2Str',
'Connect',
- 'CRC32', // (version 4.60 or later)
- 'CRC32File', // (version 4.60 or later)
- 'CygConnect', // (version 4.57 or later)
+ 'CRC32',
+ 'CRC32File',
+ 'CygConnect',
'DelPassword',
'Disconnect',
- 'Do', // (version 4.56 or later)
+ 'DispStr',
+ 'Do',
'Else',
+ 'ElseIf',
'EnableKeyb',
'End',
'EndIf',
- 'EndUntil', // (version 4.56 or later)
+ 'EndUntil',
'EndWhile',
'Exec',
'ExecCmnd',
@@ -88,32 +96,37 @@ $language_data = array (
'FileCreate',
'FileDelete',
'FileMarkPtr',
- 'FilenameBox', //(version 4.54 or later)
+ 'FileNameBox',
'FileOpen',
'FileRead',
- 'FileReadln', // (version 4.48 or later)
+ 'FileReadln',
'FileRename',
'FileSearch',
'FileSeek',
'FileSeekBack',
+ 'FileStat',
'FileStrSeek',
'FileStrSeek2',
+ 'FileTruncate',
'FileWrite',
- 'FileWriteln',
- 'FindOperations',
+ 'FileWriteLn',
+ 'FindClose',
+ 'FindFirst',
+ 'FindNext',
'FlushRecv',
- 'ForNext',
+ 'For',
'GetDate',
- 'GetDir', //(version 4.46 or later)
+ 'GetDir',
'GetEnv',
+ 'GetHostname',
'GetPassword',
'GetTime',
'GetTitle',
- 'GetVer', //(version 4.58 or later)
+ 'GetTTDir',
+ 'Getver',
'GoTo',
'If',
- 'IfDefined', // (version 4.46 or later)
- 'IfThenElseIf',
+ 'IfDefined',
'Include',
'InputBox',
'Int2Str',
@@ -121,73 +134,91 @@ $language_data = array (
'KmtGet',
'KmtRecv',
'KmtSend',
- 'LoadKeyMap',
+ 'LoadKeymap',
'LogClose',
'LogOpen',
'LogPause',
'LogStart',
'LogWrite',
- 'Loop', // (version 4.56 or later)
+ 'Loop',
'MakePath',
'MessageBox',
- 'MPause', // (version 4.27 or later)
+ 'MPause',
+ 'Next',
'PasswordBox',
'Pause',
- 'QuickvanRecv',
- 'QuickvanSend',
- 'Random', //(version 4.27 or later)
- 'Recvln',
+ 'QuickVANRecv',
+ 'QuickVANSend',
+ 'Random',
+ 'RecvLn',
'RestoreSetup',
'Return',
- 'RotateLeft', //(version 4.54 or later)
- 'RotateRight', //(version 4.54 or later)
- 'ScpRecv', // (version 4.57 or later)
- 'ScpSend', // (version 4.57 or later)
+ 'RotateLeft',
+ 'RotateRight',
+ 'ScpRecv',
+ 'ScpSend',
'Send',
'SendBreak',
+ 'SendBroadcast',
'SendFile',
- 'SendKcode',
- 'Sendln',
- 'SetBaud', // (version 4.58 or later)
+ 'SendKCode',
+ 'SendLn',
+ 'SendLnBroadcast',
+ 'SendMulticast',
+ 'SetBaud',
'SetDate',
+ 'SetDebug',
'SetDir',
'SetDlgPos',
- 'SetDTR', // (version 4.59 or later)
- 'SetRTS', // (version 4.59 or later)
- 'SetEnv', // (version 4.54 or later)
+ 'SetDTR',
'SetEcho',
+ 'SetEnv',
'SetExitCode',
+ 'SetMulticastName',
+ 'SetRTS',
'SetSync',
'SetTime',
'SetTitle',
'Show',
'ShowTT',
- 'Sprintf', // (version 4.52 or later)
+ 'SPrintF',
+ 'SPrintF2',
'StatusBox',
'Str2Code',
'Str2Int',
'StrCompare',
'StrConcat',
'StrCopy',
+ 'StrInsert',
+ 'StrJoin',
'StrLen',
- 'StrMatch', // (version 4.59 or later)
+ 'StrMatch',
+ 'StrRemove',
+ 'StrReplace',
'StrScan',
- 'Testlink',
+ 'StrSpecial',
+ 'StrSplit',
+ 'StrTrim',
+ 'TestLink',
'Then',
- 'ToLower', //(version 4.53 or later)
- 'ToUpper', //(version 4.53 or later)
- 'Unlink',
- 'Until', // (version 4.56 or later)
- 'Var2Clipb', //(version 4.46 or later)
+ 'ToLower',
+ 'ToUpper',
+ 'UnLink',
+ 'Until',
+ 'Var2Clipb',
'Wait',
+ 'Wait4All',
'WaitEvent',
- 'Waitln',
+ 'WaitLn',
+ 'WaitN',
'WaitRecv',
- 'WaitRegex', // (version 4.21 or later)
+ 'WaitRegEx',
'While',
'XmodemRecv',
'XmodemSend',
'YesNoBox',
+ 'YmodemRecv',
+ 'YmodemSend',
'ZmodemRecv',
'ZmodemSend'
),
@@ -204,6 +235,7 @@ $language_data = array (
'groupmatchstr9',
'inputstr',
'matchstr',
+ 'mtimeout',
'param2',
'param3',
'param4',
@@ -225,11 +257,14 @@ $language_data = array (
'$[6]',
'$[7]',
'$[8]',
+ '$[9]',
+ '$branch$',
+ '$computername$',
'$connection$',
'$email$',
'$logdir$',
'$logfilename$',
- '$logit$',
+ '$lttfilename$',
'$mobile$',
'$name$',
'$pager$',
@@ -239,7 +274,7 @@ $language_data = array (
'$ttdir$',
'$user$',
'$windir$',
- ),
+ ),
/* Keyword Symbols */
4 => array(
'and',
@@ -249,9 +284,11 @@ $language_data = array (
)
),
'SYMBOLS' => array(
- '(', ')', '[', ']',
- '~', '!', '+', '-', '*', '/', '%', '>>', '<<', '<<<', '>>>', '&', '^', '|',
- '<>', '<=', '>=', '=', '==', '<>', '!=', '&&', '||'
+ '(', ')', '[', ']', '{', '}',
+ '+', '-', '*', '/', '%',
+ '!', '&', '|', '^',
+ '<', '>', '=',
+ '?', ':', ';',
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
@@ -314,4 +351,4 @@ $language_data = array (
'TAB_WIDTH' => 4
);
-?>
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/text.php b/plugins/wp-syntax/geshi/geshi/text.php
index 259af419..87fb7110 100644
--- a/plugins/wp-syntax/geshi/geshi/text.php
+++ b/plugins/wp-syntax/geshi/geshi/text.php
@@ -4,7 +4,7 @@
* --------
* Author: Sean Hanna (smokingrope@gmail.com)
* Copyright: (c) 2006 Sean Hanna
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 04/23/2006
*
* Standard Text File (No Syntax Highlighting).
diff --git a/plugins/wp-syntax/geshi/geshi/thinbasic.php b/plugins/wp-syntax/geshi/geshi/thinbasic.php
index b41471b5..f54959e1 100644
--- a/plugins/wp-syntax/geshi/geshi/thinbasic.php
+++ b/plugins/wp-syntax/geshi/geshi/thinbasic.php
@@ -4,7 +4,7 @@
* ------
* Author: Eros Olmi (eros.olmi@thinbasic.com)
* Copyright: (c) 2006 Eros Olmi (http://www.thinbasic.com), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/05/12
*
* thinBasic language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/tsql.php b/plugins/wp-syntax/geshi/geshi/tsql.php
index 42e2ce2e..b4bf6bda 100644
--- a/plugins/wp-syntax/geshi/geshi/tsql.php
+++ b/plugins/wp-syntax/geshi/geshi/tsql.php
@@ -4,7 +4,7 @@
* --------
* Author: Duncan Lock (dunc@dflock.co.uk)
* Copyright: (c) 2006 Duncan Lock (http://dflock.co.uk/), Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/11/22
*
* T-SQL language file for GeSHi.
@@ -55,7 +55,7 @@ $language_data = array (
// Keywords
'ABSOLUTE', 'ACTION', 'ADD', 'ADMIN', 'AFTER', 'AGGREGATE', 'ALIAS', 'ALLOCATE', 'ALTER', 'ARE', 'ARRAY', 'AS',
'ASC', 'ASSERTION', 'AT', 'AUTHORIZATION', 'BACKUP', 'BEFORE', 'BEGIN', 'BINARY', 'BIT', 'BLOB', 'BOOLEAN', 'BOTH', 'BREADTH',
- 'BREAK', 'BROWSE', 'BULK', 'BY', 'CALL', 'CASCADE', 'CASCADED', 'CASE', 'CAST', 'CATALOG', 'CHAR', 'CHARACTER', 'CHECK', 'CHECKPOINT',
+ 'BREAK', 'BROWSE', 'BULK', 'BY', 'CALL', 'CASCADE', 'CASCADED', 'CASE', 'CAST', 'CATALOG', 'CATCH', 'CHAR', 'CHARACTER', 'CHECK', 'CHECKPOINT',
'CLASS', 'CLOB', 'CLOSE', 'CLUSTERED', 'COALESCE', 'COLLATE', 'COLLATION', 'COLUMN', 'COMMIT', 'COMPLETION', 'COMPUTE', 'CONNECT',
'CONNECTION', 'CONSTRAINT', 'CONSTRAINTS', 'CONSTRUCTOR', 'CONTAINS', 'CONTAINSTABLE', 'CONTINUE', 'CONVERT', 'CORRESPONDING', 'CREATE',
'CUBE', 'CURRENT', 'CURRENT_DATE', 'CURRENT_PATH', 'CURRENT_ROLE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER',
@@ -79,7 +79,7 @@ $language_data = array (
'SEQUENCE', 'SESSION', 'SESSION_USER', 'SET', 'SETS', 'SETUSER', 'SHUTDOWN', 'SIZE', 'SMALLINT', 'SPACE', 'SPECIFIC',
'SPECIFICTYPE', 'SQL', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'START', 'STATE', 'STATEMENT', 'STATIC', 'STATISTICS', 'STRUCTURE',
'SYSTEM_USER', 'TABLE', 'TEMPORARY', 'TERMINATE', 'TEXTSIZE', 'THAN', 'THEN', 'TIME', 'TIMESTAMP', 'TIMEZONE_HOUR', 'TIMEZONE_MINUTE',
- 'TO', 'TOP', 'TRAILING', 'TRAN', 'TRANSACTION', 'TRANSLATION', 'TREAT', 'TRIGGER', 'TRUE', 'TRUNCATE', 'TSEQUAL', 'UNDER', 'UNION',
+ 'TO', 'TOP', 'TRAILING', 'TRAN', 'TRANSACTION', 'TRANSLATION', 'TREAT', 'TRIGGER', 'TRUE', 'TRUNCATE', 'TRY', 'TSEQUAL', 'UNDER', 'UNION',
'UNIQUE', 'UNKNOWN', 'UNNEST', 'UPDATE', 'UPDATETEXT', 'USAGE', 'USE', 'USER', 'USING', 'VALUE', 'VALUES', 'VARCHAR', 'VARIABLE',
'VARYING', 'VIEW', 'WAITFOR', 'WHEN', 'WHENEVER', 'WHERE', 'WHILE', 'WITH', 'WITHOUT', 'WORK', 'WRITE', 'WRITETEXT', 'YEAR', 'ZONE',
'UNCOMMITTED', 'NOCOUNT',
diff --git a/plugins/wp-syntax/geshi/geshi/typoscript.php b/plugins/wp-syntax/geshi/geshi/typoscript.php
index c1e38068..6751aaa8 100644
--- a/plugins/wp-syntax/geshi/geshi/typoscript.php
+++ b/plugins/wp-syntax/geshi/geshi/typoscript.php
@@ -4,7 +4,7 @@
* --------
* Author: Jan-Philipp Halle (typo3@jphalle.de)
* Copyright: (c) 2005 Jan-Philipp Halle (http://www.jphalle.de/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/07/29
*
* TypoScript language file for GeSHi.
@@ -218,6 +218,15 @@ $language_data = array (
'OBJECT_SPLITTERS' => array(
),
'REGEXPS' => array(
+ // xhtml tag
+ 2 => array(
+ GESHI_SEARCH => '(&lt;)([a-zA-Z\\/][^\\/\\|]*?)(&gt;)',
+ GESHI_REPLACE => '\\2',
+ GESHI_MODIFIERS => 's',
+ GESHI_BEFORE => '\\1',
+ GESHI_AFTER => '\\3'
+ ),
+
// Constant
0 => array(
GESHI_SEARCH => '(\{)(\$[a-zA-Z_\.]+[a-zA-Z0-9_\.]*)(\})',
@@ -236,15 +245,6 @@ $language_data = array (
GESHI_AFTER => '\\2'
),
- // xhtml tag
- 2 => array(
- GESHI_SEARCH => '(&lt;[a-zA-Z\!\/].*?&gt;)',
- GESHI_REPLACE => '\\1',
- GESHI_MODIFIERS => 's',
- GESHI_BEFORE => '',
- GESHI_AFTER => ''
- ),
-
// extension keys / tables: (static|user|ttx|tx|tt|fe)_something[_something]
3 => array(
GESHI_SEARCH => '(plugin\.|[^\.]\b)((?:static|user|ttx|tx|tt|fe)(?:_[0-9A-Za-z_]+?)\b)',
diff --git a/plugins/wp-syntax/geshi/geshi/unicon.php b/plugins/wp-syntax/geshi/geshi/unicon.php
index 839bc096..6fe62d0f 100644
--- a/plugins/wp-syntax/geshi/geshi/unicon.php
+++ b/plugins/wp-syntax/geshi/geshi/unicon.php
@@ -4,7 +4,7 @@
* --------
* Author: Matt Oates (mattoates@gmail.com)
* Copyright: (c) 2010 Matt Oates (http://mattoates.co.uk)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/04/20
*
* Unicon the Unified Extended Dialect of Icon language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/upc.php b/plugins/wp-syntax/geshi/geshi/upc.php
new file mode 100644
index 00000000..e0530322
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/upc.php
@@ -0,0 +1,270 @@
+<?php
+/*************************************************************************************
+ * upc.php
+ * -----
+ * Author: Viraj Sinha (viraj@indent.com)
+ * Contributors:
+ * - Nigel McNie (nigel@geshi.org)
+ * - Jack Lloyd (lloyd@randombit.net)
+ * - Michael Mol (mikemol@gmail.com)
+ * Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2004/06/04
+ *
+ * UPC language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2011/06/14 (1.0.8.11)
+ * - This file is a revision of c.php with UPC keywords added
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'UPC',
+ 'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_REGEXP' => array(
+ //Multiline-continued single-line comments
+ 1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+ //Multiline-continued preprocessor define
+ 2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m'
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '',
+ 'ESCAPE_REGEXP' => array(
+ //Simple Single Char Escapes
+ 1 => "#\\\\[\\\\abfnrtv\'\"?\n]#i",
+ //Hexadecimal Char Specs
+ 2 => "#\\\\x[\da-fA-F]{2}#",
+ //Hexadecimal Char Specs
+ 3 => "#\\\\u[\da-fA-F]{4}#",
+ //Hexadecimal Char Specs
+ 4 => "#\\\\U[\da-fA-F]{8}#",
+ //Octal Char Specs
+ 5 => "#\\\\[0-7]{1,3}#"
+ ),
+ 'NUMBERS' =>
+ GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B |
+ GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI |
+ GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'if', 'return', 'while', 'case', 'continue', 'default',
+ 'do', 'else', 'for', 'switch', 'goto',
+
+ 'upc_forall', 'upc_barrier', 'upc_notify', 'upc_wait', 'upc_fence'
+ ),
+ 2 => array(
+ 'null', 'false', 'break', 'true', 'function', 'enum', 'extern', 'inline'
+ ),
+ 3 => array(
+ // assert.h
+ 'assert',
+
+ //complex.h
+ 'cabs', 'cacos', 'cacosh', 'carg', 'casin', 'casinh', 'catan',
+ 'catanh', 'ccos', 'ccosh', 'cexp', 'cimag', 'cis', 'clog', 'conj',
+ 'cpow', 'cproj', 'creal', 'csin', 'csinh', 'csqrt', 'ctan', 'ctanh',
+
+ //ctype.h
+ 'digittoint', 'isalnum', 'isalpha', 'isascii', 'isblank', 'iscntrl',
+ 'isdigit', 'isgraph', 'islower', 'isprint', 'ispunct', 'isspace',
+ 'isupper', 'isxdigit', 'toascii', 'tolower', 'toupper',
+
+ //inttypes.h
+ 'imaxabs', 'imaxdiv', 'strtoimax', 'strtoumax', 'wcstoimax',
+ 'wcstoumax',
+
+ //locale.h
+ 'localeconv', 'setlocale',
+
+ //math.h
+ 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'exp',
+ 'fabs', 'floor', 'frexp', 'ldexp', 'log', 'log10', 'modf', 'pow',
+ 'sin', 'sinh', 'sqrt', 'tan', 'tanh',
+
+ //setjmp.h
+ 'longjmp', 'setjmp',
+
+ //signal.h
+ 'raise',
+
+ //stdarg.h
+ 'va_arg', 'va_copy', 'va_end', 'va_start',
+
+ //stddef.h
+ 'offsetof',
+
+ //stdio.h
+ 'clearerr', 'fclose', 'fdopen', 'feof', 'ferror', 'fflush', 'fgetc',
+ 'fgetpos', 'fgets', 'fopen', 'fprintf', 'fputc', 'fputchar',
+ 'fputs', 'fread', 'freopen', 'fscanf', 'fseek', 'fsetpos', 'ftell',
+ 'fwrite', 'getc', 'getch', 'getchar', 'gets', 'perror', 'printf',
+ 'putc', 'putchar', 'puts', 'remove', 'rename', 'rewind', 'scanf',
+ 'setbuf', 'setvbuf', 'snprintf', 'sprintf', 'sscanf', 'tmpfile',
+ 'tmpnam', 'ungetc', 'vfprintf', 'vfscanf', 'vprintf', 'vscanf',
+ 'vsprintf', 'vsscanf',
+
+ //stdlib.h
+ 'abort', 'abs', 'atexit', 'atof', 'atoi', 'atol', 'bsearch',
+ 'calloc', 'div', 'exit', 'free', 'getenv', 'itoa', 'labs', 'ldiv',
+ 'ltoa', 'malloc', 'qsort', 'rand', 'realloc', 'srand', 'strtod',
+ 'strtol', 'strtoul', 'system',
+
+ //string.h
+ 'memchr', 'memcmp', 'memcpy', 'memmove', 'memset', 'strcat',
+ 'strchr', 'strcmp', 'strcoll', 'strcpy', 'strcspn', 'strerror',
+ 'strlen', 'strncat', 'strncmp', 'strncpy', 'strpbrk', 'strrchr',
+ 'strspn', 'strstr', 'strtok', 'strxfrm',
+
+ //time.h
+ 'asctime', 'clock', 'ctime', 'difftime', 'gmtime', 'localtime',
+ 'mktime', 'strftime', 'time',
+
+ //wchar.h
+ 'btowc', 'fgetwc', 'fgetws', 'fputwc', 'fputws', 'fwide',
+ 'fwprintf', 'fwscanf', 'getwc', 'getwchar', 'mbrlen', 'mbrtowc',
+ 'mbsinit', 'mbsrtowcs', 'putwc', 'putwchar', 'swprintf', 'swscanf',
+ 'ungetwc', 'vfwprintf', 'vswprintf', 'vwprintf', 'wcrtomb',
+ 'wcscat', 'wcschr', 'wcscmp', 'wcscoll', 'wcscpy', 'wcscspn',
+ 'wcsftime', 'wcslen', 'wcsncat', 'wcsncmp', 'wcsncpy', 'wcspbrk',
+ 'wcsrchr', 'wcsrtombs', 'wcsspn', 'wcsstr', 'wcstod', 'wcstok',
+ 'wcstol', 'wcstoul', 'wcsxfrm', 'wctob', 'wmemchr', 'wmemcmp',
+ 'wmemcpy', 'wmemmove', 'wmemset', 'wprintf', 'wscanf',
+
+ //wctype.h
+ 'iswalnum', 'iswalpha', 'iswcntrl', 'iswctype', 'iswdigit',
+ 'iswgraph', 'iswlower', 'iswprint', 'iswpunct', 'iswspace',
+ 'iswupper', 'iswxdigit', 'towctrans', 'towlower', 'towupper',
+ 'wctrans', 'wctype'
+ ),
+ 4 => array(
+ 'auto', 'char', 'const', 'double', 'float', 'int', 'long',
+ 'register', 'short', 'signed', 'sizeof', 'static', 'struct',
+ 'typedef', 'union', 'unsigned', 'void', 'volatile', 'wchar_t',
+
+ 'int8', 'int16', 'int32', 'int64',
+ 'uint8', 'uint16', 'uint32', 'uint64',
+
+ 'int_fast8_t', 'int_fast16_t', 'int_fast32_t', 'int_fast64_t',
+ 'uint_fast8_t', 'uint_fast16_t', 'uint_fast32_t', 'uint_fast64_t',
+
+ 'int_least8_t', 'int_least16_t', 'int_least32_t', 'int_least64_t',
+ 'uint_least8_t', 'uint_least16_t', 'uint_least32_t', 'uint_least64_t',
+
+ 'int8_t', 'int16_t', 'int32_t', 'int64_t',
+ 'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t',
+
+ 'intmax_t', 'uintmax_t', 'intptr_t', 'uintptr_t',
+ 'size_t', 'off_t',
+
+ 'upc_lock_t', 'shared', 'strict', 'relaxed', 'upc_blocksizeof',
+ 'upc_localsizeof', 'upc_elemsizeof'
+ ),
+ ),
+ 'SYMBOLS' => array(
+ '(', ')', '{', '}', '[', ']',
+ '+', '-', '*', '/', '%',
+ '=', '<', '>',
+ '!', '^', '&', '|',
+ '?', ':',
+ ';', ','
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #b1b100;',
+ 2 => 'color: #000000; font-weight: bold;',
+ 3 => 'color: #000066;',
+ 4 => 'color: #993333;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666; font-style: italic;',
+ 2 => 'color: #339933;',
+ 'MULTI' => 'color: #808080; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;',
+ 1 => 'color: #000099; font-weight: bold;',
+ 2 => 'color: #660099; font-weight: bold;',
+ 3 => 'color: #660099; font-weight: bold;',
+ 4 => 'color: #660099; font-weight: bold;',
+ 5 => 'color: #006699; font-weight: bold;',
+ 'HARD' => '',
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #009900;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #ff0000;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #0000dd;',
+ GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;',
+ GESHI_NUMBER_OCT_PREFIX => 'color: #208080;',
+ GESHI_NUMBER_HEX_PREFIX => 'color: #208080;',
+ GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;',
+ GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;',
+ GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;',
+ GESHI_NUMBER_FLT_NONSCI => 'color:#800080;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #202020;',
+ 2 => 'color: #202020;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #339933;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => 'http://www.opengroup.org/onlinepubs/009695399/functions/{FNAMEL}.html',
+ 4 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.',
+ 2 => '::'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/urbi.php b/plugins/wp-syntax/geshi/geshi/urbi.php
new file mode 100644
index 00000000..a7353ea8
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/urbi.php
@@ -0,0 +1,200 @@
+<?php
+/*************************************************************************************
+ * urbi.php
+ * -------
+ * Author: Alexandre Morgand (morgand.alexandre@gmail.com)
+ * Copyright: (c) 2011 Morgand (http://gostai.com)
+ * Release Version: 1.0.8.11
+ * Date Started: 2011/09/10
+ *
+ * Urbi language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * -------------------------
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'Urbi',
+ 'COMMENT_SINGLE' => array(1 => '//'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_REGEXP' => array(
+ //Multiline-continued single-line comments
+ 1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m',
+ //Multiline-continued preprocessor define
+ 2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m',
+ // Urbi warning.
+ 3 => "#\[[0-9a-f]{8}:warning\].*#",
+ // Urbi message from echo.
+ 4 => '#\[[0-9a-f]{8}\] \*\*\*.*#',
+ // Urbi error message.
+ 6 => '#\[[0-9a-f]{8}:error\].*#',
+ // Urbi system message.
+ 5 => '#\[00.*\].*#',
+ // Nested comment. Max depth 4.
+ 7 => '#\/\*(.|\n)*\/\*(.|\n)*\*\/(.|\n)*\*\/#',
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array(
+ 0 => '"',
+ 1 => '\'',
+ ),
+ // For Urbi, disable escape char is better.
+ 'ESCAPE_CHAR' => '\\',
+ 'ESCAPE_REGEXP' => array(
+ //Simple Single Char Escapes
+ 1 => "#\\\\[abfnrtv\\\'\"?\n]#",
+ //Hexadecimal Char Specs
+ 2 => "#\\\\x[\da-fA-F]{2}#",
+ //Hexadecimal Char Specs
+ 3 => "#\\\\u[\da-fA-F]{4}#",
+ //Hexadecimal Char Specs
+ 4 => "#\\\\U[\da-fA-F]{8}#",
+ //Octal Char Specs
+ 5 => "#\\\\[0-7]{1,3}#",
+ ),
+ 'NUMBERS' =>
+ GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B |
+ GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI |
+ GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO,
+ 'KEYWORDS' => array(
+ // Condition keywords.
+ 1 => array(
+ 'at', 'at;', 'at|', 'at&', 'at,', 'break', 'call', 'case', 'catch', 'continue',
+ 'do', 'else', 'every', 'every&', 'every,', 'every;', 'every|', 'for', 'for&',
+ 'for,', 'for;', 'foreach', 'for|', 'freezeif', 'goto', 'if', 'in', 'loop',
+ 'loop&', 'loop,', 'loop;', 'loop|', 'or_eq', 'stopif', 'switch', 'try',
+ 'waituntil', 'when', 'whenever', 'while', 'while&', 'while,', 'while;',
+ 'while|', 'throw', 'onleave', 'watch', 'return', 'and_eq', 'default', 'finally',
+ 'timeout', 'xor_eq'
+ ),
+ // Type.
+ 2 => array(
+ 'virtual', 'using', 'namespace', 'inline', 'protected', 'private', 'public',
+ 'typename', 'typeid', 'class', 'const_cast', 'dynamic_cast', 'friend',
+ 'template', 'enum', 'static_cast', 'reinterpret_cast', 'mutable', 'explicit'
+ ),
+ // Standard function.
+ 3 => array(
+ 'this', 'sizeof', 'delete', 'assert', 'isdef', 'compl', 'detach',
+ 'disown', '__HERE__', 'asm'
+ ),
+ // Type.
+ 4 => array(
+ 'char', 'const', 'double', 'int', 'long', 'typedef', 'union',
+ 'unsigned', 'var', 'short', 'wchar_t', 'volatile', 'signed', 'bool',
+ 'float', 'struct', 'auto', 'register', 'static', 'extern', 'function',
+ 'export', 'external', 'internal', 'closure', 'BIN'
+ ),
+ ),
+ 'SYMBOLS' => array(
+ 0 => array('(', ')', '{', '}', '[', ']'),
+ 1 => array('<', '>','=', '!=', '==', '==='),
+ 2 => array('+', '-', '*', '/', '%', 'bitand', 'bitor', 'xor'),
+ 3 => array('!', '^', '&', '|'),
+ 4 => array('?', ':', ';')
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => true,
+ 2 => true,
+ 3 => true,
+ 4 => true,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #0000ff;',
+ 2 => 'color: #0000ff;',
+ 3 => 'color: #0000dd;',
+ 4 => 'color: #0000ff;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666;',
+ 2 => 'color: #339900;',
+ 3 => 'color: #d46b0f;',
+ 4 => 'color: #20b537;',
+ 5 => 'color: #73776f;',
+ 6 => 'color: #a71616;',
+ 7 => 'color: #666666;',
+ 'MULTI' => 'color: #666666; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #ff0000;',
+ 1 => 'color: #ff0000;',
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #7a0874; font-weight: bold;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #ff0000;',
+ 1 => 'color: #007788;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #0000dd;'
+ ),
+ 'METHODS' => array(
+ 1 => 'color: #007788;',
+ 2 => 'color: #007788;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #008000;',
+ 1 => 'color: #0000f8;',
+ 2 => 'color: #000040;',
+ 3 => 'color: #000040; font-weight: bold;',
+ 4 => 'color: #008080;'
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color: #0000dd',
+ 1 => 'color: #0000dd;',
+ 2 => 'color: #0000dd;',
+ 3 => 'color: #0000dd;',
+ ),
+ 'SCRIPT' => array(
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array(
+ 1 => '.',
+ 2 => '::',
+ // FIXME: add -> splitter.
+ ),
+ 'REGEXPS' => array(
+ 0 => '0x[0-9a-fA-F]([0-9a-fA-F_]*[0-9a-fA-F])*',
+ 1 => '[0-9]([0-9_]*[0-9])*(e|E)(-|\+)?[0-9]([0-9_]*[0-9])*',
+ 2 => '[0-9]([0-9_]*[0-9])*(min|s|ms|h|d)',
+ 3 => '[0-9]+_([0-9_])*[0-9]',
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'TAB_WIDTH' => 4,
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/uscript.php b/plugins/wp-syntax/geshi/geshi/uscript.php
new file mode 100644
index 00000000..58cdb8d9
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/uscript.php
@@ -0,0 +1,299 @@
+<?php
+/*************************************************************************************
+ * uscript.php
+ * ---------------------------------
+ * Author: pospi (pospi@spadgos.com)
+ * Copyright: (c) 2007 pospi (http://pospi.spadgos.com)
+ * Release Version: 1.0.8.11
+ * Date Started: 2007/05/21
+ *
+ * UnrealScript language file for GeSHi.
+ *
+ * Comments:
+ * * Main purpose at this time is for Unreal Engine 2 / 2.5
+ * * Mostly taken from UltraEdit unrealScript wordfile.
+ *
+ * CHANGES
+ * -------
+ * 2007/05/21 (1.0.8.10)
+ * - First Release
+ *
+ * TODO (updated 2007/05/21)
+ * -------------------------
+ * * Update to feature any UE3 classes / keywords when UT3 comes out
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'Unreal Script',
+ 'COMMENT_SINGLE' => array(
+ 1 => '//',
+ 2 => '#'
+ ),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array("'", '"'),
+ 'ESCAPE_CHAR' => '\\',
+ 'KEYWORDS' => array(
+ 1 => array( //declaration keywords
+ 'simulated', 'state', 'class', 'function', 'event', 'var', 'local',
+ 'ignores', 'globalconfig', 'config', 'abstract', 'nativereplication', 'native',
+ 'auto', 'coerce', 'const', 'default',
+ 'defaultproperties',
+ 'enum', 'extends', 'expands', 'final', 'guid', 'latent', 'localized',
+ 'new', 'noexport', 'operator', 'preoperator', 'optional', 'out',
+ 'private', 'public', 'protected', 'reliable', 'replication',
+ 'singular', 'static', 'struct', 'transient', 'unreliable',
+ 'hidedropdown', 'cacheexempt', 'exec', 'delegate', 'import', 'placeable', 'exportstructs'
+ ),
+ 2 => array( //control flow keywords
+ 'for', 'while', 'do', 'if', 'else', 'switch', 'case', 'return', 'break', 'continue',
+ 'begin', 'loop', 'assert',
+ 'foreach', 'AllActors', 'DynamicActors', 'ChildActors', 'BasedActors', 'TouchingActors',
+ 'TraceActors', 'RadiusActors', 'VisibleActors', 'CollidingActors', 'VisibleCollidingActors'
+ ),
+ 3 => array( //global (object) functions
+ 'log', 'warn', 'rot', 'vect', 'Rand', 'Min', 'Max', 'Clamp', 'Abs', 'Sin', 'ASin',
+ 'Cos', 'ACos', 'Tan', 'ATan', 'Exp', 'Loge', 'Sqrt', 'Square', 'FRand', 'FMin', 'FMax', 'FClamp',
+ 'Lerp', 'Smerp', 'Ceil', 'Round', 'VSize', 'Normal', 'Invert', 'VRand', 'MirrorVectorByNormal',
+ 'GetAxes', 'GetUnAxes', 'RotRand', 'OrthoRotation', 'Normalize', 'ClockwiseFrom',
+ 'Len', 'InStr', 'Mid', 'Left', 'Right', 'Caps', 'Chr', 'Asc', 'Locs',
+ 'Divide', 'Split', 'StrCmp', 'Repl', 'Eval',
+ 'InterpCurveEval', 'InterpCurveGetOutputRange', 'InterpCurveGetInputDomain',
+ 'QuatProduct', 'QuatInvert', 'QuatRotateVector', 'QuatFindBetween', 'QuatFromAxisAndAngle',
+ 'QuatFromRotator', 'QuatToRotator', 'QuatSlerp',
+ 'Localize', 'GotoState', 'IsInState', 'GetStateName',
+ 'ClassIsChildOf', 'IsA', 'Enable', 'Disable',
+ 'GetPropertyText', 'SetPropertyText', 'GetEnum', 'DynamicLoadObject', 'FindObject',
+ 'SaveConfig', 'ClearConfig', 'StaticSaveConfig', 'ResetConfig', 'StaticClearConfig',
+ 'GetPerObjectNames', 'RandRange', 'StopWatch', 'IsOnConsole', 'IsSoaking',
+ 'PlatformIsMacOS', 'PlatformIsUnix', 'PlatformIsWindows', 'PlatformIs64Bit',
+ 'BeginState', 'EndState', 'Created', 'AllObjects', 'GetReferencers', 'GetItemName',
+ 'ReplaceText', 'EatStr'
+ ),
+ 4 => array( //common almost-global (actor) functions
+ 'ClientMessage', 'ConsoleCommand', 'CopyObjectToClipboard', 'TextToSpeech',
+ 'Error', 'Sleep', 'SetCollision', 'SetCollisionSize', 'SetDrawScale', 'SetDrawScale3D',
+ 'SetStaticMesh', 'SetDrawType', 'Move', 'SetLocation', 'SetRotation',
+ 'SetRelativeLocation', 'SetRelativeRotation', 'MoveSmooth', 'AutonomousPhysics',
+ 'SetBase', 'SetOwner', 'IsJoinedTo', 'GetMeshName', 'PlayAnim', 'LoopAnim', 'TweenAnim',
+ 'IsAnimating', 'FinishAnim', 'HasAnim', 'StopAnimating', 'FreezeFrameAt', 'SetAnimFrame',
+ 'IsTweening', 'AnimStopLooping', 'AnimEnd', 'LinkSkelAnim', 'LinkMesh', 'BoneRefresh',
+ 'GetBoneCoords', 'GetBoneRotation', 'GetRootLocation', 'GetRootRotation', 'AttachToBone',
+ 'DetachFromBone', 'SetBoneScale', 'UpdateURL', 'GetURLOption', 'SetPhysics', 'KAddImpulse',
+ 'KImpact', 'KApplyForce', 'Clock', 'UnClock', 'Destroyed', 'GainedChild', 'LostChild',
+ 'Tick', 'PostNetReceive', 'ClientTrigger', 'Trigger', 'UnTrigger', 'BeginEvent', 'EndEvent',
+ 'Timer', 'HitWall', 'Falling', 'Landed', 'ZoneChange', 'PhysicsVolumeChange', 'Touch',
+ 'PostTouch', 'UnTouch', 'Bump', 'BaseChange', 'Attach', 'Detach', 'SpecialHandling',
+ 'EncroachingOn', 'EncroachedBy', 'RanInto', 'FinishedInterpolation', 'EndedRotation',
+ 'UsedBy', 'FellOutOfWorld', 'KilledBy', 'TakeDamage', 'HealDamage', 'Trace', 'FastTrace',
+ 'TraceThisActor', 'spawn', 'Destroy', 'TornOff', 'SetTimer', 'PlaySound', 'PlayOwnedSound',
+ 'GetSoundDuration', 'MakeNoise', 'BeginPlay', 'GetAllInt', 'RenderOverlays', 'RenderTexture',
+ 'PreBeginPlay', 'PostBeginPlay', 'PostNetBeginPlay', 'HurtRadius', 'Reset', 'Crash'
+ ),
+ 5 => array( //data types
+ 'none', 'null',
+ 'float', 'int', 'bool', 'byte', 'char', 'double', 'iterator', 'name', 'string', //primitive
+ 'plane', 'rotator', 'vector', 'spline', 'coords', 'Quat', 'Range', 'RangeVector', //structs
+ 'Scale', 'Color', 'Box', 'IntBox', 'FloatBox', 'BoundingVolume', 'Matrix', 'InterpCurvePoint',
+ 'InterpCurve', 'CompressedPosition', 'TMultiMap', 'PointRegion',
+ 'KRigidBodyState', 'KSimParams', 'AnimRep', 'FireProperties',
+ 'lodmesh', 'skeletalmesh', 'mesh', 'StaticMesh', 'MeshInstance', //3d resources
+ 'sound', //sound resources
+ 'material', 'texture', 'combiner', 'modifier', 'ColorModifier', 'FinalBlend', //2d resources
+ 'MaterialSequence', 'MaterialSwitch', 'OpacityModifier', 'TexModifier', 'TexEnvMap',
+ 'TexCoordSource', 'TexMatrix', 'TexOscillator', 'TexPanner', 'TexRotator', 'TexScaler',
+ 'RenderedMaterial', 'BitmapMaterial', 'ScriptedTexture', 'ShadowBitmapMaterial', 'Cubemap',
+ 'FractalTexture', 'FireTexture', 'IceTexture', 'WaterTexture', 'FluidTexture', 'WaveTexture',
+ 'WetTexture', 'ConstantMaterial', 'ConstantColor', 'FadeColor', 'ParticleMaterial',
+ 'ProjectorMaterial', 'Shader', 'TerrainMaterial', 'VertexColor'
+ ),
+ 6 => array( //misc keywords
+ 'false', 'true', 'self', 'super', 'MaxInt', 'Pi'
+ ),
+ 7 => array( //common actor enums & variables
+ 'DT_None', 'DT_Sprite', 'DT_Mesh', 'DT_Brush', 'DT_RopeSprite',
+ 'DT_VerticalSprite', 'DT_TerraForm', 'DT_SpriteAnimOnce', 'DT_StaticMesh', 'DT_DrawType',
+ 'DT_Particle', 'DT_AntiPortal', 'DT_FluidSurface',
+ 'PHYS_None', 'PHYS_Walking', 'PHYS_Falling', 'PHYS_Swimming', 'PHYS_Flying',
+ 'PHYS_Rotating', 'PHYS_Projectile', 'PHYS_Interpolating', 'PHYS_MovingBrush', 'PHYS_Spider',
+ 'PHYS_Trailer', 'PHYS_Ladder', 'PHYS_RootMotion', 'PHYS_Karma', 'PHYS_KarmaRagDoll',
+ 'PHYS_Hovering', 'PHYS_CinMotion',
+ 'ROLE_None', 'ROLE_DumbProxy', 'ROLE_SimulatedProxy',
+ 'ROLE_AutonomousProxy', 'ROLE_Authority',
+ 'STY_None', 'STY_Normal', 'STY_Masked', 'STY_Translucent', 'STY_Modulated', 'STY_Alpha',
+ 'STY_Additive', 'STY_Subtractive', 'STY_Particle', 'STY_AlphaZ',
+ 'OCCLUSION_None', 'OCCLUSION_BSP', 'OCCLUSION_Default', 'OCCLUSION_StaticMeshes',
+ 'SLOT_None', 'SLOT_Misc', 'SLOT_Pain', 'SLOT_Interact', 'SLOT_Ambient', 'SLOT_Talk',
+ 'SLOT_Interface', 'MTRAN_None', 'MTRAN_Instant', 'MTRAN_Segue', 'MTRAN_Fade',
+ 'MTRAN_FastFade', 'MTRAN_SlowFade',
+
+ 'DrawType', 'Physics', 'Owner', 'Base', 'Level', 'Game', 'Instigator', 'RemoteRole', 'Role',
+ 'LifeSpan', 'Tag', 'Event', 'Location', 'Rotation', 'Velocity', 'Acceleration',
+ 'RelativeLocation', 'RelativeRotation', 'DrawScale', 'DrawScale3D', 'Skins', 'Style',
+ 'SoundVolume', 'SoundPitch', 'SoundRadius', 'TransientSoundVolume', 'TransientSoundRadius',
+ 'CollisionRadius', 'CollisionHeight', 'Mass', 'Buoyancy', 'RotationRate', 'DesiredRotation'
+ ),
+ 8 => array( //common non-actor uscript classes
+ 'Object',
+ 'CacheManager', 'CameraEffect', 'Canvas', 'CheatManager', 'Commandlet', 'DecoText', 'GUI',
+ 'InteractionMaster', 'Interactions', 'Interaction', 'KarmaParamsCollision', 'KarmaParamsRBFull',
+ 'KarmaParamsSkel', 'KarmaParams', 'LevelSummary', 'Locale', 'Manifest', 'MaterialFactory',
+ 'MeshObject', 'ObjectPool', 'Pallete',
+ 'ParticleEmitter', 'MeshEmitter', 'BeamEmitter', 'SpriteEmitter', 'SparkEmitter', 'TrailEmitter',
+ 'Player', 'PlayerInput', 'PlayInfo', 'ReachSpec', 'Resource', 'LatentScriptedAction', 'ScriptedAction',
+ 'speciesType', 'StreamBase', 'Stream', 'EditorEngine', 'Engine', 'Time', 'WeaponFire',
+ 'WebApplication', 'WebRequest', 'WebResponse', 'WebSkin', 'xPawnGibGroup', 'xPawnSoundGroup',
+ 'xUtil'
+ ),
+ 9 => array( //common actor-based uscript classes
+ 'Actor',
+ 'Controller', 'AIController', 'ScriptedController', 'Bot', 'xBot',
+ 'PlayerController', 'UnrealPlayer', 'xPlayer',
+ 'DamageType', 'WeaponDamageType', 'Effects', 'Emitter', 'NetworkEmitter',
+ 'Gib', 'HUD', 'HudBase', 'Info', 'FluidSurfaceInfo', 'Combo',
+ 'GameInfo', 'UnrealMPGameInfo', 'DeathMatch', 'TeamGame', 'CTFGame',
+ 'xCTFGame', 'xBombingRun', 'xDoubleDom', 'xTeamGame',
+ 'ASGameInfo', 'Invasion', 'ONSOnslaughtGame', 'xDeathmatch',
+ 'Mutator', 'Inventory', 'Ammunition', 'KeyInventory', 'Powerups', 'Armor', 'Weapon',
+ 'InventoryAttachment', 'WeaponAttachment',
+ 'KActor', 'KConstraint', 'KBSJoint', 'KCarWheelJoint', 'KConeLimit', 'KHinge', 'KTire',
+ 'KVehicleFactory', 'Keypoint', 'AIScript', 'ScriptedSequence', 'ScriptedTrigger',
+ 'AmbientSound', 'Light', 'SpotLight', 'SunLight', 'TriggerLight',
+ 'MeshEffect', 'NavigationPoint', 'GameObjective', 'DestroyableObjective',
+ 'PathNode', 'FlyingPathNode', 'RoadPathNode', 'InventorySpot', 'PlayerStart',
+ 'Pawn', 'Vehicle', 'UnrealPawn', 'xPawn', 'Monster', 'ASVehicle', 'KVehicle', 'KCar',
+ 'ONSWeaponPawn', 'SVehicle', 'ONSVehicle', 'ONSChopperCraft', 'ONSHoverCraft',
+ 'ONSPlaneCraft', 'ONSTreadCraft', 'ONSWheeledCraft',
+ 'Pickup', 'Ammo', 'UTAmmoPickup', 'ArmorPickup', 'KeyPickup', 'TournamentPickup',
+ 'Projectile', 'Projector', 'DynamicProjector', 'ShadowProjector', 'xScorch',
+ 'xEmitter', 'xPickupBase', 'xProcMesh', 'xWeatherEffect', 'PhysicsVolume', 'Volume'
+ ),
+ 10 => array( //symbol-like operators
+ 'dot','cross'
+ )
+ ),
+ 'SYMBOLS' => array(
+ '+','-','=','/','*','-','%','>','<','&','^','!','|','`','(',')','[',']','{','}',
+ '<<','>>','$','@'
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #0000FF;',
+ 2 => 'color: #0000FF;',
+ 3 => 'color: #0066AA;',
+ 4 => 'color: #0088FF;',
+ 5 => 'color: #E000E0;',
+ 6 => 'color: #900000;',
+ 7 => 'color: #888800;',
+ 8 => 'color: #AA6600;',
+ 9 => 'color: #FF8800;',
+ 10 => 'color: #0000FF;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #008080; font-style: italic;',
+ 2 => 'color: #000000; font-weight: bold;',
+ 'MULTI' => 'color: #008080; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => ''
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #000000;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #999999;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #FF0000;'
+ ),
+ 'METHODS' => array(
+ 0 => 'color: #006600;'
+ ),
+ 'SYMBOLS' => array(
+ 0 => 'color: #669966;'
+ ),
+ 'REGEXPS' => array(
+ 0 => 'color: #E000E0;',
+ 1 => 'color: #E000E0;'
+ ),
+ 'SCRIPT' => array(
+ 0 => ''
+ )
+ ),
+ 'URLS' => array(
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => 'http://wiki.beyondunreal.com/wiki?search={FNAME}',
+ 9 => 'http://wiki.beyondunreal.com/wiki?search={FNAME}',
+ 10 => ''
+ ),
+ 'OOLANG' => true,
+ 'OBJECT_SPLITTERS' => array('.'),
+ 'REGEXPS' => array( //handle template-style variable definitions
+ 0 => array(
+ GESHI_SEARCH => '(class\s*)<(\s*(\w+)\s*)>',
+ GESHI_REPLACE => "\${1}",
+ GESHI_MODIFIERS => 'i',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => "< \${3} >"
+ ),
+ 1 => array(
+ GESHI_SEARCH => '(array\s*)<(\s*(\w+)\s*)>',
+ GESHI_REPLACE => "\${1}",
+ GESHI_MODIFIERS => 'i',
+ GESHI_BEFORE => '',
+ GESHI_AFTER => "< \${3} >"
+ )
+ ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(
+ ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'PARSER_CONTROL' => array(
+ 'KEYWORDS' => array(
+ 10 => array(
+ 'DISALLOWED_BEFORE' => '(?<!<)(?=DOT>)'
+ )
+ )
+ )
+);
+
+?>
diff --git a/plugins/wp-syntax/geshi/geshi/vala.php b/plugins/wp-syntax/geshi/geshi/vala.php
index 1e4cecef..acac57e2 100644
--- a/plugins/wp-syntax/geshi/geshi/vala.php
+++ b/plugins/wp-syntax/geshi/geshi/vala.php
@@ -4,7 +4,7 @@
* ----------
* Author: Nicolas Joseph (nicolas.joseph@valaide.org)
* Copyright: (c) 2009 Nicolas Joseph
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/04/29
*
* Vala language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/vb.php b/plugins/wp-syntax/geshi/geshi/vb.php
index 638da5e8..528e7cd4 100644
--- a/plugins/wp-syntax/geshi/geshi/vb.php
+++ b/plugins/wp-syntax/geshi/geshi/vb.php
@@ -5,7 +5,7 @@
* Author: Roberto Rossi (rsoftware@altervista.org)
* Copyright: (c) 2004 Roberto Rossi (http://rsoftware.altervista.org),
* Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/08/30
*
* Visual Basic language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/vbnet.php b/plugins/wp-syntax/geshi/geshi/vbnet.php
index 0121f8de..758df989 100644
--- a/plugins/wp-syntax/geshi/geshi/vbnet.php
+++ b/plugins/wp-syntax/geshi/geshi/vbnet.php
@@ -4,7 +4,7 @@
* ---------
* Author: Alan Juden (alan@judenware.org)
* Copyright: (c) 2004 Alan Juden, Nigel McNie (http://qbnz.com/highlighter)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/06/04
*
* VB.NET language file for GeSHi.
@@ -45,60 +45,46 @@ $language_data = array (
'QUOTEMARKS' => array('"'),
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
+ //Keywords
1 => array(
- '3DDKSHADOW', '3DHIGHLIGHT', '3DLIGHT', 'ABORT', 'ABORTRETRYIGNORE', 'ACTIVEBORDER',
- 'ACTIVETITLEBAR', 'ALIAS', 'APPLICATIONMODAL', 'APPLICATIONWORKSPACE', 'ARCHIVE',
- 'BACK', 'BINARYCOMPARE', 'BLACK', 'BLUE', 'BUTTONFACE', 'BUTTONSHADOW', 'BUTTONTEXT',
- 'CANCEL', 'CDROM', 'CR', 'CRITICAL', 'CRLF', 'CYAN', 'DEFAULT', 'DEFAULTBUTTON1',
- 'DEFAULTBUTTON2', 'DEFAULTBUTTON3', 'DESKTOP', 'DIRECTORY', 'EXCLAMATION', 'FALSE',
- 'FIXED', 'FORAPPENDING', 'FORMFEED', 'FORREADING', 'FORWRITING', 'FROMUNICODE',
- 'GRAYTEXT', 'GREEN', 'HIDDEN', 'HIDE', 'HIGHLIGHT', 'HIGHLIGHTTEXT', 'HIRAGANA',
- 'IGNORE', 'INACTIVEBORDER', 'INACTIVECAPTIONTEXT', 'INACTIVETITLEBAR', 'INFOBACKGROUND',
- 'INFORMATION', 'INFOTEXT', 'KATAKANALF', 'LOWERCASE', 'MAGENTA', 'MAXIMIZEDFOCUS',
- 'MENUBAR', 'MENUTEXT', 'METHOD', 'MINIMIZEDFOCUS', 'MINIMIZEDNOFOCUS', 'MSGBOXRIGHT',
- 'MSGBOXRTLREADING', 'MSGBOXSETFOREGROUND', 'NARROW', 'NEWLINE', 'NO', 'NORMAL',
- 'NORMALFOCUS', 'NORMALNOFOCUS', 'NULLSTRING', 'OBJECTERROR', 'OK', 'OKCANCEL', 'OKONLY',
- 'PROPERCASE', 'QUESTION', 'RAMDISK', 'READONLY', 'RED', 'REMOTE', 'REMOVABLE', 'RETRY',
- 'RETRYCANCEL', 'SCROLLBARS', 'SYSTEMFOLDER', 'SYSTEMMODAL', 'TEMPORARYFOLDER',
- 'TEXTCOMPARE', 'TITLEBARTEXT', 'TRUE', 'UNICODE', 'UNKNOWN', 'UPPERCASE', 'VERTICALTAB',
- 'VOLUME', 'WHITE', 'WIDE', 'WIN16', 'WIN32', 'WINDOWBACKGROUND', 'WINDOWFRAME',
- 'WINDOWSFOLDER', 'WINDOWTEXT', 'YELLOW', 'YES', 'YESNO', 'YESNOCANCEL'
- ),
+ 'AddHandler', 'AddressOf', 'Alias', 'And', 'AndAlso', 'As', 'ByRef', 'ByVal',
+ 'Call', 'Case', 'Catch', 'Char', 'Class', 'Const', 'Continue',
+ 'Declare', 'Default',
+ 'Delegate', 'Dim', 'DirectCast', 'Do', 'Each', 'Else', 'ElseIf', 'End', 'EndIf',
+ 'Enum', 'Erase', 'Error', 'Event', 'Exit', 'False', 'Finally', 'For', 'Friend', 'Function',
+ 'Get', 'GetType', 'GetXMLNamespace', 'Global', 'GoSub', 'GoTo', 'Handles', 'If', 'Implements',
+ 'Imports', 'In', 'Inherits', 'Interface', 'Is', 'IsNot', 'Let', 'Lib', 'Like', 'Loop', 'Me',
+ 'Mod', 'Module', 'Module Statement', 'MustInherit', 'MustOverride', 'MyBase', 'MyClass', 'Namespace',
+ 'Narrowing', 'New', 'Next', 'Not', 'Nothing', 'NotInheritable', 'NotOverridable', 'Of', 'On',
+ 'Operator', 'Option', 'Optional', 'Or', 'OrElse', 'Out', 'Overloads', 'Overridable', 'Overrides',
+ 'ParamArray', 'Partial', 'Private', 'Property', 'Protected', 'Public', 'RaiseEvent', 'ReadOnly', 'ReDim',
+ 'REM', 'RemoveHandler', 'Resume', 'Return', 'Select','Set', 'Shadows', 'Shared', 'Static', 'Step',
+ 'Stop', 'Structure', 'Sub', 'SyncLock', 'Then', 'Throw', 'To', 'True', 'Try', 'TryCast', 'TypeOf',
+ 'Using', 'Wend', 'When', 'While', 'Widening', 'With', 'WithEvents', 'WriteOnly', 'Xor'
+ ),
+ //Data Types
2 => array(
- 'AndAlso', 'As', 'ADDHANDLER', 'ASSEMBLY', 'AUTO', 'Binary', 'ByRef', 'ByVal', 'BEGINEPILOGUE',
- 'Else', 'ElseIf', 'Empty', 'Error', 'ENDPROLOGUE', 'EXTERNALSOURCE', 'ENVIRON', 'For',
- 'Friend', 'Func', 'GET', 'HANDLES', 'Input', 'Is', 'IsNot', 'Len', 'Lock', 'Me', 'Mid', 'MUSTINHERIT', 'MustOverride',
- 'MYBASE', 'MYCLASS', 'New', 'Next', 'Nothing', 'Null', 'NOTINHERITABLE',
- 'NOTOVERRIDABLE', 'Of', 'OFF', 'On', 'Option', 'Optional', 'Overloads', 'OVERRIDABLE', 'Overrides', 'ParamArray', 'Predicate',
- 'Print', 'Private', 'Property', 'Public', 'Resume', 'Return', 'Seek', 'Static', 'Step',
- 'String', 'SHELL', 'SENDKEYS', 'SET', 'Shared', 'Then', 'Time', 'To', 'THROW', 'WithEvents'
+ 'Boolean', 'Byte', 'Date', 'Decimal', 'Double', 'Integer', 'Long', 'Object',
+ 'SByte', 'Short', 'Single', 'String', 'UInteger', 'ULong', 'UShort'
),
+ //Compiler Directives
3 => array(
- 'COLLECTION', 'DEBUG', 'DICTIONARY', 'DRIVE', 'DRIVES', 'ERR', 'FILE', 'FILES',
- 'FILESYSTEMOBJECT', 'FOLDER', 'FOLDERS', 'TEXTSTREAM'
+ '#Const', '#Else', '#ElseIf', '#End', '#If'
),
+ //Constants
4 => array(
- 'BOOLEAN', 'BYTE', 'DATE', 'DECIMIAL', 'DOUBLE', 'INTEGER', 'LONG', 'OBJECT',
- 'SINGLE STRING'
+ 'CBool', 'CByte', 'CChar', 'CChr', 'CDate', 'CDbl', 'CDec','CInt', 'CLng', 'CLng8', 'CObj', 'CSByte', 'CShort',
+ 'CSng', 'CStr', 'CType', 'CUInt', 'CULng', 'CUShort'
),
+ //Linq
5 => array(
- 'ADDRESSOF', 'AND', 'BITAND', 'BITNOT', 'BITOR', 'BITXOR',
- 'GETTYPE', 'LIKE', 'MOD', 'NOT', 'ORXOR'
- ),
- 6 => array(
- 'APPACTIVATE', 'BEEP', 'CALL', 'CHDIR', 'CHDRIVE', 'CLASS', 'CASE', 'CATCH', 'CONST',
- 'DECLARE', 'DELEGATE', 'DELETESETTING', 'DIM', 'DO', 'DOEVENTS', 'END', 'ENUM',
- 'EVENT', 'EXIT', 'EACH', 'FUNCTION', 'FINALLY', 'IF', 'IMPORTS', 'INHERITS',
- 'INTERFACE', 'IMPLEMENTS', 'KILL', 'LOOP', 'NAMESPACE', 'OPEN', 'PUT',
- 'RAISEEVENT', 'RANDOMIZE', 'REDIM', 'REM', 'RESET', 'SAVESETTING', 'SELECT',
- 'SETATTR', 'STOP', 'SUB', 'SYNCLOCK', 'STRUCTURE', 'SHADOWS', 'SWITCH',
- 'TRY', 'WIDTH', 'WITH', 'WRITE', 'WHILE'
+ 'By','From','Group','Where'
),
+ //Built-in functions
7 => array(
- 'ABS', 'ARRAY', 'ASC', 'ASCB', 'ASCW', 'CALLBYNAME', 'CBOOL', 'CBYTE', 'CCHAR',
- 'CCHR', 'CDATE', 'CDBL', 'CDEC', 'CHOOSE', 'CHR', 'CHR$', 'CHRB', 'CHRB$', 'CHRW',
- 'CINT', 'CLNG', 'CLNG8', 'CLOSE', 'COBJ', 'COMMAND', 'COMMAND$', 'CONVERSION',
- 'COS', 'CREATEOBJECT', 'CSHORT', 'CSTR', 'CURDIR', 'CTYPE', 'CVDATE', 'DATEADD',
+ 'ABS', 'ARRAY', 'ASC', 'ASCB', 'ASCW', 'CALLBYNAME', 'CHOOSE', 'CHR', 'CHR$', 'CHRB', 'CHRB$', 'CHRW',
+ 'CLOSE', 'COMMAND', 'COMMAND$', 'CONVERSION',
+ 'COS', 'CREATEOBJECT', 'CURDIR', 'CVDATE', 'DATEADD',
'DATEDIFF', 'DATEPART', 'DATESERIAL', 'DATEVALUE', 'DAY', 'DDB', 'DIR', 'DIR$',
'EOF', 'ERROR$', 'EXP', 'FILEATTR', 'FILECOPY', 'FILEDATATIME', 'FILELEN', 'FILTER',
'FIX', 'FORMAT', 'FORMAT$', 'FORMATCURRENCY', 'FORMATDATETIME', 'FORMATNUMBER',
@@ -115,16 +101,10 @@ $language_data = array (
'TIMER', 'TIMESERIAL', 'TIMEVALUE', 'TODAY', 'TRIM', 'TRIM$', 'TYPENAME', 'UBOUND',
'UCASE', 'UCASE$', 'VAL', 'WEEKDAY', 'WEEKDAYNAME', 'YEAR'
),
- 8 => array(
- 'ANY', 'ATN', 'CALENDAR', 'CIRCLE', 'CURRENCY', 'DEFBOOL', 'DEFBYTE', 'DEFCUR',
- 'DEFDATE', 'DEFDBL', 'DEFDEC', 'DEFINT', 'DEFLNG', 'DEFOBJ', 'DEFSNG', 'DEFSTR',
- 'DEFVAR', 'EQV', 'GOSUB', 'IMP', 'INITIALIZE', 'ISMISSING', 'LET', 'LINE', 'LSET',
- 'RSET', 'SGN', 'SQR', 'TERMINATE', 'VARIANT', 'VARTYPE', 'WEND'
- ),
),
'SYMBOLS' => array(
- '&', '&=', '*', '*=', '+', '+=', '-', '-=', '//', '/', '/=', '=', '\\', '\\=',
- '^', '^='
+ '+', '-', '*', '?', '=', '/', '%', '&', '>', '<', '^', '!',
+ '(', ')', '{', '}', '.'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
@@ -133,24 +113,20 @@ $language_data = array (
3 => false,
4 => false,
5 => false,
- 6 => false,
- 7 => false,
- 8 => false,
+ 7 => false
),
'STYLES' => array(
'KEYWORDS' => array(
- 1 => 'color: #0600FF;', //Constants
- 2 => 'color: #FF8000;', //Keywords
- 3 => 'color: #008000;', //Data Types
- 4 => 'color: #FF0000;', //Objects
- 5 => 'color: #804040;', //Operators
- 6 => 'color: #0600FF;', //Statements
- 7 => 'color: #0600FF;', //Functions
- 8 => 'color: #0600FF;' //Deprecated
+ 1 => 'color: #0000FF; font-weight: bold;', //Keywords
+ 2 => 'color: #6a5acd;', //primitive Data Types
+ 3 => 'color: #6a5acd; font-weight: bold;', //preprocessor-commands
+ 4 => 'color: #cd6a5a;', //Constants
+ 5 => 'color: #cd6a5a; font-weight: bold;', //LinQ
+ 7 => 'color: #000066;', //Built-in functions
),
'COMMENTS' => array(
- 1 => 'color: #008080; font-style: italic;',
- 'MULTI' => 'color: #008080; font-style: italic;'
+ 1 => 'color: #008000; font-style: italic;',
+ 'MULTI' => 'color: #008000; font-style: italic;'
),
'ESCAPE_CHAR' => array(
0 => 'color: #008080; font-weight: bold;'
@@ -159,16 +135,16 @@ $language_data = array (
0 => 'color: #000000;'
),
'STRINGS' => array(
- 0 => 'color: #808080;'
+ 0 => 'color: #a52a2a; back-color: #fffacd;'
),
'NUMBERS' => array(
- 0 => 'color: #FF0000;'
+ 0 => 'color: #a52a2a; back-color: #fffacd;'
),
'METHODS' => array(
- 1 => 'color: #0000FF;'
+ 1 => 'color: #000000;'
),
'SYMBOLS' => array(
- 0 => 'color: #008000;'
+ 0 => 'color: #000000;'
),
'REGEXPS' => array(
),
@@ -181,9 +157,7 @@ $language_data = array (
3 => 'http://www.google.com/search?q={FNAMEU}+site:msdn.microsoft.com',
4 => '',
5 => '',
- 6 => '',
- 7 => '',
- 8 => ''
+ 7 => 'http://www.google.com/search?q={FNAMEU}+site:msdn.microsoft.com'
),
'OOLANG' => true,
'OBJECT_SPLITTERS' => array(
@@ -195,6 +169,13 @@ $language_data = array (
'SCRIPT_DELIMITERS' => array(
),
'HIGHLIGHT_STRICT_BLOCK' => array(
+ ),
+ 'PARSER_CONTROL' => array(
+ 'KEYWORDS' => array(
+ 7 => array(
+ 'DISALLOWED_AFTER' => '(?!\w)(?=\s*\()'
+ )
+ )
)
);
diff --git a/plugins/wp-syntax/geshi/geshi/vedit.php b/plugins/wp-syntax/geshi/geshi/vedit.php
new file mode 100644
index 00000000..19b2bdb2
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/vedit.php
@@ -0,0 +1,103 @@
+<?php
+/*************************************************************************************
+ * vedit.php
+ * --------
+ * Author: Pauli Lindgren (pauli0212@yahoo.com)
+ * Copyright: (c) 2009 Pauli Lindgren (http://koti.mbnet.fi/pkl/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2009/12/16
+ *
+ * Vedit macro language language file for GeSHi.
+ *
+ * CHANGES
+ * -------
+ * 2009/12/16 (1.0.8.11)
+ * - First Release
+ *
+ * TODO (updated 2009/12/16)
+ * -------------------------
+ * - Add keyword groups 2, 3 and 4.
+ *
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array(
+ 'LANG_NAME' => 'Vedit macro language',
+ 'COMMENT_SINGLE' => array(1 => '//'),
+ 'COMMENT_MULTI' => array(),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"', '\''),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'break', 'breakout', 'break_out', 'continue', 'do', 'else', 'for',
+ 'goto', 'if', 'repeat', 'return', 'while'
+ )
+ ),
+ 'SYMBOLS' => array(
+ 1 => array(
+ '(', ')', '{', '}', '[', ']', '+', '-', '*', '/', '%',
+ '=', '<', '>', '!', '^', '&', '|', '?', ':', ';', ','
+ )
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'color: #b1b100;'
+ ),
+ 'COMMENTS' => array(
+ 1 => 'color: #666666; font-style: italic;',
+ 'MULTI' => 'color: #666666; font-style: italic;'
+ ),
+ 'ESCAPE_CHAR' => array(
+ 0 => 'color: #000099; font-weight: bold;'
+ ),
+ 'BRACKETS' => array(
+ 0 => 'color: #009900;'
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #0000ff;'
+ ),
+ 'NUMBERS' => array(
+ 0 => 'color: #cc66cc;',
+ ),
+ 'METHODS' => array(
+ 0 => 'color: #004000;'
+ ),
+ 'SYMBOLS' => array(
+ 1 => 'color: #339933;'
+ ),
+ 'REGEXPS' => array(),
+ 'SCRIPT' => array()
+ ),
+ 'URLS' => array(1 => ''),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array(),
+ 'REGEXPS' => array(),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array(),
+ 'HIGHLIGHT_STRICT_BLOCK' => array()
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/verilog.php b/plugins/wp-syntax/geshi/geshi/verilog.php
index 3c3c2249..2bf66d1c 100644
--- a/plugins/wp-syntax/geshi/geshi/verilog.php
+++ b/plugins/wp-syntax/geshi/geshi/verilog.php
@@ -4,7 +4,7 @@
* -----------
* Author: G�nter Dannoritzer <dannoritzer@web.de>
* Copyright: (C) 2008 Guenter Dannoritzer
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/05/28
*
* Verilog language file for GeSHi.
@@ -53,7 +53,7 @@ $language_data = array (
'casex', 'casez', 'cmos', 'deassign', 'default', 'defparam',
'disable', 'edge', 'else', 'end', 'endcase', 'endfunction',
'endmodule', 'endprimitive', 'endspecify', 'endtable', 'endtask',
- 'event', 'for', 'force', 'forever', 'function', 'highz0',
+ 'event', 'fork', 'for', 'force', 'forever', 'function', 'highz0',
'highz1', 'if', 'ifnone', 'initial', 'inout', 'input', 'integer',
'join', 'large', 'macromodule', 'medium', 'module', 'nand',
'negedge', 'nmos', 'nor', 'not', 'notif0', 'notif1', 'or',
diff --git a/plugins/wp-syntax/geshi/geshi/vhdl.php b/plugins/wp-syntax/geshi/geshi/vhdl.php
index 386604c0..a8f37e67 100644
--- a/plugins/wp-syntax/geshi/geshi/vhdl.php
+++ b/plugins/wp-syntax/geshi/geshi/vhdl.php
@@ -3,14 +3,21 @@
* vhdl.php
* --------
* Author: Alexander 'E-Razor' Krause (admin@erazor-zone.de)
+ * Contributors:
+ * - Kevin Thibedeau (kevinpt@yahoo.com)
* Copyright: (c) 2005 Alexander Krause
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/06/15
*
* VHDL (VHSICADL, very high speed integrated circuit HDL) language file for GeSHi.
*
* CHANGES
* -------
+ * 2012/4/30 (1.0.8.10)
+ * - Reworked to support new features of VHDL-2008.
+ * - Changes include: multi-line comments, all new keywords, PSL keywords and metacomments,
+ * - based literals, attribute highlighting, preprocessor macros (from PSL), and other small
+ * - improvements.
* 2008/05/23 (1.0.7.22)
* - Added description of extra language features (SF#1970248)
* - Optimized regexp group 0 somewhat
@@ -43,56 +50,80 @@
$language_data = array (
'LANG_NAME' => 'VHDL',
'COMMENT_SINGLE' => array(1 => '--'),
- 'COMMENT_MULTI' => array('%' => '%'),
+ 'COMMENT_MULTI' => array('/*' => '*/'),
+ 'COMMENT_REGEXP' => array(
+ // PSL adds C-preprocessor support
+ 1 => '/(?<=\s)#(?:\\\\\\\\|\\\\\\n|.)*$/m',
+ // PSL metacomments (single-line only for now)
+ 2 => '/--\s*@?psl(?:.)*?;$/m',
+ ),
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
'QUOTEMARKS' => array('"'),
'ESCAPE_CHAR' => '',
'KEYWORDS' => array(
/*keywords*/
1 => array(
- 'access','after','alias','all','assert','attribute','architecture','begin',
- 'block','body','buffer','bus','case','component','configuration','constant',
- 'disconnect','downto','else','elsif','end','entity','exit','file','for',
+ 'access','after','alias','all','attribute','architecture','array','begin',
+ 'block','body','buffer','bus','case','case?','component','configuration','constant','context',
+ 'disconnect','downto','else','elsif','end','entity','exit','file','for','force',
'function','generate','generic','group','guarded','if','impure','in',
'inertial','inout','is','label','library','linkage','literal','loop',
'map','new','next','null','of','on','open','others','out','package',
- 'port','postponed','procedure','process','pure','range','record','register',
- 'reject','report','return','select','severity','signal','shared','subtype',
+ 'port','postponed','procedure','process','protected','pure','range','record','register',
+ 'reject','release','report','return','select','severity','shared','signal','subtype',
'then','to','transport','type','unaffected','units','until','use','variable',
- 'wait','when','while','with','note','warning','error','failure','and',
- 'or','xor','not','nor','used','memory','segments','dff','dffe','help_id',
- 'mod','info','latch','rising_edge','falling_edge'
- ),
- /*types*/
+ 'wait','when','while','with'
+ ),
+ /*types and standard libs*/
2 => array(
- 'bit','bit_vector','character','boolean','integer','real','time','string',
+ 'bit','bit_vector','character','boolean','integer','real','time','delay_length','string',
'severity_level','positive','natural','signed','unsigned','line','text',
- 'std_logic','std_logic_vector','std_ulogic','std_ulogic_vector','qsim_state',
- 'qsim_state_vector','qsim_12state','qsim_12state_vector','qsim_strength',
- 'mux_bit','mux_vector','reg_bit','reg_vector','wor_bit','wor_vector',
- 'work','ieee','std_logic_signed','std_logic_1164','std_logic_arith',
- 'numeric_std'
-
- ),
+ 'std_logic','std_logic_vector','std_ulogic','std_ulogic_vector',
+ 'sfixed','ufixed','float','float32','float64','float128',
+ 'work','ieee','std_logic_1164','math_real','math_complex','textio',
+ 'numeric_std','numeric_std_signed','numeric_std_unsigned','numeric_bit'
+ ),
/*operators*/
- ),
+ 3 => array(
+ 'abs','and','mod','nor','not','or','rem','rol','ror','sla','sll','sra','srl','xnor','xor'
+ ),
+ /*psl*/
+ 4 => array(
+ 'assert','assume','assume_guarantee','clock','const','countones','cover','default',
+ 'endpoint','fairness','fell','forall','inf','inherit','isunknown','onehot','onehot0','property',
+ 'prev','restrict','restrict_guarantee','rose','sequence','stable','strong','union','vmode','vprop','vunit'
+ ),
+ /*psl operators*/
+ 5 => array(
+ 'abort','always','before','before!','before!_','before_','eventually!','never',
+ 'next!','next_a','next_a!','next_e','next_e!','next_event','next_event!','next_event_a','next_event_a!',
+ 'next_event_e','next_event_e!','until!','until!_','until_','within'
+ )
+ ),
'SYMBOLS' => array(
'[', ']', '(', ')',
';',':',
- '<','>','=','<=',':=','=>','=='
+ '<','>','=','+','-','*','/','&','|','?'
),
'CASE_SENSITIVE' => array(
GESHI_COMMENTS => false,
1 => false,
- 2 => false
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false
),
'STYLES' => array(
'KEYWORDS' => array(
1 => 'color: #000080; font-weight: bold;',
- 2 => 'color: #0000ff;'
+ 2 => 'color: #0000ff;',
+ 3 => 'color: #000066;',
+ 4 => 'color: #000080; font-weight: bold;',
+ 5 => 'color: #000066;'
),
'COMMENTS' => array(
1 => 'color: #008000; font-style: italic;',
+ 2 => 'color: #ff0000; font-weight: bold;',
'MULTI' => 'color: #008000; font-style: italic;'
),
'ESCAPE_CHAR' => array(
@@ -114,25 +145,33 @@ $language_data = array (
),
'REGEXPS' => array(
0 => 'color: #ff0000;',
- 1 => 'color: #ff0000;'
+ //1 => 'color: #ff0000;',
+ 2 => 'color: #ee82ee;'
),
'SCRIPT' => array(
)
),
'URLS' => array(
1 => '',
- 2 => ''
- ),
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => ''
+ ),
'OOLANG' => false,
'OBJECT_SPLITTERS' => array(
),
'REGEXPS' => array(
- //Hex numbers and scientific notation for numbers
- 0 => '(\b0x[0-9a-fA-F]+|\b\d[0-9a-fA-F]+[hH])|'.
- '(\b\d+?(\.\d+?)?E[+\-]?\d+)|(\bns)|'.
- "('[0-9a-zA-Z]+(?!'))",
- //Number characters?
- 1 => "\b(''\d'')"
+ //Based literals, scientific notation, and time units
+ 0 => '(\b\d+#[[:xdigit:]_]+#)|'.
+ '(\b[\d_]+(\.[\d_]+)?[eE][+\-]?[\d_]+)|'.
+ '(\b(hr|min|sec|ms|us|ns|ps|fs)\b)',
+ //Character literals
+ /* GeSHi won't match this pattern for some reason and QUOTEMARKS
+ * can't be used because it interferes with attribute parsing */
+ /*1 => "\b'.'\b",*/
+ //Attributes
+ 2 => "'\w+(?!')"
),
'STRICT_MODE_APPLIES' => GESHI_NEVER,
'SCRIPT_DELIMITERS' => array(
diff --git a/plugins/wp-syntax/geshi/geshi/vim.php b/plugins/wp-syntax/geshi/geshi/vim.php
index 0d63ccdb..fe7e5e00 100644
--- a/plugins/wp-syntax/geshi/geshi/vim.php
+++ b/plugins/wp-syntax/geshi/geshi/vim.php
@@ -6,7 +6,7 @@
* Contributors:
* - Laurent Peuch (psycojoker@gmail.com)
* Copyright: (c) 2008 Swaroop C H (http://www.swaroopch.com)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/10/19
*
* Vim scripting language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/visualfoxpro.php b/plugins/wp-syntax/geshi/geshi/visualfoxpro.php
index a14bed82..123a3db4 100644
--- a/plugins/wp-syntax/geshi/geshi/visualfoxpro.php
+++ b/plugins/wp-syntax/geshi/geshi/visualfoxpro.php
@@ -4,7 +4,7 @@
* ----------------
* Author: Roberto Armellin (r.armellin@tin.it)
* Copyright: (c) 2004 Roberto Armellin, Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/09/17
*
* Visual FoxPro language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/visualprolog.php b/plugins/wp-syntax/geshi/geshi/visualprolog.php
index 21827193..d36f1c67 100644
--- a/plugins/wp-syntax/geshi/geshi/visualprolog.php
+++ b/plugins/wp-syntax/geshi/geshi/visualprolog.php
@@ -4,7 +4,7 @@
* ----------
* Author: Thomas Linder Puls (puls@pdc.dk)
* Copyright: (c) 2008 Thomas Linder Puls (puls@pdc.dk)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/11/20
*
* Visual Prolog language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/whitespace.php b/plugins/wp-syntax/geshi/geshi/whitespace.php
index 91186d3f..58f39637 100644
--- a/plugins/wp-syntax/geshi/geshi/whitespace.php
+++ b/plugins/wp-syntax/geshi/geshi/whitespace.php
@@ -4,7 +4,7 @@
* ----------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2009/10/31
*
* Whitespace language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/whois.php b/plugins/wp-syntax/geshi/geshi/whois.php
index 24065ed1..a89e4731 100644
--- a/plugins/wp-syntax/geshi/geshi/whois.php
+++ b/plugins/wp-syntax/geshi/geshi/whois.php
@@ -4,7 +4,7 @@
* --------
* Author: Benny Baumann (BenBE@geshi.org)
* Copyright: (c) 2008 Benny Baumann (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/09/14
*
* Whois response (RPSL format) language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/winbatch.php b/plugins/wp-syntax/geshi/geshi/winbatch.php
index a39d1de8..3599a027 100644
--- a/plugins/wp-syntax/geshi/geshi/winbatch.php
+++ b/plugins/wp-syntax/geshi/geshi/winbatch.php
@@ -4,7 +4,7 @@
* ------------
* Author: Craig Storey (storey.craig@gmail.com)
* Copyright: (c) 2004 Craig Storey (craig.xcottawa.ca)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2006/05/19
*
* WinBatch language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/xbasic.php b/plugins/wp-syntax/geshi/geshi/xbasic.php
index b30c02cf..2edede36 100644
--- a/plugins/wp-syntax/geshi/geshi/xbasic.php
+++ b/plugins/wp-syntax/geshi/geshi/xbasic.php
@@ -4,9 +4,8 @@
* ----------
* Author: José Gabriel Moya Yangüela (josemoya@gmail.com)
* Copyright: (c) 2005 José Gabriel Moya Yangüela (http://aprenderadesaprender.6te.net)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2005/11/23
- * Last Modified: $Date: 2010/01/30 00:42:00 $
*
* XBasic language file for GeSHi.
*
diff --git a/plugins/wp-syntax/geshi/geshi/xml.php b/plugins/wp-syntax/geshi/geshi/xml.php
index e85a5564..6354e457 100644
--- a/plugins/wp-syntax/geshi/geshi/xml.php
+++ b/plugins/wp-syntax/geshi/geshi/xml.php
@@ -4,7 +4,7 @@
* -------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie (http://qbnz.com/highlighter/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2004/09/01
*
* XML language file for GeSHi. Based on the idea/file by Christian Weiske
diff --git a/plugins/wp-syntax/geshi/geshi/xorg_conf.php b/plugins/wp-syntax/geshi/geshi/xorg_conf.php
index 388850d7..99edc665 100644
--- a/plugins/wp-syntax/geshi/geshi/xorg_conf.php
+++ b/plugins/wp-syntax/geshi/geshi/xorg_conf.php
@@ -4,7 +4,7 @@
* ----------
* Author: Milian Wolff (mail@milianw.de)
* Copyright: (c) 2008 Milian Wolff (http://milianw.de)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2008/06/18
*
* xorg.conf language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/xpp.php b/plugins/wp-syntax/geshi/geshi/xpp.php
index 367a1c68..a06e2779 100644
--- a/plugins/wp-syntax/geshi/geshi/xpp.php
+++ b/plugins/wp-syntax/geshi/geshi/xpp.php
@@ -4,7 +4,7 @@
* -------
* Author: Simon Butcher (simon@butcher.name)
* Copyright: (c) 2007 Simon Butcher (http://simon.butcher.name/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/02/27
*
* Axapta/Dynamics Ax X++ language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/yaml.php b/plugins/wp-syntax/geshi/geshi/yaml.php
new file mode 100644
index 00000000..a2974eb5
--- /dev/null
+++ b/plugins/wp-syntax/geshi/geshi/yaml.php
@@ -0,0 +1,150 @@
+<?php
+/*************************************************************************************
+ * yaml.php
+ * --------
+ * Author: Josh Ventura (JoshV10@gmail.com)
+ * Copyright: (c) 2010 Josh Ventura
+ * Release Version: 1.0.8.11
+ * Date Started: 2010/12/14
+ *
+ * YAML language file for GeSHi.
+ *
+ * YAML gets hairy sometimes. If anything needs fixed, drop me an email and
+ * I'll probably spit up on it. This is, in general, not a long format.
+ *
+ * CHANGES
+ * ---------
+ * 2010/12/14
+ * - Started project in rage over GML support but not YAML support. WTFH?
+ * 2010/12/15
+ * - Submitted to Ben.
+ *
+ * TODO (not updated since release)
+ * ----------------------------------
+ * - Field testing and necessary corrections: this grammar file is usable, but not
+ * completely accurate. There are, in fact, multiple cases in which it will mess
+ * up, and some of it may need moved around. It is the most temperamental parser
+ * I have ever associated my name with. Points of interest follow:
+ * * Improvised support for | and >: since PHP offers no variable-width lookbehind,
+ * these blocks will still be highlighted even when commented out. As it happens,
+ * any line ending with | or > could result in the unintentional highlighting of
+ * all remaining lines in the file, just because I couldn't check for this regex
+ * as a lookbehind: '/:(\s+)(!!(\w+)(\s+))?/'
+ * If there is a workaround for that, it needs implemented.
+ * * I may be missing some operators. I deliberately omitted inline array notation
+ * as, in general, it's ugly and tends to conflict with plain-text. Ensuring all
+ * highlighted list delimiters are not plain text would be as simple as checking
+ * that they follow a colon directly. Alas, without variable-length lookbehinds,
+ * if there is a way to do so in GeSHi I am unaware of it.
+ * * I kind of whored the comment regexp array. It seemed like a safe bet, so it's
+ * where I crammed everything. Some of it may need moved elsewhere for neatness.
+ * * The !!typename highlight needs not to interfere with ": |" and ": >": Pairing
+ * key: !!type | value is perfectly legal, but again due to lookbehind issues, I
+ * can't add a case for that. Also, it is likely that multiple spaces can be put
+ * between the colon and pipe symbol, which would also break it.
+ *
+ *************************************************************************************
+ *
+ * This file is part of GeSHi.
+ *
+ * GeSHi is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GeSHi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GeSHi; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ ************************************************************************************/
+
+$language_data = array (
+ 'LANG_NAME' => 'YAML',
+ 'COMMENT_SINGLE' => array(),
+ 'COMMENT_MULTI' => array(),
+ //Keys
+ 'COMMENT_REGEXP' => array( // ENTRY ZERO SHOULD CHECK FOR (\n(\s*)([^#%]+?):(\s+)(!!(\w+)(\s+))?) AS A LOOKBEHIND, BUT IT CAN'T.
+ 0 => '/(?<=\s[\|>]\n)(\s+)(.*)((?=[\n$])(([\n^](\1(.*)|(?=[\n$])))*)|$)/', // Pipe blocks and > blocks.
+ 1 => '/#(.*)/', // Blue # comments
+ 2 => '/%(.*)/', // Red % comments
+ 3 => '/(^|\n)([^#%^\n]+?)(?=: )/', // Key-value names
+ 4 => '/(^|\n)([^#%^\n]+?)(?=:\n)/',// Key-group names
+ 5 => '/(?<=^---)(\s*)!(\S+)/', // Comments after ---
+ 6 => '/(?<=: )(\s*)\&(\S+)/', // References
+ 7 => '/(?<=: )(\s*)\*(\S+)/', // Dereferences
+ 8 => '/!!(\w+)/', // Types
+ //9 => '/(?<=\n)(\s*)-(?!-)/', // List items: This needs to search within comments 3 and 4, but I don't know how.
+ ),
+ 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
+ 'QUOTEMARKS' => array('"'),
+ 'ESCAPE_CHAR' => '',
+ 'KEYWORDS' => array(
+ 1 => array(
+ 'all','any','none', "yes", "no"
+ ),
+ ),
+ 'SYMBOLS' => array(
+ 1 => array('---', '...'),
+ 2 => array(': ', ">\n", "|\n", '<<:', ":\n") // It'd be nice if I could specify that the colon must
+ // follow comment 3 or 4 to be considered, and the > and |
+ // must follow such a colon.
+ ),
+ 'CASE_SENSITIVE' => array(
+ GESHI_COMMENTS => false,
+ 1 => false,
+ ),
+ 'STYLES' => array(
+ 'KEYWORDS' => array(
+ 1 => 'font-weight: bold;'
+ ),
+ 'COMMENTS' => array(
+ 0 => 'color: #303050;background-color: #F5F5F5',
+ 1 => 'color: blue;',
+ 2 => 'font-weight: bold; color: red;',
+ 3 => 'color: green;',
+ 4 => 'color: #007F45;',
+ 5 => 'color: #7f7fFF;',
+ 6 => 'color: #FF7000;',
+ 7 => 'color: #FF45C0;',
+ 8 => 'font-weight: bold; color: #005F5F;',
+ //9 => 'font-weight: bold; color: #000000;',
+ ),
+ 'ESCAPE_CHAR' => array(
+ ),
+ 'BRACKETS' => array(
+ ),
+ 'STRINGS' => array(
+ 0 => 'color: #CF00CF;'
+ ),
+ 'NUMBERS' => array(
+ // 0 => 'color: #33f;' // Don't highlight numbers, really...
+ ),
+ 'METHODS' => array(
+ 1 => '',
+ 2 => ''
+ ),
+ 'SYMBOLS' => array(
+ 1 => 'color: cyan;',
+ 2 => 'font-weight: bold; color: brown;'
+ ),
+ 'REGEXPS' => array(
+ ),
+ 'SCRIPT' => array(
+ 0 => ''
+ )
+ ),
+ 'URLS' => array(1 => ''),
+ 'OOLANG' => false,
+ 'OBJECT_SPLITTERS' => array( ),
+ 'REGEXPS' => array( ),
+ 'STRICT_MODE_APPLIES' => GESHI_NEVER,
+ 'SCRIPT_DELIMITERS' => array( ),
+ 'HIGHLIGHT_STRICT_BLOCK' => array( )
+);
+
+?> \ No newline at end of file
diff --git a/plugins/wp-syntax/geshi/geshi/z80.php b/plugins/wp-syntax/geshi/geshi/z80.php
index 5ab146bf..47326bb2 100644
--- a/plugins/wp-syntax/geshi/geshi/z80.php
+++ b/plugins/wp-syntax/geshi/geshi/z80.php
@@ -4,7 +4,7 @@
* -------
* Author: Benny Baumann (BenBE@omorphia.de)
* Copyright: (c) 2007-2008 Benny Baumann (http://www.omorphia.de/)
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2007/02/06
*
* ZiLOG Z80 Assembler language file for GeSHi.
diff --git a/plugins/wp-syntax/geshi/geshi/zxbasic.php b/plugins/wp-syntax/geshi/geshi/zxbasic.php
index 430e5f6a..b1de472b 100644
--- a/plugins/wp-syntax/geshi/geshi/zxbasic.php
+++ b/plugins/wp-syntax/geshi/geshi/zxbasic.php
@@ -4,7 +4,7 @@
* -------------
* Author: Jose Rodriguez (a.k.a. Boriel)
* Based on Copyright: (c) 2005 Roberto Rossi (http://rsoftware.altervista.org) Freebasic template
- * Release Version: 1.0.8.9
+ * Release Version: 1.0.8.11
* Date Started: 2010/06/19
*
* ZXBasic language file for GeSHi.
diff --git a/plugins/wp-syntax/js/wp-syntax.js b/plugins/wp-syntax/js/wp-syntax.js
new file mode 100644
index 00000000..f7f6c739
--- /dev/null
+++ b/plugins/wp-syntax/js/wp-syntax.js
@@ -0,0 +1,34 @@
+jQuery(document).ready(function($)
+{
+ $('.wp_syntax').bind(
+ {
+ mouseover: function()
+ {
+ var w = $(this).find('table').outerWidth();
+ var hw = $(document).width() - $(this).offset().left - 20;
+
+ /*
+ * Test code.
+ */
+ /*var left, top;
+ left = $(this).offset().left;
+ top = $(this).offset().top;
+
+ $(this)
+ .appendTo('body')
+ .css({
+ 'position': 'absolute',
+ 'left': left + 'px',
+ 'top': top + 'px'
+ });
+ */
+
+ if(w > $(this).outerWidth())
+ $(this).css({'position':'relative', 'z-index':'9999', 'box-shadow':'5px 5px 5px #888', 'width':(w > hw ? hw : w)+'px'});
+ },
+ mouseout: function()
+ {
+ //$(this).removeAttr('style');
+ }
+ });
+}); \ No newline at end of file
diff --git a/plugins/wp-syntax/wp-syntax.php b/plugins/wp-syntax/wp-syntax.php
index 3d195ead..d3a95ffe 100644
--- a/plugins/wp-syntax/wp-syntax.php
+++ b/plugins/wp-syntax/wp-syntax.php
@@ -1,207 +1,372 @@
<?php
/*
Plugin Name: WP-Syntax
-Plugin URI: http://wordpress.org/extend/plugins/wp-syntax/
-Description: Syntax highlighting using <a href="http://qbnz.com/highlighter/">GeSHi</a> supporting a wide range of popular languages. Wrap code blocks with <code>&lt;pre lang="LANGUAGE" line="1"&gt;</code> and <code>&lt;/pre&gt;</code> where <code>LANGUAGE</code> is a geshi supported language syntax. The <code>line</code> attribute is optional.
+Plugin URI: http://www.connections-pro.com
+Description: Syntax highlighting using <a href="http://qbnz.com/highlighter/">GeSHi</a> supporting a wide range of popular languages.
+Version: 1.0
Author: Steven A. Zahm
-Version: 0.9.12
-Author URI: http://connections-pro.com
+Author URI: http://www.connections-pro.com
+License: GPL2
+Text Domain: wp_syntax
+Domain Path: /lang
+
+Original Author: Ryan McGeary
+
+Copyright 2013 Steven A. Zahm (email : helpdesk@connections-pro.com)
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License, version 2, as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-# Original Author: Ryan McGeary
-
-#
-# Copyright (c) 2007-2009 Ryan McGeary 2010 Steven A. Zahm
-#
-# This file is part of WP-Syntax.
-#
-# WP-Syntax is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation; either version 2 of the License, or (at your option)
-# any later version.
-#
-# WP-Syntax is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along
-# with WP-Syntax; if not, write to the Free Software Foundation, Inc., 59
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-// Override allowed attributes for pre tags in order to use <pre lang=""> in
-// comments. For more info see wp-includes/kses.php
-if (!CUSTOM_TAGS) {
- $allowedposttags['pre'] = array(
- 'lang' => array(),
- 'line' => array(),
- 'escaped' => array(),
- 'style' => array(),
- 'width' => array(),
- 'highlight' => array()
- );
- //Allow plugin use in comments
- $allowedtags['pre'] = array(
- 'lang' => array(),
- 'line' => array(),
- 'escaped' => array(),
- 'highlight' => array()
- );
-}
-
-include_once("geshi/geshi.php");
-
-if (!defined("WP_CONTENT_URL")) define("WP_CONTENT_URL", get_option("siteurl") . "/wp-content");
-if (!defined("WP_PLUGIN_URL")) define("WP_PLUGIN_URL", WP_CONTENT_URL . "/plugins");
-
-function wp_syntax_head()
-{
- /*$css_url = WP_PLUGIN_URL . "/wp-syntax/wp-syntax.css";
- if (file_exists(TEMPLATEPATH . "/wp-syntax.css"))
- {
- $css_url = get_bloginfo("template_url") . "/wp-syntax.css";
- }
- echo "\n".'<link rel="stylesheet" href="' . $css_url . '" type="text/css" media="screen" />'."\n";*/
-
- $css_url = WP_PLUGIN_URL . "/wp-syntax/wp-syntax.css";
- if (file_exists(STYLESHEETPATH . "/wp-syntax.css"))
- {
- $css_url = get_bloginfo("stylesheet_directory") . "/wp-syntax.css";
- }
- echo "\n".'<link rel="stylesheet" href="' . $css_url . '" type="text/css" media="screen" />'."\n";
-}
-
-function wp_syntax_code_trim($code)
-{
- // special ltrim b/c leading whitespace matters on 1st line of content
- $code = preg_replace("/^\s*\n/siU", "", $code);
- $code = rtrim($code);
- return $code;
-}
-
-function wp_syntax_substitute(&$match)
-{
- global $wp_syntax_token, $wp_syntax_matches;
-
- $i = count($wp_syntax_matches);
- $wp_syntax_matches[$i] = $match;
-
- return "\n\n<p>" . $wp_syntax_token . sprintf("%03d", $i) . "</p>\n\n";
-}
-
-function wp_syntax_line_numbers($code, $start)
-{
- $line_count = count(explode("\n", $code));
- $output = "<pre>";
- for ($i = 0; $i < $line_count; $i++)
- {
- $output .= ($start + $i) . "\n";
- }
- $output .= "</pre>";
- return $output;
-}
-
-function wp_syntax_highlight($match)
-{
- global $wp_syntax_matches;
-
- $i = intval($match[1]);
- $match = $wp_syntax_matches[$i];
-
- $language = strtolower(trim($match[1]));
- $line = trim($match[2]);
- $escaped = trim($match[3]);
-
- $code = wp_syntax_code_trim($match[5]);
- if ($escaped == "true") $code = htmlspecialchars_decode($code);
-
- $geshi = new GeSHi($code, $language);
- $geshi->enable_keyword_links(false);
- do_action_ref_array('wp_syntax_init_geshi', array(&$geshi));
-
- //START LINE HIGHLIGHT SUPPORT
- $highlight = array();
- if ( !empty($match[4]) )
- {
- $highlight = strpos($match[4],',') == false ? array($match[4]) : explode(',', $match[4]);
-
- $h_lines = array();
- for( $i=0; $i<sizeof($highlight); $i++ )
- {
- $h_range = explode('-', $highlight[$i]);
-
- if( sizeof($h_range) == 2 )
- $h_lines = array_merge( $h_lines, range($h_range[0], $h_range[1]) );
- else
- array_push($h_lines, $highlight[$i]);
+/*
+@todo integrate TinyMCE button support using one of these as a base:
+ http://wordpress.org/extend/plugins/wp-syntax-integration/
+ http://wordpress.org/extend/plugins/wp-syntax-button/
+@todo Merge this add-on plugin functionality: http://wordpress.org/extend/plugins/wp-syntax-download-extension/
+
+Look at these: http://wordpress.org/extend/plugins/wp-synhighlight/
+ http://wordpress.org/extend/plugins/wp-codebox/
+ */
+
+if ( ! class_exists( 'WP_Syntax' ) ) {
+
+ class WP_Syntax {
+
+ /**
+ * @var (object) WP_Syntax stores the instance of this class.
+ */
+ private static $instance;
+
+ private static $token;
+
+ private static $matches;
+
+ /**
+ * A dummy constructor to prevent WP_Syntax from being loaded more than once.
+ *
+ * @access private
+ * @since 1.0
+ * @see WP_Syntax::instance()
+ * @see WP_Syntax();
+ */
+ private function __construct() { /* Do nothing here */ }
+
+ /**
+ * Main WP_Syntax Instance
+ *
+ * Insures that only one instance of WP_Syntax exists in memory at any one time.
+ *
+ * @access public
+ * @since 1.0
+ * @return object WP_Syntax
+ */
+ public static function getInstance() {
+ if ( ! isset( self::$instance ) ) {
+ self::$instance = new self;
+ self::$instance->init();
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Initiate the plugin.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ private function init() {
+
+ self::defineConstants();
+ self::inludeDependencies();
+
+ self::$token = md5( uniqid( rand() ) );
+
+ self::$matches = array();
+
+ // Nothing to do during activation/deactivation yet...
+ // register_activation_hook( dirname(__FILE__) . '/wp-syntax.php', array( __CLASS__, 'activate' ) );
+ // register_deactivation_hook( dirname(__FILE__) . '/wp-syntax.php', array( __CLASS__, 'deactivate' ) );
+
+ // Nothing to translate presently.
+ // load_plugin_textdomain( 'wp_syntax' , false , WPS__DIR_NAME . 'lang' );
+
+ add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueueScripts' ) );
+
+ // Update config for WYSIWYG editor to accept the pre tag and its attributes.
+ add_filter( 'tiny_mce_before_init', array( __CLASS__,'tinyMCEConfig') );
+
+ // We want to run before other filters; hence, a priority of 0 was chosen.
+ // The lower the number, the higher the priority. 10 is the default and
+ // several formatting filters run at or around 6.
+ add_filter( 'the_content', array( __CLASS__, 'beforeFilter' ), 0);
+ add_filter( 'the_excerpt', array( __CLASS__, 'beforeFilter' ), 0);
+ add_filter( 'comment_text', array( __CLASS__, 'beforeFilter' ), 0);
+
+ // We want to run after other filters; hence, a priority of 99.
+ add_filter( 'the_content', array( __CLASS__, 'afterFilter' ), 99);
+ add_filter( 'the_excerpt', array( __CLASS__, 'afterFilter' ), 99);
+ add_filter( 'comment_text', array( __CLASS__, 'afterFilter' ), 99);
+
+ }
+
+ /**
+ * Define the constants.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ private static function defineConstants() {
+
+ define( 'WPS_VERSION', '1.0' );
+
+ define( 'WPS_DIR_NAME', plugin_basename( dirname( __FILE__ ) ) );
+ define( 'WPS_BASE_NAME', plugin_basename( __FILE__ ) );
+ define( 'WPS_BASE_PATH', plugin_dir_path( __FILE__ ) );
+ define( 'WPS_BASE_URL', plugin_dir_url( __FILE__ ) );
+
+ }
+
+ private static function inludeDependencies() {
+
+ include_once( 'geshi/geshi.php' );
+
+ }
+
+ /**
+ * Called when activating via the activation hook.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ public static function activate() {
+
+ }
+
+ /**
+ * Called when deactivating via the deactivation hook.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ public static function deactivate() {
+
+ }
+
+ /**
+ * Enqueue the CSS and JavaScripts.
+ *
+ * @access private
+ * @since 1.0
+ * @return void
+ */
+ public static function enqueueScripts() {
+
+ // If a wp-syntax.css file exists in the theme folder use it instead.
+ $url = file_exists( STYLESHEETPATH . '/wp-syntax.css' ) ? get_bloginfo( 'stylesheet_directory' ) . '/wp-syntax.css' : WPS_BASE_URL . 'css/wp-syntax.css';
+
+ // Enqueue the CSS
+ wp_enqueue_style( 'wp-syntax-css', $url, array(), WPS_VERSION );
+
+ // Enqueue the JavaScript
+ // wp_enqueue_script( 'wp-syntax-js', WPS_BASE_URL . 'js/wp-syntax.js', array( 'jquery' ), WPS_VERSION, TRUE );
+
+ }
+
+ /**
+ * Update the TinyMCE config to add support for the pre tag and its attributes.
+ *
+ * @access private
+ * @since 0.9.13
+ * @param (array) $init The TinyMCE config.
+ * @return (array)
+ */
+ public static function tinyMCEConfig( $init ) {
+
+ $ext = 'pre[id|name|class|style|lang|line|escaped|highlight|src]';
+
+ if ( isset( $init['extended_valid_elements'] ) ) {
+ $init['extended_valid_elements'] .= "," . $ext;
+ } else {
+ $init['extended_valid_elements'] = $ext;
+ }
+
+ return $init;
+ }
+
+ // special ltrim b/c leading whitespace matters on 1st line of content
+ public static function trimCode( $code ) {
+ $code = preg_replace("/^\s*\n/siU", '', $code);
+ $code = rtrim ($code );
+ return $code;
+ }
+
+ public static function substituteToken( &$match ) {
+ // global $wp_syntax_token, $wp_syntax_matches;
+
+ $i = count( self::$matches );
+ self::$matches[ $i ] = $match;
+
+ return "\n\n<p>" . self::$token . sprintf( '%03d', $i ) . "</p>\n\n";
+ }
+
+ public static function lineNumbers( $code, $start ) {
+
+ $line_count = count( explode( "\n", $code ) );
+ $output = '<pre>';
+
+ for ( $i = 0; $i < $line_count; $i++ ) {
+ $output .= ( $start + $i ) . "\n";
+ }
+
+ $output .= '</pre>';
+
+ return $output;
+ }
+
+ public static function caption( $url ) {
+
+ $parsed = parse_url( $url );
+ $path = pathinfo( $parsed['path'] );
+ $caption = '';
+
+ if ( ! isset( $path['filename'] ) ) {
+ return;
+ }
+
+ if ( isset( $parsed['scheme'] ) ) {
+ $caption .= '<a href="' . $url . '">';
+ }
+
+ if ( isset( $parsed["host"] ) && $parsed["host"] == 'github.com' )
+ {
+ $caption .= substr( $parsed['path'], strpos( $parsed['path'], '/', 1 ) ); /* strip github.com username */
+ } else {
+ $caption .= $parsed['path'];
+ }
+
+ /* $caption . $path["filename"];
+ if (isset($path["extension"])) {
+ $caption .= "." . $path["extension"];
+ }*/
+
+ if ( isset($parsed['scheme']) ) {
+ $caption .= '</a>';
+ }
+
+ return $caption;
+ }
+
+ public static function highlight( $match ) {
+ // global $wp_syntax_matches;
+
+ $i = intval( $match[1] );
+ $match = self::$matches[ $i ];
+
+ $language = strtolower( trim( $match[1] ) );
+ $line = trim( $match[2] );
+ $escaped = trim( $match[3] );
+ $caption = self::caption( $match[5] );
+ $code = self::trimCode( $match[6] );
+
+ if ( $escaped == 'true' ) $code = htmlspecialchars_decode( $code );
+
+ $geshi = new GeSHi( $code, $language );
+ $geshi->enable_keyword_links( FALSE );
+
+ do_action_ref_array( 'wp_syntax_init_geshi', array( &$geshi ) );
+
+ if ( ! empty( $match[4] ) ) {
+
+ $linespecs = strpos( $match[4], ",") == FALSE ? array( $match[4] ) : explode( ',', $match[4] );
+ $lines = array();
+
+ foreach ( $linespecs as $spec ) {
+ $range = explode( '-', $spec );
+ $lines = array_merge( $lines, ( count( $range ) == 2) ? range( $range[0], $range[1]) : $range );
+ }
+
+ $geshi->highlight_lines_extra( $lines );
+ }
+
+ $output = "\n" . '<div class="wp_syntax">';
+ $output .= '<table>';
+
+ if ( ! empty( $caption ) ) {
+ $output .= '<caption>' . $caption . '</caption>';
+ }
+
+ $output .= '<tr>';
+
+ if ( $line ) {
+ $output .='<td class="line_numbers">' . self::lineNumbers( $code, $line ) . '</td>';
+ }
+
+ $output .= '<td class="code">';
+ $output .= $geshi->parse_code();
+ $output .= '</td></tr></table>';
+ $output .= '</div>' . "\n";
+
+ return $output;
+ }
+
+ public static function beforeFilter( $content ) {
+
+ return preg_replace_callback(
+ "/\s*<pre(?:lang=[\"']([\w-]+)[\"']|line=[\"'](\d*)[\"']|escaped=[\"'](true|false)?[\"']|highlight=[\"']((?:\d+[,-])*\d+)[\"']|src=[\"']([^\"']+)[\"']|\s)+>(.*)<\/pre>\s*/siU",
+ array( __CLASS__, 'substituteToken' ),
+ $content
+ );
+
+ }
+
+ public static function afterFilter( $content ) {
+ // global $wp_syntax_token;
+
+ $content = preg_replace_callback(
+ '/<p>\s*' . self::$token . '(\d{3})\s*<\/p>/si',
+ array( __CLASS__, 'highlight' ),
+ $content
+ );
+
+ return $content;
+ }
+
}
- $geshi->highlight_lines_extra( $h_lines );
- }
- //END LINE HIGHLIGHT SUPPORT
-
- $output = "\n<div class=\"wp_syntax\">";
-
- if ($line)
- {
- $output .= "<table><tr><td class=\"line_numbers\">";
- $output .= wp_syntax_line_numbers($code, $line);
- $output .= "</td><td class=\"code\">";
- $output .= $geshi->parse_code();
- $output .= "</td></tr></table>";
- }
- else
- {
- $output .= "<div class=\"code\">";
- $output .= $geshi->parse_code();
- $output .= "</div>";
- }
- return
-
- $output .= "</div>\n";
-
- return $output;
-}
-
-function wp_syntax_before_filter($content)
-{
- return preg_replace_callback(
- "/\s*<pre(?:lang=[\"']([\w-]+)[\"']|line=[\"'](\d*)[\"']|escaped=[\"'](true|false)?[\"']|highlight=[\"']((?:\d+[,-])*\d+)[\"']|\s)+>(.*)<\/pre>\s*/siU",
- "wp_syntax_substitute",
- $content
- );
-}
-
-function wp_syntax_after_filter($content)
-{
- global $wp_syntax_token;
-
- $content = preg_replace_callback(
- "/<p>\s*".$wp_syntax_token."(\d{3})\s*<\/p>/si",
- "wp_syntax_highlight",
- $content
- );
-
- return $content;
-}
-
-$wp_syntax_token = md5(uniqid(rand()));
-$wp_syntax_matches = array();
-
-// Add styling
-add_action('wp_head', 'wp_syntax_head');
-
-// We want to run before other filters; hence, a priority of 0 was chosen.
-// The lower the number, the higher the priority. 10 is the default and
-// several formatting filters run at or around 6.
-add_filter('the_content', 'wp_syntax_before_filter', 0);
-add_filter('the_excerpt', 'wp_syntax_before_filter', 0);
-add_filter('comment_text', 'wp_syntax_before_filter', 0);
-
-// We want to run after other filters; hence, a priority of 99.
-add_filter('the_content', 'wp_syntax_after_filter', 99);
-add_filter('the_excerpt', 'wp_syntax_after_filter', 99);
-add_filter('comment_text', 'wp_syntax_after_filter', 99);
-
-?>
+ /**
+ * The main function responsible for returning the WP_Syntax instance
+ * to functions everywhere.
+ *
+ * Use this function like you would a global variable, except without needing
+ * to declare the global.
+ *
+ * Example: <?php $wp_syntex = WP_Syntax(); ?>
+ *
+ * @access public
+ * @since 1.0
+ * @return mixed (object)
+ */
+ function WP_Syntax() {
+ return WP_Syntax::getInstance();
+ }
+
+ /**
+ * Start the plugin.
+ */
+ add_action( 'plugins_loaded', 'WP_Syntax' );
+
+} \ No newline at end of file