public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/blogs-gentoo:master commit in: plugins/jetpack/modules/publicize/assets/rtl/, ...
@ 2013-03-10 11:07 Theo Chatzimichos
  0 siblings, 0 replies; 2+ messages in thread
From: Theo Chatzimichos @ 2013-03-10 11:07 UTC (permalink / raw
  To: gentoo-commits

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 4174261 bytes --]

commit:     7aea9fc04bd42e2ac02a1925d3a02a76d391c3e7
Author:     Theo Chatzimichos <tampakrap <AT> gentoo <DOT> org>
AuthorDate: Sun Mar 10 11:10:26 2013 +0000
Commit:     Theo Chatzimichos <tampakrap <AT> gentoo <DOT> org>
CommitDate: Sun Mar 10 11:10:26 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/blogs-gentoo.git;a=commit;h=7aea9fc0

update plugins

---
 plugins/akismet/.htaccess                          |    6 +
 plugins/akismet/admin.php                          |   27 +-
 plugins/akismet/akismet.js                         |   12 +-
 plugins/akismet/akismet.php                        |   39 +-
 plugins/akismet/readme.txt                         |   13 +-
 plugins/jetpack/_inc/gallery-settings.js           |   19 +
 .../jetpack/_inc/images/module-icons-sprite-2x.png |  Bin 37559 -> 72735 bytes
 .../jetpack/_inc/images/module-icons-sprite.png    |  Bin 11465 -> 31542 bytes
 plugins/jetpack/_inc/images/publicize.png          |  Bin 0 -> 113219 bytes
 .../jetpack/_inc/images/screenshots/carousel.png   |  Bin 0 -> 361672 bytes
 .../jetpack/_inc/images/screenshots/custom-css.png |  Bin 0 -> 43048 bytes
 plugins/jetpack/_inc/images/screenshots/likes.png  |  Bin 0 -> 48953 bytes
 .../screenshots/mobile-push-notifications.jpg      |  Bin 0 -> 29830 bytes
 .../_inc/images/screenshots/mobile-theme.png       |  Bin 0 -> 37559 bytes
 plugins/jetpack/_inc/images/screenshots/notes.png  |  Bin 0 -> 27450 bytes
 .../_inc/images/screenshots/post-by-email.png      |  Bin 0 -> 28349 bytes
 .../jetpack/_inc/images/screenshots/publicize.png  |  Bin 0 -> 113219 bytes
 .../_inc/images/screenshots/tiled-gallery.png      |  Bin 0 -> 192182 bytes
 plugins/jetpack/_inc/jetpack.css                   |  247 +-
 plugins/jetpack/_inc/jetpack.js                    |   58 +-
 plugins/jetpack/_inc/jquery.inview.js              |  143 +
 plugins/jetpack/_inc/jquery.jetpack-resize.js      |  275 +
 plugins/jetpack/_inc/jquery.spin.js                |   86 +
 plugins/jetpack/_inc/postmessage.js                |  438 +
 plugins/jetpack/_inc/spin.js                       |  301 +
 plugins/jetpack/class.jetpack-ixr-client.php       |    2 -
 plugins/jetpack/class.jetpack-post-images.php      |  440 +
 plugins/jetpack/class.jetpack-signature.php        |   24 +-
 plugins/jetpack/class.jetpack-user-agent.php       | 1331 +++
 plugins/jetpack/class.jetpack-xmlrpc-server.php    |  225 +-
 plugins/jetpack/class.json-api-endpoints.php       | 3912 ++++++++
 plugins/jetpack/class.json-api.php                 |  443 +
 plugins/jetpack/class.photon.php                   |  554 ++
 plugins/jetpack/functions.compat.php               |   15 +
 plugins/jetpack/functions.gallery.php              |   50 +
 plugins/jetpack/functions.opengraph.php            |  158 +
 plugins/jetpack/functions.photon.php               |  160 +
 plugins/jetpack/jetpack.php                        | 2107 ++++-
 plugins/jetpack/languages/jetpack-ar.mo            |  Bin 0 -> 14004 bytes
 plugins/jetpack/languages/jetpack-az.mo            |  Bin 2398 -> 2886 bytes
 plugins/jetpack/languages/jetpack-bs_BA.mo         |  Bin 59865 -> 76528 bytes
 plugins/jetpack/languages/jetpack-ca.mo            |  Bin 52959 -> 76602 bytes
 plugins/jetpack/languages/jetpack-cs_CZ.mo         |  Bin 5260 -> 8242 bytes
 plugins/jetpack/languages/jetpack-da_DK.mo         |  Bin 48806 -> 44830 bytes
 plugins/jetpack/languages/jetpack-de_DE.mo         |  Bin 43096 -> 117625 bytes
 plugins/jetpack/languages/jetpack-el.mo            |  Bin 0 -> 8337 bytes
 plugins/jetpack/languages/jetpack-es_ES.mo         |  Bin 45191 -> 49121 bytes
 plugins/jetpack/languages/jetpack-fa_IR.mo         |  Bin 32814 -> 47862 bytes
 plugins/jetpack/languages/jetpack-fi.mo            |  Bin 21934 -> 27526 bytes
 plugins/jetpack/languages/jetpack-fr_FR.mo         |  Bin 69552 -> 113684 bytes
 plugins/jetpack/languages/jetpack-gl_ES.mo         |  Bin 30784 -> 33955 bytes
 plugins/jetpack/languages/jetpack-he_IL.mo         |  Bin 62301 -> 75590 bytes
 plugins/jetpack/languages/jetpack-hr.mo            |  Bin 31130 -> 35895 bytes
 plugins/jetpack/languages/jetpack-hu_HU.mo         |  Bin 30043 -> 77710 bytes
 plugins/jetpack/languages/jetpack-id_ID.mo         |  Bin 49894 -> 52347 bytes
 plugins/jetpack/languages/jetpack-it_IT.mo         |  Bin 33628 -> 50000 bytes
 plugins/jetpack/languages/jetpack-ja.mo            |  Bin 67264 -> 116549 bytes
 plugins/jetpack/languages/jetpack-ko_KR.mo         |  Bin 0 -> 110462 bytes
 plugins/jetpack/languages/jetpack-lt_LT.mo         |  Bin 0 -> 12440 bytes
 plugins/jetpack/languages/jetpack-mk_MK.mo         |  Bin 22392 -> 23594 bytes
 plugins/jetpack/languages/jetpack-my_MM.mo         |  Bin 5741 -> 11071 bytes
 plugins/jetpack/languages/jetpack-nb_NO.mo         |  Bin 64081 -> 88203 bytes
 plugins/jetpack/languages/jetpack-nl_NL.mo         |  Bin 32682 -> 38043 bytes
 plugins/jetpack/languages/jetpack-nn_NO.mo         |  Bin 9040 -> 14701 bytes
 plugins/jetpack/languages/jetpack-pl_PL.mo         |  Bin 5948 -> 11997 bytes
 plugins/jetpack/languages/jetpack-pt_BR.mo         |  Bin 62629 -> 107473 bytes
 plugins/jetpack/languages/jetpack-pt_PT.mo         |  Bin 40066 -> 46165 bytes
 plugins/jetpack/languages/jetpack-ro_RO.mo         |  Bin 6675 -> 10652 bytes
 plugins/jetpack/languages/jetpack-ru_RU.mo         |  Bin 41905 -> 49300 bytes
 plugins/jetpack/languages/jetpack-sa_IN.mo         |  Bin 1008 -> 1006 bytes
 plugins/jetpack/languages/jetpack-sk_SK.mo         |  Bin 7567 -> 10517 bytes
 plugins/jetpack/languages/jetpack-sq.mo            |  Bin 56036 -> 112583 bytes
 plugins/jetpack/languages/jetpack-sr_RS.mo         |  Bin 36803 -> 44079 bytes
 plugins/jetpack/languages/jetpack-sv_SE.mo         |  Bin 19356 -> 24534 bytes
 plugins/jetpack/languages/jetpack-th.mo            |  Bin 0 -> 18421 bytes
 plugins/jetpack/languages/jetpack-tr_TR.mo         |  Bin 23475 -> 35311 bytes
 plugins/jetpack/languages/jetpack-zh_CN.mo         |  Bin 0 -> 7637 bytes
 plugins/jetpack/languages/jetpack-zh_TW.mo         |  Bin 0 -> 93742 bytes
 plugins/jetpack/locales.php                        |  139 +-
 plugins/jetpack/modules/after-the-deadline.php     |    2 +-
 .../modules/after-the-deadline/config-options.php  |    4 +-
 .../modules/carousel/jetpack-carousel-ie8fix.css   |    8 +
 .../jetpack/modules/carousel/jetpack-carousel.css  |   89 +-
 .../jetpack/modules/carousel/jetpack-carousel.js   |  344 +-
 .../jetpack/modules/carousel/jetpack-carousel.php  |   85 +-
 .../jetpack-carousel-rtl.css}                      |  213 +-
 plugins/jetpack/modules/comments.php               |    9 +
 plugins/jetpack/modules/comments/base.php          |   47 +-
 plugins/jetpack/modules/comments/comments.php      |  134 +
 plugins/jetpack/modules/contact-form/admin.php     |  245 +-
 .../jetpack/modules/contact-form/css/grunion.css   |    7 +-
 .../modules/contact-form/grunion-contact-form.php  | 1866 +++--
 .../contact-form/images/grunion-menu-2x.png        |  Bin 541 -> 53439 bytes
 .../contact-form/images/grunion-menu-hover-2x.png  |  Bin 697 -> 51427 bytes
 .../images/grunion-remove-field-2x.png             |  Bin 201 -> 47832 bytes
 .../images/grunion-remove-field-hover-2x.png       |  Bin 207 -> 47745 bytes
 plugins/jetpack/modules/contact-form/js/grunion.js |   60 +-
 plugins/jetpack/modules/custom-css.php             |   26 +
 .../modules/custom-css/csstidy/class.csstidy.php   | 1241 +++
 .../custom-css/csstidy/class.csstidy_ctype.php     |   46 +
 .../custom-css/csstidy/class.csstidy_optimise.php  |  936 ++
 .../custom-css/csstidy/class.csstidy_print.php     |  408 +
 .../modules/custom-css/csstidy/cssparse.css        |  118 +
 .../modules/custom-css/csstidy/cssparsed.css       |   29 +
 .../modules/custom-css/csstidy/data-wp.inc.php     |   75 +
 .../modules/custom-css/csstidy/data.inc.php        |  661 ++
 .../modules/custom-css/csstidy/lang.inc.php        |  311 +
 .../custom-css/csstidy/wordpress-standard.tpl      |   10 +
 plugins/jetpack/modules/custom-css/custom-css.php  | 1468 +++
 .../modules/custom-css/custom-css/blank.css        |    1 +
 .../modules/custom-css/custom-css/js/ace/ace.js    |   11 +
 .../custom-css/custom-css/js/ace/mode-css.js       |    1 +
 .../custom-css/custom-css/js/ace/readme.txt        |    1 +
 .../custom-css/custom-css/js/ace/theme-textmate.js |    1 +
 .../custom-css/custom-css/js/ace/worker-css.js     |    1 +
 .../custom-css/custom-css/js/safecss-ace.js        |   69 +
 .../custom-css/custom-css/preprocessors.php        |   57 +
 .../custom-css/preprocessors/lessc.inc.php         | 3359 +++++++
 .../custom-css/preprocessors/scss.inc.php          | 3759 ++++++++
 plugins/jetpack/modules/enhanced-distribution.php  |   23 +-
 .../modules/featured-content/featured-content.php  |  454 +
 plugins/jetpack/modules/gravatar-hovercards.php    |   17 +-
 plugins/jetpack/modules/holiday-snow.php           |   72 +
 plugins/jetpack/modules/holiday-snow/snowstorm.js  |  539 ++
 plugins/jetpack/modules/infinite-scroll.php        |  196 +
 .../jetpack/modules/infinite-scroll/infinity.css   |  137 +
 .../jetpack/modules/infinite-scroll/infinity.js    |  490 +
 .../jetpack/modules/infinite-scroll/infinity.php   |  945 ++
 .../infinite-scroll/themes/twentyeleven.css        |   45 +
 .../infinite-scroll/themes/twentyeleven.php        |   27 +
 .../modules/infinite-scroll/themes/twentyten.css   |   25 +
 .../modules/infinite-scroll/themes/twentyten.php   |   48 +
 .../infinite-scroll/themes/twentytwelve.css        |   33 +
 .../infinite-scroll/themes/twentytwelve.php        |   46 +
 plugins/jetpack/modules/json-api.php               |   19 +
 plugins/jetpack/modules/latex.php                  |    6 +-
 plugins/jetpack/modules/likes.php                  |  970 ++
 plugins/jetpack/modules/likes/style.css            |  189 +
 plugins/jetpack/modules/minileven.php              |  108 +
 .../modules/minileven/images/wp-app-devices.png    |  Bin 0 -> 1865 bytes
 plugins/jetpack/modules/minileven/minileven.php    |  313 +
 .../minileven/theme/pub/minileven/comments.php     |   52 +
 .../theme/pub/minileven/content-gallery.php        |   78 +
 .../minileven/theme/pub/minileven/content.php      |   60 +
 .../minileven/theme/pub/minileven/footer.php       |   36 +
 .../minileven/theme/pub/minileven/functions.php    |  152 +
 .../minileven/theme/pub/minileven/header.php       |   49 +
 .../minileven/theme/pub/minileven/image.php        |   98 +
 .../theme/pub/minileven/inc/custom-header.php      |  101 +
 .../theme/pub/minileven/inc/template-tags.php      |   99 +
 .../minileven/theme/pub/minileven/inc/tweaks.php   |   94 +
 .../minileven/theme/pub/minileven/index.php        |   73 +
 .../minileven/theme/pub/minileven/js/small-menu.js |   41 +
 .../modules/minileven/theme/pub/minileven/page.php |   42 +
 .../modules/minileven/theme/pub/minileven/rtl.css  |  582 ++
 .../minileven/theme/pub/minileven/screenshot.png   |  Bin 0 -> 59059 bytes
 .../minileven/theme/pub/minileven/searchform.php   |   12 +
 .../minileven/theme/pub/minileven/sidebar.php      |   12 +
 .../minileven/theme/pub/minileven/style.css        | 1437 +++
 plugins/jetpack/modules/mobile-push.php            |   11 +
 plugins/jetpack/modules/module-extras.php          |   58 +
 plugins/jetpack/modules/module-info.php            |  347 +-
 plugins/jetpack/modules/notes.php                  |  195 +
 plugins/jetpack/modules/photon.php                 |    9 +
 plugins/jetpack/modules/photon/photon.js           |   42 +
 plugins/jetpack/modules/post-by-email.php          |  240 +
 .../modules/post-by-email/post-by-email.css        |    6 +
 .../jetpack/modules/post-by-email/post-by-email.js |  129 +
 plugins/jetpack/modules/publicize.php              |  283 +
 .../jetpack/modules/publicize/assets/connected.gif |  Bin 0 -> 1681 bytes
 .../modules/publicize/assets/facebook-logo.png     |  Bin 0 -> 37624 bytes
 .../modules/publicize/assets/linkedin-logo.png     |  Bin 0 -> 6882 bytes
 .../jetpack/modules/publicize/assets/publicize.css |  175 +
 .../jetpack/modules/publicize/assets/publicize.js  |  108 +
 .../modules/publicize/assets/rtl/publicize-rtl.css |  177 +
 .../jetpack/modules/publicize/assets/spinner.gif   |  Bin 0 -> 457 bytes
 .../modules/publicize/assets/tumblr-logo.png       |  Bin 0 -> 9001 bytes
 .../modules/publicize/assets/twitter-logo.png      |  Bin 0 -> 4623 bytes
 .../modules/publicize/assets/yahoo-logo.png        |  Bin 0 -> 9675 bytes
 .../modules/publicize/publicize-jetpack.php        |  578 ++
 plugins/jetpack/modules/publicize/publicize.php    |  328 +
 plugins/jetpack/modules/publicize/ui.php           |  545 ++
 plugins/jetpack/modules/sharedaddy.php             |    2 +-
 .../jetpack/modules/sharedaddy/admin-sharing.css   |  140 +-
 .../modules/sharedaddy/images/icon-facebook-2x.png |  Bin 0 -> 671 bytes
 .../modules/sharedaddy/images/icon-facebook.png    |  Bin 0 -> 887 bytes
 .../modules/sharedaddy/images/icon-twitter-2x.png  |  Bin 0 -> 1451 bytes
 .../modules/sharedaddy/images/icon-twitter.png     |  Bin 0 -> 523 bytes
 .../sharedaddy/images/icon-wordpress-2x.png        |  Bin 0 -> 657 bytes
 .../modules/sharedaddy/images/icon-wordpress.png   |  Bin 0 -> 775 bytes
 plugins/jetpack/modules/sharedaddy/sharedaddy.php  |   57 +-
 .../jetpack/modules/sharedaddy/sharing-service.php |  217 +-
 .../jetpack/modules/sharedaddy/sharing-sources.php |  566 +-
 plugins/jetpack/modules/sharedaddy/sharing.css     |  142 +-
 plugins/jetpack/modules/sharedaddy/sharing.js      |  123 +-
 plugins/jetpack/modules/sharedaddy/sharing.php     |  128 +-
 plugins/jetpack/modules/shortcodes/audio.php       |   45 +-
 .../shortcodes/css/rtl/slideshow-shortcode-rtl.css |  131 +
 .../modules/shortcodes/css/slideshow-shortcode.css |  129 +
 plugins/jetpack/modules/shortcodes/googlemaps.php  |    2 +-
 .../shortcodes/img/slideshow-controls-2x.png       |  Bin 0 -> 1944 bytes
 .../modules/shortcodes/img/slideshow-controls.png  |  Bin 0 -> 1009 bytes
 .../modules/shortcodes/img/slideshow-loader.gif    |  Bin 0 -> 13545 bytes
 .../modules/shortcodes/js/audio-shortcode.js       |  154 +
 .../jetpack/modules/shortcodes/js/jquery.cycle.js  | 1551 ++++
 .../modules/shortcodes/js/slideshow-shortcode.js   |  187 +
 plugins/jetpack/modules/shortcodes/polldaddy.php   |    6 +-
 plugins/jetpack/modules/shortcodes/slideshow.php   |  208 +
 plugins/jetpack/modules/shortcodes/soundcloud.php  |  246 +-
 plugins/jetpack/modules/shortcodes/ted.php         |   68 +
 plugins/jetpack/modules/shortcodes/videopress.php  |   51 +-
 plugins/jetpack/modules/shortcodes/vimeo.php       |   20 +-
 plugins/jetpack/modules/shortcodes/youtube.php     |   10 +-
 plugins/jetpack/modules/stats.php                  |  172 +-
 plugins/jetpack/modules/subscriptions.php          |  289 +-
 plugins/jetpack/modules/tiled-gallery.php          |   25 +
 .../math/class-constrained-array-rounding.php      |   75 +
 .../modules/tiled-gallery/tiled-gallery.php        |  588 ++
 .../tiled-gallery/rtl/tiled-gallery-rtl.css        |   88 +
 .../tiled-gallery/tiled-gallery/tiled-gallery.css  |   85 +
 .../tiled-gallery/tiled-gallery/tiled-gallery.js   |  150 +
 plugins/jetpack/modules/widgets.php                |   21 +-
 .../jetpack/modules/widgets/facebook-likebox.php   |   57 +-
 .../jetpack/modules/widgets/gravatar-profile.css   |   15 +-
 .../jetpack/modules/widgets/gravatar-profile.php   |  128 +-
 plugins/jetpack/modules/widgets/image-widget.php   |    2 +-
 plugins/jetpack/modules/widgets/readmill.php       |  138 +
 plugins/jetpack/modules/widgets/top-posts.php      |  295 +
 plugins/jetpack/modules/widgets/twitter.php        |  407 +
 .../modules/widgets/widget-grid-and-list.css       |  110 +
 plugins/jetpack/modules/widgets/widgets.css        |   13 +
 plugins/jetpack/readme.txt                         |  251 +-
 plugins/openid/admin_panels.php                    |    3 -
 plugins/openid/common.php                          |    8 +-
 plugins/openid/consumer.php                        |    6 -
 plugins/openid/lib/Auth/OpenID.php                 |  563 ++
 plugins/openid/lib/Auth/OpenID/AX.php              | 1022 +++
 plugins/openid/lib/Auth/OpenID/Association.php     |  610 ++
 plugins/openid/lib/Auth/OpenID/BigMath.php         |  451 +
 plugins/openid/lib/Auth/OpenID/Consumer.php        | 2236 +++++
 plugins/openid/lib/Auth/OpenID/CryptUtil.php       |  122 +
 .../openid/lib/Auth/OpenID/DatabaseConnection.php  |  130 +
 plugins/openid/lib/Auth/OpenID/DiffieHellman.php   |  113 +
 plugins/openid/lib/Auth/OpenID/Discover.php        |  606 ++
 plugins/openid/lib/Auth/OpenID/DumbStore.php       |   99 +
 plugins/openid/lib/Auth/OpenID/Extension.php       |   61 +
 plugins/openid/lib/Auth/OpenID/FileStore.php       |  618 ++
 plugins/openid/lib/Auth/OpenID/HMAC.php            |  105 +
 plugins/openid/lib/Auth/OpenID/Interface.php       |  196 +
 plugins/openid/lib/Auth/OpenID/KVForm.php          |  111 +
 plugins/openid/lib/Auth/OpenID/MDB2Store.php       |  413 +
 plugins/openid/lib/Auth/OpenID/MemcachedStore.php  |  207 +
 plugins/openid/lib/Auth/OpenID/Message.php         |  920 ++
 plugins/openid/lib/Auth/OpenID/MySQLStore.php      |   77 +
 plugins/openid/lib/Auth/OpenID/Nonce.php           |  108 +
 plugins/openid/lib/Auth/OpenID/PAPE.php            |  300 +
 plugins/openid/lib/Auth/OpenID/Parse.php           |  381 +
 plugins/openid/lib/Auth/OpenID/PostgreSQLStore.php |  112 +
 plugins/openid/lib/Auth/OpenID/SQLStore.php        |  557 ++
 plugins/openid/lib/Auth/OpenID/SQLiteStore.php     |   70 +
 plugins/openid/lib/Auth/OpenID/SReg.php            |  521 ++
 plugins/openid/lib/Auth/OpenID/Server.php          | 1765 ++++
 plugins/openid/lib/Auth/OpenID/ServerRequest.php   |   36 +
 plugins/openid/lib/Auth/OpenID/TrustRoot.php       |  461 +
 plugins/openid/lib/Auth/OpenID/URINorm.php         |  249 +
 plugins/openid/lib/Auth/Yadis/HTTPFetcher.php      |  174 +
 plugins/openid/lib/Auth/Yadis/Manager.php          |  523 ++
 plugins/openid/lib/Auth/Yadis/Misc.php             |   58 +
 .../openid/lib/Auth/Yadis/ParanoidHTTPFetcher.php  |  273 +
 plugins/openid/lib/Auth/Yadis/ParseHTML.php        |  258 +
 plugins/openid/lib/Auth/Yadis/PlainHTTPFetcher.php |  248 +
 plugins/openid/lib/Auth/Yadis/XML.php              |  352 +
 plugins/openid/lib/Auth/Yadis/XRDS.php             |  478 +
 plugins/openid/lib/Auth/Yadis/XRI.php              |  234 +
 plugins/openid/lib/Auth/Yadis/XRIRes.php           |   72 +
 plugins/openid/lib/Auth/Yadis/Yadis.php            |  382 +
 plugins/openid/openid.php                          |   25 +-
 plugins/openid/readme.txt                          |    9 +-
 plugins/openid/server.php                          |   21 +-
 plugins/wp-syntax/README.txt                       |   89 +-
 plugins/wp-syntax/css/wp-syntax.css                |   98 +
 plugins/wp-syntax/geshi/geshi.php                  | 9534 ++++++++++----------
 plugins/wp-syntax/geshi/geshi/4cs.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/6502acme.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/6502kickass.php      |    2 +-
 plugins/wp-syntax/geshi/geshi/6502tasm.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/68000devpac.php      |    2 +-
 plugins/wp-syntax/geshi/geshi/abap.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/actionscript.php     |    2 +-
 plugins/wp-syntax/geshi/geshi/actionscript3.php    |    6 +-
 plugins/wp-syntax/geshi/geshi/ada.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/algol68.php          |  287 +-
 plugins/wp-syntax/geshi/geshi/apache.php           |    5 +-
 plugins/wp-syntax/geshi/geshi/applescript.php      |    2 +-
 plugins/wp-syntax/geshi/geshi/apt_sources.php      |   12 +-
 plugins/wp-syntax/geshi/geshi/arm.php              | 3318 +++++++
 plugins/wp-syntax/geshi/geshi/asm.php              |  536 +-
 plugins/wp-syntax/geshi/geshi/asp.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/asymptote.php        |  194 +
 plugins/wp-syntax/geshi/geshi/autoconf.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/autohotkey.php       |    2 +-
 plugins/wp-syntax/geshi/geshi/autoit.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/avisynth.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/awk.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/bascomavr.php        |  185 +
 plugins/wp-syntax/geshi/geshi/bash.php             |  141 +-
 plugins/wp-syntax/geshi/geshi/basic4gl.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/bf.php               |   15 +-
 plugins/wp-syntax/geshi/geshi/bibtex.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/blitzbasic.php       |    4 +-
 plugins/wp-syntax/geshi/geshi/bnf.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/boo.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/c.php                |   85 +-
 plugins/wp-syntax/geshi/geshi/c_loadrunner.php     |  323 +
 plugins/wp-syntax/geshi/geshi/c_mac.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/caddcl.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/cadlisp.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/cfdg.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/cfm.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/chaiscript.php       |    4 +-
 plugins/wp-syntax/geshi/geshi/cil.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/clojure.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/cmake.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/cobol.php            |    2 +-
 .../geshi/geshi/{idl.php => coffeescript.php}      |   99 +-
 plugins/wp-syntax/geshi/geshi/cpp-qt.php           |    8 +-
 plugins/wp-syntax/geshi/geshi/cpp.php              |    4 +-
 plugins/wp-syntax/geshi/geshi/csharp.php           |   19 +-
 plugins/wp-syntax/geshi/geshi/css.php              |   22 +-
 plugins/wp-syntax/geshi/geshi/cuesheet.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/d.php                |   68 +-
 plugins/wp-syntax/geshi/geshi/dcl.php              |  192 +
 .../wp-syntax/geshi/geshi/{m68k.php => dcpu16.php} |   84 +-
 plugins/wp-syntax/geshi/geshi/dcs.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/delphi.php           |   46 +-
 plugins/wp-syntax/geshi/geshi/diff.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/div.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/dos.php              |    8 +-
 plugins/wp-syntax/geshi/geshi/dot.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/e.php                |    2 +-
 plugins/wp-syntax/geshi/geshi/ecmascript.php       |    2 +-
 plugins/wp-syntax/geshi/geshi/eiffel.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/email.php            |   26 +-
 plugins/wp-syntax/geshi/geshi/epc.php              |  154 +
 plugins/wp-syntax/geshi/geshi/erlang.php           |   10 +-
 plugins/wp-syntax/geshi/geshi/euphoria.php         |  140 +
 plugins/wp-syntax/geshi/geshi/f1.php               |    2 +-
 plugins/wp-syntax/geshi/geshi/falcon.php           |  218 +
 plugins/wp-syntax/geshi/geshi/fo.php               |    2 +-
 plugins/wp-syntax/geshi/geshi/fortran.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/freebasic.php        |    2 +-
 plugins/wp-syntax/geshi/geshi/freeswitch.php       |  168 +
 plugins/wp-syntax/geshi/geshi/fsharp.php           |    8 +-
 plugins/wp-syntax/geshi/geshi/gambas.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/gdb.php              |   63 +-
 plugins/wp-syntax/geshi/geshi/genero.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/genie.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/gettext.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/glsl.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/gml.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/gnuplot.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/go.php               |   47 +-
 plugins/wp-syntax/geshi/geshi/groovy.php           |   18 +-
 plugins/wp-syntax/geshi/geshi/gwbasic.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/haskell.php          |    8 +-
 plugins/wp-syntax/geshi/geshi/haxe.php             |  161 +
 plugins/wp-syntax/geshi/geshi/hicest.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/hq9plus.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/html4strict.php      |   29 +-
 .../geshi/geshi/{html4strict.php => html5.php}     |   73 +-
 plugins/wp-syntax/geshi/geshi/icon.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/idl.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/ini.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/inno.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/intercal.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/io.php               |    2 +-
 plugins/wp-syntax/geshi/geshi/j.php                |   73 +-
 plugins/wp-syntax/geshi/geshi/java.php             |    4 +-
 plugins/wp-syntax/geshi/geshi/java5.php            |  328 +-
 plugins/wp-syntax/geshi/geshi/javascript.php       |   70 +-
 plugins/wp-syntax/geshi/geshi/jquery.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/kixtart.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/klonec.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/klonecpp.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/latex.php            |    8 +-
 plugins/wp-syntax/geshi/geshi/lb.php               |   16 +-
 .../geshi/geshi/{properties.php => ldif.php}       |   53 +-
 plugins/wp-syntax/geshi/geshi/lisp.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/llvm.php             |  385 +
 plugins/wp-syntax/geshi/geshi/locobasic.php        |    2 +-
 plugins/wp-syntax/geshi/geshi/logtalk.php          |   35 +-
 plugins/wp-syntax/geshi/geshi/lolcode.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/lotusformulas.php    |    2 +-
 plugins/wp-syntax/geshi/geshi/lotusscript.php      |    2 +-
 plugins/wp-syntax/geshi/geshi/lscript.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/lsl2.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/lua.php              |   62 +-
 plugins/wp-syntax/geshi/geshi/m68k.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/magiksf.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/make.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/mapbasic.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/matlab.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/mirc.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/mmix.php             |   66 +-
 plugins/wp-syntax/geshi/geshi/modula2.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/modula3.php          |    4 +-
 plugins/wp-syntax/geshi/geshi/mpasm.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/mxml.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/mysql.php            |   34 +-
 plugins/wp-syntax/geshi/geshi/nagios.php           |  225 +
 plugins/wp-syntax/geshi/geshi/netrexx.php          |  163 +
 plugins/wp-syntax/geshi/geshi/newlisp.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/nsis.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/oberon2.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/objc.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/objeck.php           |   10 +-
 plugins/wp-syntax/geshi/geshi/ocaml-brief.php      |    2 +-
 plugins/wp-syntax/geshi/geshi/ocaml.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/octave.php           |  515 ++
 plugins/wp-syntax/geshi/geshi/oobas.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/oorexx.php           |  171 +
 plugins/wp-syntax/geshi/geshi/oracle11.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/oracle8.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/oxygene.php          |    6 +-
 plugins/wp-syntax/geshi/geshi/oz.php               |    2 +-
 .../geshi/geshi/{ada.php => parasail.php}          |   54 +-
 plugins/wp-syntax/geshi/geshi/parigp.php           |  277 +
 plugins/wp-syntax/geshi/geshi/pascal.php           |   53 +-
 plugins/wp-syntax/geshi/geshi/pcre.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/per.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/perl.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/perl6.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/pf.php               |    2 +-
 plugins/wp-syntax/geshi/geshi/php-brief.php        |    4 +-
 plugins/wp-syntax/geshi/geshi/php.php              |   21 +-
 plugins/wp-syntax/geshi/geshi/pic16.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/pike.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/pixelbender.php      |    2 +-
 plugins/wp-syntax/geshi/geshi/pli.php              |  200 +
 plugins/wp-syntax/geshi/geshi/plsql.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/postgresql.php       |    2 +-
 plugins/wp-syntax/geshi/geshi/povray.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/powerbuilder.php     |    2 +-
 plugins/wp-syntax/geshi/geshi/powershell.php       |    2 +-
 plugins/wp-syntax/geshi/geshi/proftpd.php          |  374 +
 plugins/wp-syntax/geshi/geshi/progress.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/prolog.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/properties.php       |    2 +-
 plugins/wp-syntax/geshi/geshi/providex.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/purebasic.php        |    2 +-
 plugins/wp-syntax/geshi/geshi/pycon.php            |   64 +
 .../geshi/geshi/{python.php => pys60.php}          |  164 +-
 plugins/wp-syntax/geshi/geshi/python.php           |   17 +-
 plugins/wp-syntax/geshi/geshi/q.php                |    2 +-
 plugins/wp-syntax/geshi/geshi/qbasic.php           |    6 +-
 plugins/wp-syntax/geshi/geshi/rails.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/rebol.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/reg.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/rexx.php             |  162 +
 plugins/wp-syntax/geshi/geshi/robots.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/rpmspec.php          |    2 +-
 plugins/wp-syntax/geshi/geshi/rsplus.php           |   20 +-
 plugins/wp-syntax/geshi/geshi/ruby.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/sas.php              |    6 +-
 plugins/wp-syntax/geshi/geshi/scala.php            |   26 +-
 plugins/wp-syntax/geshi/geshi/scheme.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/scilab.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/sdlbasic.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/smalltalk.php        |    2 +-
 plugins/wp-syntax/geshi/geshi/smarty.php           |    2 +-
 .../wp-syntax/geshi/geshi/{ada.php => spark.php}   |   27 +-
 plugins/wp-syntax/geshi/geshi/sparql.php           |  155 +
 plugins/wp-syntax/geshi/geshi/sql.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/stonescript.php      |  307 +
 plugins/wp-syntax/geshi/geshi/systemverilog.php    |    8 +-
 plugins/wp-syntax/geshi/geshi/tcl.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/teraterm.php         |  147 +-
 plugins/wp-syntax/geshi/geshi/text.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/thinbasic.php        |    2 +-
 plugins/wp-syntax/geshi/geshi/tsql.php             |    6 +-
 plugins/wp-syntax/geshi/geshi/typoscript.php       |   20 +-
 plugins/wp-syntax/geshi/geshi/unicon.php           |    2 +-
 plugins/wp-syntax/geshi/geshi/{c.php => upc.php}   |  122 +-
 plugins/wp-syntax/geshi/geshi/urbi.php             |  200 +
 plugins/wp-syntax/geshi/geshi/uscript.php          |  299 +
 plugins/wp-syntax/geshi/geshi/vala.php             |    2 +-
 plugins/wp-syntax/geshi/geshi/vb.php               |    2 +-
 plugins/wp-syntax/geshi/geshi/vbnet.php            |  127 +-
 .../wp-syntax/geshi/geshi/{pike.php => vedit.php}  |   42 +-
 plugins/wp-syntax/geshi/geshi/verilog.php          |    4 +-
 plugins/wp-syntax/geshi/geshi/vhdl.php             |  105 +-
 plugins/wp-syntax/geshi/geshi/vim.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/visualfoxpro.php     |    2 +-
 plugins/wp-syntax/geshi/geshi/visualprolog.php     |    2 +-
 plugins/wp-syntax/geshi/geshi/whitespace.php       |    2 +-
 plugins/wp-syntax/geshi/geshi/whois.php            |    2 +-
 plugins/wp-syntax/geshi/geshi/winbatch.php         |    2 +-
 plugins/wp-syntax/geshi/geshi/xbasic.php           |    3 +-
 plugins/wp-syntax/geshi/geshi/xml.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/xorg_conf.php        |    2 +-
 plugins/wp-syntax/geshi/geshi/xpp.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/yaml.php             |  150 +
 plugins/wp-syntax/geshi/geshi/z80.php              |    2 +-
 plugins/wp-syntax/geshi/geshi/zxbasic.php          |    2 +-
 plugins/wp-syntax/js/wp-syntax.js                  |   34 +
 plugins/wp-syntax/wp-syntax.php                    |  563 +-
 506 files changed, 74843 insertions(+), 9242 deletions(-)

diff --git a/plugins/akismet/.htaccess b/plugins/akismet/.htaccess
new file mode 100644
index 0000000..18eed64
--- /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 aa30cde..9d7673f 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 839fe6b..8925c51 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 48fa3c3..4c3aef7 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 227fad9..4d61fe9 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 0000000..0ce38f0
--- /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 db87b2d..11f4204 100644
Binary files a/plugins/jetpack/_inc/images/module-icons-sprite-2x.png and b/plugins/jetpack/_inc/images/module-icons-sprite-2x.png differ

diff --git a/plugins/jetpack/_inc/images/module-icons-sprite.png b/plugins/jetpack/_inc/images/module-icons-sprite.png
index 44de3b9..c6979f6 100644
Binary files a/plugins/jetpack/_inc/images/module-icons-sprite.png and b/plugins/jetpack/_inc/images/module-icons-sprite.png differ

diff --git a/plugins/jetpack/_inc/images/publicize.png b/plugins/jetpack/_inc/images/publicize.png
new file mode 100644
index 0000000..428b886
Binary files /dev/null and b/plugins/jetpack/_inc/images/publicize.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/carousel.png b/plugins/jetpack/_inc/images/screenshots/carousel.png
new file mode 100644
index 0000000..5bcc94c
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/carousel.png 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 0000000..4be5cb2
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/custom-css.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/likes.png b/plugins/jetpack/_inc/images/screenshots/likes.png
new file mode 100644
index 0000000..1c7670a
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/likes.png 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 0000000..94ca6dd
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpg 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 0000000..88bad2d
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/mobile-theme.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/notes.png b/plugins/jetpack/_inc/images/screenshots/notes.png
new file mode 100644
index 0000000..4506db1
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/notes.png 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 0000000..b114088
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/post-by-email.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/publicize.png b/plugins/jetpack/_inc/images/screenshots/publicize.png
new file mode 100644
index 0000000..428b886
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/publicize.png 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 0000000..8168590
Binary files /dev/null and b/plugins/jetpack/_inc/images/screenshots/tiled-gallery.png differ

diff --git a/plugins/jetpack/_inc/jetpack.css b/plugins/jetpack/_inc/jetpack.css
index 0b6c340..b684f7c 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 69a86c1..6ef9de8 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 0000000..45f71c4
--- /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 0000000..e1adb22
--- /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 0000000..4642af1
--- /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 0000000..e8933bc
--- /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).toStri
 ng(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).toSt
 ring(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 0000000..f506cd2
--- /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 19f119c..8d6e52f 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 0000000..afdcacf
--- /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 b571884..975375a 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 0000000..3ae1bb8
--- /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 cf01db5..3aa5adb 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 0000000..6189d40
--- /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 0000000..5a322eb
--- /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 0000000..c045688
--- /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 0000000..5e776c0
--- /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 0000000..9a9e71b
--- /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 0000000..542d01f
--- /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 0000000..fc276b3
--- /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 68d7aae..80b6a3c 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 );
+
+		if ( !isset( $this->sync[$object] ) ) {
+			$this->sync[$object] = array();
+		}
 
-	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;
+		// 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 comment( $id, $fields = true ) {
-		if ( !$comment = get_comment( $id ) ) {
+	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 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';
 		}
-		if ( !$comment->comment_post_ID ) {
+
+		return $status;
+	}
+
+	function transition_comment_status_action( $new_status, $old_status, $comment ) {
+		$post = get_post( $comment->comment_post_ID );
+		if ( !$post ) {
 			return false;
 		}
-		if ( !$this->post( $comment->comment_post_ID, false ) ) {
+
+		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;
 		}
-		return $this->register( 'comment', (int) $id, $fields );
+
+		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;
+		}
+
+		$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 0000000..254be8e
Binary files /dev/null and b/plugins/jetpack/languages/jetpack-ar.mo differ

diff --git a/plugins/jetpack/languages/jetpack-az.mo b/plugins/jetpack/languages/jetpack-az.mo
index 40f5771..033f859 100644
Binary files a/plugins/jetpack/languages/jetpack-az.mo and b/plugins/jetpack/languages/jetpack-az.mo differ

diff --git a/plugins/jetpack/languages/jetpack-bs_BA.mo b/plugins/jetpack/languages/jetpack-bs_BA.mo
index e53b955..67cd446 100644
Binary files a/plugins/jetpack/languages/jetpack-bs_BA.mo and b/plugins/jetpack/languages/jetpack-bs_BA.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ca.mo b/plugins/jetpack/languages/jetpack-ca.mo
index 9a25543..2daa9e1 100644
Binary files a/plugins/jetpack/languages/jetpack-ca.mo and b/plugins/jetpack/languages/jetpack-ca.mo differ

diff --git a/plugins/jetpack/languages/jetpack-cs_CZ.mo b/plugins/jetpack/languages/jetpack-cs_CZ.mo
index 0977a8b..5e08877 100644
Binary files a/plugins/jetpack/languages/jetpack-cs_CZ.mo and b/plugins/jetpack/languages/jetpack-cs_CZ.mo differ

diff --git a/plugins/jetpack/languages/jetpack-da_DK.mo b/plugins/jetpack/languages/jetpack-da_DK.mo
index dd4a5ae..773e5b5 100644
Binary files a/plugins/jetpack/languages/jetpack-da_DK.mo and b/plugins/jetpack/languages/jetpack-da_DK.mo differ

diff --git a/plugins/jetpack/languages/jetpack-de_DE.mo b/plugins/jetpack/languages/jetpack-de_DE.mo
index c21d78b..a93c1c7 100644
Binary files a/plugins/jetpack/languages/jetpack-de_DE.mo and b/plugins/jetpack/languages/jetpack-de_DE.mo differ

diff --git a/plugins/jetpack/languages/jetpack-el.mo b/plugins/jetpack/languages/jetpack-el.mo
new file mode 100644
index 0000000..8538e68
Binary files /dev/null and b/plugins/jetpack/languages/jetpack-el.mo differ

diff --git a/plugins/jetpack/languages/jetpack-es_ES.mo b/plugins/jetpack/languages/jetpack-es_ES.mo
index 9102fc8..3cc9243 100644
Binary files a/plugins/jetpack/languages/jetpack-es_ES.mo and b/plugins/jetpack/languages/jetpack-es_ES.mo differ

diff --git a/plugins/jetpack/languages/jetpack-fa_IR.mo b/plugins/jetpack/languages/jetpack-fa_IR.mo
index 864aa9b..f34c74e 100644
Binary files a/plugins/jetpack/languages/jetpack-fa_IR.mo and b/plugins/jetpack/languages/jetpack-fa_IR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-fi.mo b/plugins/jetpack/languages/jetpack-fi.mo
index fae02a3..591c047 100644
Binary files a/plugins/jetpack/languages/jetpack-fi.mo and b/plugins/jetpack/languages/jetpack-fi.mo differ

diff --git a/plugins/jetpack/languages/jetpack-fr_FR.mo b/plugins/jetpack/languages/jetpack-fr_FR.mo
index 15385ae..165c2b9 100644
Binary files a/plugins/jetpack/languages/jetpack-fr_FR.mo and b/plugins/jetpack/languages/jetpack-fr_FR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-gl_ES.mo b/plugins/jetpack/languages/jetpack-gl_ES.mo
index 1fb3e4c..e5f4c09 100644
Binary files a/plugins/jetpack/languages/jetpack-gl_ES.mo and b/plugins/jetpack/languages/jetpack-gl_ES.mo differ

diff --git a/plugins/jetpack/languages/jetpack-he_IL.mo b/plugins/jetpack/languages/jetpack-he_IL.mo
index 3bbb699..90d820c 100644
Binary files a/plugins/jetpack/languages/jetpack-he_IL.mo and b/plugins/jetpack/languages/jetpack-he_IL.mo differ

diff --git a/plugins/jetpack/languages/jetpack-hr.mo b/plugins/jetpack/languages/jetpack-hr.mo
index 6dfab5c..8765f20 100644
Binary files a/plugins/jetpack/languages/jetpack-hr.mo and b/plugins/jetpack/languages/jetpack-hr.mo differ

diff --git a/plugins/jetpack/languages/jetpack-hu_HU.mo b/plugins/jetpack/languages/jetpack-hu_HU.mo
index f9e1b63..1171565 100644
Binary files a/plugins/jetpack/languages/jetpack-hu_HU.mo and b/plugins/jetpack/languages/jetpack-hu_HU.mo differ

diff --git a/plugins/jetpack/languages/jetpack-id_ID.mo b/plugins/jetpack/languages/jetpack-id_ID.mo
index 3e16a67..8d3427d 100644
Binary files a/plugins/jetpack/languages/jetpack-id_ID.mo and b/plugins/jetpack/languages/jetpack-id_ID.mo differ

diff --git a/plugins/jetpack/languages/jetpack-it_IT.mo b/plugins/jetpack/languages/jetpack-it_IT.mo
index 1aa7c72..7165de1 100644
Binary files a/plugins/jetpack/languages/jetpack-it_IT.mo and b/plugins/jetpack/languages/jetpack-it_IT.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ja.mo b/plugins/jetpack/languages/jetpack-ja.mo
index 82c715e..f715cc9 100644
Binary files a/plugins/jetpack/languages/jetpack-ja.mo and b/plugins/jetpack/languages/jetpack-ja.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ko_KR.mo b/plugins/jetpack/languages/jetpack-ko_KR.mo
new file mode 100644
index 0000000..3a7a529
Binary files /dev/null and b/plugins/jetpack/languages/jetpack-ko_KR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-lt_LT.mo b/plugins/jetpack/languages/jetpack-lt_LT.mo
new file mode 100644
index 0000000..55f190a
Binary files /dev/null and b/plugins/jetpack/languages/jetpack-lt_LT.mo differ

diff --git a/plugins/jetpack/languages/jetpack-mk_MK.mo b/plugins/jetpack/languages/jetpack-mk_MK.mo
index a567c77..804e8a3 100644
Binary files a/plugins/jetpack/languages/jetpack-mk_MK.mo and b/plugins/jetpack/languages/jetpack-mk_MK.mo differ

diff --git a/plugins/jetpack/languages/jetpack-my_MM.mo b/plugins/jetpack/languages/jetpack-my_MM.mo
index ba1e694..1d1604b 100644
Binary files a/plugins/jetpack/languages/jetpack-my_MM.mo and b/plugins/jetpack/languages/jetpack-my_MM.mo differ

diff --git a/plugins/jetpack/languages/jetpack-nb_NO.mo b/plugins/jetpack/languages/jetpack-nb_NO.mo
index 7c6bf66..5600cf1 100644
Binary files a/plugins/jetpack/languages/jetpack-nb_NO.mo and b/plugins/jetpack/languages/jetpack-nb_NO.mo differ

diff --git a/plugins/jetpack/languages/jetpack-nl_NL.mo b/plugins/jetpack/languages/jetpack-nl_NL.mo
index 9bd9ffb..a125514 100644
Binary files a/plugins/jetpack/languages/jetpack-nl_NL.mo and b/plugins/jetpack/languages/jetpack-nl_NL.mo differ

diff --git a/plugins/jetpack/languages/jetpack-nn_NO.mo b/plugins/jetpack/languages/jetpack-nn_NO.mo
index f5061e1..1157c95 100644
Binary files a/plugins/jetpack/languages/jetpack-nn_NO.mo and b/plugins/jetpack/languages/jetpack-nn_NO.mo differ

diff --git a/plugins/jetpack/languages/jetpack-pl_PL.mo b/plugins/jetpack/languages/jetpack-pl_PL.mo
index c8ba1dd..3a5df93 100644
Binary files a/plugins/jetpack/languages/jetpack-pl_PL.mo and b/plugins/jetpack/languages/jetpack-pl_PL.mo differ

diff --git a/plugins/jetpack/languages/jetpack-pt_BR.mo b/plugins/jetpack/languages/jetpack-pt_BR.mo
index b32d48f..da51355 100644
Binary files a/plugins/jetpack/languages/jetpack-pt_BR.mo and b/plugins/jetpack/languages/jetpack-pt_BR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-pt_PT.mo b/plugins/jetpack/languages/jetpack-pt_PT.mo
index 226b63d..62d6331 100644
Binary files a/plugins/jetpack/languages/jetpack-pt_PT.mo and b/plugins/jetpack/languages/jetpack-pt_PT.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ro_RO.mo b/plugins/jetpack/languages/jetpack-ro_RO.mo
index a310050..6a76116 100644
Binary files a/plugins/jetpack/languages/jetpack-ro_RO.mo and b/plugins/jetpack/languages/jetpack-ro_RO.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ru_RU.mo b/plugins/jetpack/languages/jetpack-ru_RU.mo
index 7c3dc2d..392de6d 100644
Binary files a/plugins/jetpack/languages/jetpack-ru_RU.mo and b/plugins/jetpack/languages/jetpack-ru_RU.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sa_IN.mo b/plugins/jetpack/languages/jetpack-sa_IN.mo
index 10f549d..f7bfee6 100644
Binary files a/plugins/jetpack/languages/jetpack-sa_IN.mo and b/plugins/jetpack/languages/jetpack-sa_IN.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sk_SK.mo b/plugins/jetpack/languages/jetpack-sk_SK.mo
index b936017..0f6a8ea 100644
Binary files a/plugins/jetpack/languages/jetpack-sk_SK.mo and b/plugins/jetpack/languages/jetpack-sk_SK.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sq.mo b/plugins/jetpack/languages/jetpack-sq.mo
index 39c037c..795f5ab 100644
Binary files a/plugins/jetpack/languages/jetpack-sq.mo and b/plugins/jetpack/languages/jetpack-sq.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sr_RS.mo b/plugins/jetpack/languages/jetpack-sr_RS.mo
index 9e7db3c..62d2959 100644
Binary files a/plugins/jetpack/languages/jetpack-sr_RS.mo and b/plugins/jetpack/languages/jetpack-sr_RS.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sv_SE.mo b/plugins/jetpack/languages/jetpack-sv_SE.mo
index ca682a7..382cbc3 100644
Binary files a/plugins/jetpack/languages/jetpack-sv_SE.mo and b/plugins/jetpack/languages/jetpack-sv_SE.mo differ

diff --git a/plugins/jetpack/languages/jetpack-th.mo b/plugins/jetpack/languages/jetpack-th.mo
new file mode 100644
index 0000000..1349918
Binary files /dev/null and b/plugins/jetpack/languages/jetpack-th.mo differ

diff --git a/plugins/jetpack/languages/jetpack-tr_TR.mo b/plugins/jetpack/languages/jetpack-tr_TR.mo
index 83a6b84..24eecce 100644
Binary files a/plugins/jetpack/languages/jetpack-tr_TR.mo and b/plugins/jetpack/languages/jetpack-tr_TR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-zh_CN.mo b/plugins/jetpack/languages/jetpack-zh_CN.mo
new file mode 100644
index 0000000..17900fb
Binary files /dev/null and b/plugins/jetpack/languages/jetpack-zh_CN.mo differ

diff --git a/plugins/jetpack/languages/jetpack-zh_TW.mo b/plugins/jetpack/languages/jetpack-zh_TW.mo
new file mode 100644
index 0000000..3866213
Binary files /dev/null and b/plugins/jetpack/languages/jetpack-zh_TW.mo differ

diff --git a/plugins/jetpack/locales.php b/plugins/jetpack/locales.php
index 41075cd..e910fbf 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 b187de3..606f648 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 31cc4da..097b062 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 0000000..9f2f6cf
--- /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 aa2b1d0..49bdad8 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 5760811..43f1d1f 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){thi
 s.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 3d48681..314dd7b 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/jetpack-carousel.css b/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css
similarity index 86%
copy from plugins/jetpack/modules/carousel/jetpack-carousel.css
copy to plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css
index aa2b1d0..0d010eb 100644
--- a/plugins/jetpack/modules/carousel/jetpack-carousel.css
+++ b/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css
@@ -1,3 +1,5 @@
+/* This file was automatically generated on Jan 29 2013 22:51:19 */
+
 * {
 	line-height:inherit; /* prevent declarations of line-height in the universal selector */
 }
@@ -8,17 +10,17 @@
 
 div.jp-carousel-fadeaway {
 	background: -moz-linear-gradient(bottom, rgba(0,0,0,0.5), rgba(0,0,0,0));
-	background: -webkit-gradient(linear, left bottom, left top, from(rgba(0,0,0,0.5)), to(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: 99999;
+	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: url(.././images/arrows.png) no-repeat center center;
 	background-size: 200px 126px;
 }
 
@@ -29,7 +31,7 @@ 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);
+		background-image: url(.././images/arrows-2x.png);
 	}
 }
 
@@ -40,7 +42,7 @@ only screen and (min-device-pixel-ratio: 1.5) {
 .jp-carousel-info {
 	position: absolute;
 	bottom: 0;
-	text-align: left !important;
+	text-align: right !important;
 	-webkit-font-smoothing: subpixel-antialiased !important;
 }
 
@@ -60,7 +62,7 @@ only screen and (min-device-pixel-ratio: 1.5) {
 	-moz-transition: 400ms ease-out;
 	-o-transition: 400ms ease-out;
 	transition: 400ms ease-out;
-	left: 25%;
+	right: 25%;
 	width: 50%;
 }
 
@@ -74,7 +76,7 @@ only screen and (min-device-pixel-ratio: 1.5) {
 	margin: 7px 0 0 0 !important;
 	padding: 10px 0 0 !important;
 	overflow: hidden;
-	text-align: left;
+	text-align: right;
 	text-shadow: none !important;
 	text-transform: none !important;
 	-webkit-font-smoothing: subpixel-antialiased;
@@ -109,12 +111,12 @@ only screen and (min-device-pixel-ratio: 1.5) {
 }
 .jp-carousel-next-button span {
 	background-position: -110px center;
-	right: 0;
+	left: 0;
 }
 
 .jp-carousel-previous-button span {
 	background-position: -10px center;
-	left:0;
+	right:0;
 }
 
 .jp-carousel-buttons {
@@ -130,7 +132,7 @@ div.jp-carousel-buttons a {
 	color: #999;
 	font: normal 11px/1.2em "Helvetica Neue", sans-serif !important;
 	letter-spacing: 0 !important;
-	padding: 5px 2px 5px 0;
+	padding: 5px 0 5px 2px;
 	text-decoration: none !important;
 	text-shadow: none !important;
 	vertical-align: baseline !important;
@@ -199,13 +201,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: right;
+	width: 90%;
 	-webkit-transition: color 200ms linear;
 	-moz-transition: color 200ms linear;
 	-o-transition: color 200ms linear;
@@ -213,16 +213,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;
+	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;
-	line-height: 22px;
-	margin: 0 0 0 0.4em;
+	width: 22px;
 	-moz-border-radius: 4px;
 	-webkit-border-radius: 4px;
 	border-radius: 4px;
@@ -245,19 +246,19 @@ 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: 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 14px 0 0 !important;
+	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-right: 8px !important;
+	padding-left: 8px !important;
 	border-radius: 2px;
 	border-radius:2px;
 	-webkit-border-radius:2px;
@@ -267,20 +268,20 @@ div.jp-carousel-buttons a.jp-carousel-like.liked {
 }
 
 div.jp-carousel-buttons a.jp-carousel-reblog.reblogged {
-	margin:0 2px 0 -12px !important;
+	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-left: 26px !important;
+	padding-right: 26px !important;
 	color: #999;
 }
 
 div.jp-carousel-buttons a.jp-carousel-commentlink {
 	background-position: 0px -116px;
-	padding-left: 19px !important;
+	padding-right: 19px !important;
 }
 
 div.jp-carousel-buttons a.jp-carousel-reblog.reblogged:hover {
@@ -294,7 +295,7 @@ div.jp-carousel-buttons a.jp-carousel-reblog:hover {
 
 div.jp-carousel-buttons a.jp-carousel-like {
 	background-position: 5px 5px;
-	padding-left: 24px !important;
+	padding-right: 24px !important;
 }
 
 div.jp-carousel-buttons a.jp-carousel-like:hover {
@@ -310,7 +311,7 @@ only screen and (min-device-pixel-ratio: 1.5) {
 	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);
+		background-image: url(.././images/carousel-sprite-2x.png?4);
 	}
 }
 
@@ -318,7 +319,7 @@ only screen and (min-device-pixel-ratio: 1.5) {
 div#carousel-reblog-box {
 	background: #222;
 	background: -moz-linear-gradient(bottom,  #222,  #333);
-	background: -webkit-gradient(linear, left bottom, left top, from(#222), to(#333));
+	background: -webkit-gradient(linear, right bottom, right top, from(#222), to(#333));
 	padding: 3px 0 0;
 	display: none;
 	margin: 5px auto 0;
@@ -339,7 +340,7 @@ div#carousel-reblog-box {
 	padding: 3px 6px;
 	width: 370px;
 	height: 48px;
-	float: left;
+	float: right;
 	margin: 6px 9px 0 9px;
 	border: 1px solid #666;
 	-webkit-box-shadow: inset 2px 2px 2px rgba(0,0,0,0.2);
@@ -357,8 +358,8 @@ div#carousel-reblog-box {
 #carousel-reblog-box label {
 	color: #aaa;
 	font-size: 11px;
-	padding-right: 2px;
 	padding-left: 2px;
+	padding-right: 2px;
 	display: inline;
 	font-weight: normal;
 }
@@ -376,19 +377,19 @@ div#carousel-reblog-box {
 
 #carousel-reblog-box .submit,
 #wrapper #carousel-reblog-box p.response {
-	float: left;
+	float: right;
 	width: 154px;
 	padding-top: 0;
-	padding-left: 1px;
+	padding-right: 1px;
 	overflow: hidden;
 	height: 34px;
-	margin:3px 0 0 2px !important;
+	margin:3px 2px 0 0 !important;
 }
 
 #wrapper #carousel-reblog-box p.response {
 	font-size: 13px;
 	clear: none;
-	padding-left: 2px;
+	padding-right: 2px;
 	height: 34px;
 	color: #aaa;
 }
@@ -404,14 +405,14 @@ div#carousel-reblog-box {
 	font-weight: normal;
 	background: #aaa;
 	background: -moz-linear-gradient(bottom,  #aaa,  #ccc);
-	background: -webkit-gradient(linear, left bottom, left top, from(#aaa), to(#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, left bottom, left top, from(#ccc), to(#eee));
+	background: -webkit-gradient(linear, right bottom, right top, from(#ccc), to(#eee));
 }
 
 #carousel-reblog-box .canceltext {
@@ -482,7 +483,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 **/
@@ -504,8 +508,8 @@ h1:before, h1:after {
 	font-family: "Helvetica Neue", sans-serif !important;
 	position: inherit !important;
 	top: auto !important;
-	right: auto !important;
 	left: auto !important;
+	right: auto !important;
 	bottom: auto !important;
 	background: none !important;
 	border: none !important;
@@ -521,8 +525,8 @@ h1:before, h1:after {
 
 .jp-carousel-image-meta li {
 	width: 48% !important;
-	float: left !important;
-	margin: 0 2% 15px 0 !important;
+	float: right !important;
+	margin: 0 0 15px 2% !important;
 	color: #fff !important;
 	font-size:13px !important;
 }
@@ -536,7 +540,7 @@ h1:before, h1:after {
 }
 
 a.jp-carousel-image-download {
-	padding-left: 23px;
+	padding-right: 23px;
 	display: inline-block;
 	clear: both;
 	color: #999;
@@ -550,12 +554,12 @@ a.jp-carousel-image-download {
 a.jp-carousel-image-download span.photo-size {
 	font-size: 11px;
 	border-radius: 1em;
-	margin-left: 2px;
+	margin-right: 2px;
 	display: inline-block;
 }
 
 a.jp-carousel-image-download span.photo-size-times {
-	padding: 0 1px 0 2px;
+	padding: 0 2px 0 1px;
 }
 
 a.jp-carousel-image-download:hover {
@@ -576,28 +580,28 @@ a.jp-carousel-image-download:hover {
 
 .jp-carousel-image-map img.gmap-main {
 	-moz-border-radius-topleft: 6px;
-	border-top-left-radius: 6px;
-	border-right: 1px solid rgba( 255, 255, 255, 0.17 );
+	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;
-	right: 0;
+	left: 0;
 }
 .jp-carousel-image-map div.imgclip {
 	overflow: hidden;
 	-moz-border-radius-topright: 6px;
-	border-top-right-radius: 6px;
+	border-top-left-radius: 6px;
 }
 .jp-carousel-image-map div.gmap-topright img {
-	margin-left: -40px;
+	margin-right: -40px;
 }
 .jp-carousel-image-map img.gmap-bottomright {
 	position: absolute;
 	top: 96px;
-	right: 0;
+	left: 0;
 }
 
 /** Comments Start **/
@@ -615,7 +619,7 @@ a.jp-carousel-image-download:hover {
 	background:none transparent;
 	color: #999;
 	margin-bottom: 20px;
-	clear:left;
+	clear:right;
 	overflow: auto;
 	width: 100%
 }
@@ -631,6 +635,8 @@ a.jp-carousel-image-download:hover {
 	width:auto;
 	display: inline;
 	float:none;
+	border:none;
+	margin:0;
 }
 
 .jp-carousel-comment .comment-author a {
@@ -638,16 +644,17 @@ a.jp-carousel-image-download:hover {
 }
 
 .jp-carousel-comment .comment-gravatar {
-	float:left;
+	float:right;
 }
 
 .jp-carousel-comment .comment-content {
 	border:none;
-	margin-left:85px;
+	margin-right:85px;
+	padding: 0;
 }
 
 .jp-carousel-comment .avatar {
-	margin:0 20px 0 0;
+	margin:0 0 0 20px;
 	-moz-border-radius: 4px;
 	-webkit-border-radius: 4px;
 	border-radius: 4px;
@@ -661,13 +668,13 @@ a.jp-carousel-image-download:hover {
 	margin-top: 4px;
 	font-size:11px;
 	display: inline;
-	float: right;
+	float: left;
 	/*clear: right;*/
 }
 
 #jp-carousel-comment-form {
 	margin:0 0 10px !important;
-	float: left;
+	float: right;
 	width: 100%;
 }
 
@@ -707,11 +714,11 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 
 #jp-carousel-comment-form-spinner {
 	color: #fff;
-	margin:22px 0 0 10px;
+	margin:22px 10px 0 0;
 	display: block;
 	width: 20px;
 	height: 20px;
-	float: left;
+	float: right;
 }
 
 #jp-carousel-comment-form-submit-and-info-wrapper {
@@ -730,7 +737,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 	color: #aaa;
 	font: 13px/1.4 "Helvetica Neue", sans-serif !important;
 	padding: 3px 6px;
-	float: left;
+	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;
@@ -747,11 +754,11 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 #jp-carousel-comment-form-commenting-as p {
 	font: 400 13px/1.7 "Helvetica Neue", sans-serif !important;
 	margin:22px 0 0;
-	float: left;
+	float: right;
 }
 
 #jp-carousel-comment-form-commenting-as fieldset {
-	float:left;
+	float:right;
 	border:none;
 	margin:20px 0 0 0;
 	padding:0;
@@ -763,14 +770,14 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 
 #jp-carousel-comment-form-commenting-as label {
 	font: 400 13px/1.7 "Helvetica Neue", sans-serif !important;
-	margin:0 20px 3px 0;
-	float:left;
+	margin:0 0 3px 20px;
+	float:right;
 	width:100px;
 }
 
 #jp-carousel-comment-form-button-submit {
 	margin-top: 20px;
-	float:right;
+	float:left;
 }
 
 #js-carousel-comment-form-container {
@@ -803,8 +810,8 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 	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 0px 5px 5px rgba(0, 0, 0, 1);
-            box-shadow: inset 0px 0px 5px 5px rgba(0, 0, 0, 1);
+    -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 {
@@ -824,7 +831,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 	font: 444 15px/1.7 "Helvetica Neue", sans-serif !important;
 	display: none;
 	color: #999;
-	text-align: left;
+	text-align: right;
 	margin-bottom: 20px;
 }
 
@@ -889,7 +896,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 .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-left: 24px !important;
+	padding-right: 24px !important;
 }
 
 .jp-carousel-light div.jp-carousel-buttons a.jp-carousel-reblog.reblogged,
@@ -905,7 +912,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 .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-left: 23px !important;
+	padding-right: 23px !important;
 }
 
 .jp-carousel-light div.jp-carousel-buttons a.jp-carousel-reblog.reblogged {
@@ -919,7 +926,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 .jp-carousel-light div#carousel-reblog-box {
 	background: #eee;
 	background: -moz-linear-gradient(bottom,  #ececec,  #f7f7f7);
-	background: -webkit-gradient(linear, left bottom, left top, from(#ececec), to(#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);
@@ -951,7 +958,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 	color: #333;
 	background: #fff;
 	background: -moz-linear-gradient(bottom,  #ddd,  #fff);
-	background: -webkit-gradient(linear, left bottom, left top, from(#ddd), to(#fff));
+	background: -webkit-gradient(linear, right bottom, right top, from(#ddd), to(#fff));
 	border: 1px solid #aaa;
 }
 
@@ -959,7 +966,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 	background: #fafafa;
 	border: 1px solid #eee;
 	border-top-color: #f5f5f5;
-	border-left-color: #f5f5f5;
+	border-right-color: #f5f5f5;
 	color: #333;
 }
 
@@ -1035,5 +1042,65 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 
 .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, left bottom, left top, from(rgba(255,255,255,0.75)), to(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 b30ccd7..d5d4da4 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 2835313..f1b5440 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 d33ad24..8dae39b 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 b5fcadd..d3efefa 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 a8f1651..0003518 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 bbf2ba5..5600feb 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 04fd8be..7c19744 100644
Binary files a/plugins/jetpack/modules/contact-form/images/grunion-menu-2x.png and b/plugins/jetpack/modules/contact-form/images/grunion-menu-2x.png 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 f4656a9..21840d1 100644
Binary files a/plugins/jetpack/modules/contact-form/images/grunion-menu-hover-2x.png and b/plugins/jetpack/modules/contact-form/images/grunion-menu-hover-2x.png 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 4955374..244c102 100644
Binary files a/plugins/jetpack/modules/contact-form/images/grunion-remove-field-2x.png and b/plugins/jetpack/modules/contact-form/images/grunion-remove-field-2x.png 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 561382f..11fc10e 100644
Binary files a/plugins/jetpack/modules/contact-form/images/grunion-remove-field-hover-2x.png and b/plugins/jetpack/modules/contact-form/images/grunion-remove-field-hover-2x.png differ

diff --git a/plugins/jetpack/modules/contact-form/js/grunion.js b/plugins/jetpack/modules/contact-form/js/grunion.js
index 4fe391b..835f7f8 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 0000000..2b5e6a3
--- /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 0000000..f458a46
--- /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 0000000..bc5accc
--- /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 0000000..364573a
--- /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 0000000..00a1956
--- /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 0000000..38fc40b
--- /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 0000000..5aaf2bb
--- /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 0000000..f39ecbf
--- /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 0000000..c085568
--- /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 0000000..9e6b24b
--- /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 0000000..9499e83
--- /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 0000000..9bc0c21
--- /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 0000000..79a9626
--- /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 0000000..520b8fc
--- /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=fun
 ction(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("./virt
 ual_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.ig
 noreCase?"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||(RegEx
 p.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=a
 rguments[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 TypeE
 rror;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).jo
 in(":")+"."+("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\v\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.b
 ody.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.remo
 veEventListener)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.stopPropagatio
 n()}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={MODI
 FIER_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.is
 Mac=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/def
 ault_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.getKeybo
 ardHandler=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.removeEventList
 ener("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.onC
 ursorChange=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.$updateHighlightActiveLi
 ne();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=functio
 n(){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){thi
 s.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()},th
 is.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.re
 nderer.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.get
 ShowFoldWidgets=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.remo
 ve(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.toLowe
 rCase()?-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.valu
 e);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.m
 oveLinesUp(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.getFirstVis
 ibleRow=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.moveCursorT
 o=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,th
 is.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.clearSelect
 ion(),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.getLastSearchOp
 tions=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.autocorre
 ct="off",n.autocapitalize="off",n.spellcheck=!1,n.style.top="-2em",e.insertBefore(n,e.firstChild);var u="\x01\x01",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.isOld
 IE){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.g
 etCopyText();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=func
 tion(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=thi
 s.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.captur
 eMouse(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.mou
 sedownEvent.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.rend
 erer.$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=n
 ull,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.$i
 nSelection=!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.ren
 derer.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.foldWidge
 ts&&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.addKeyboardHa
 ndler(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.passEve
 nt!=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)br
 eak}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.setBreakpo
 ints=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){fu
 nction 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.$work
 er=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.$undoS
 elect&&!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.acti
 on,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.$useWra
 pMode?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){retu
 rn 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.getAttr
 ibute("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 availabl
 e");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 f
 or '"+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.is
 Backwards();(!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.setSelection
 Anchor(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(typeo
 f 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.do
 c.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.sessio
 n.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,t
 his.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.lastInd
 ex=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.$s
 electLongWords?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.deta
 ch(),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)va
 r 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("./b
 ehaviour").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=funct
 ion(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-0A300A320A330A350A360A
 380A390A59-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-17B317D717DC182
 0-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-A
 ADDABC0-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-03D703D903DB03
 DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F
 151F20-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-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E013001320134013
 60139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A0
 50C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD6
 2CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-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-0A
 300A320A330A350A360A380A390A59-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-074A0
 7A6-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-302F309930
 9AA66F-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-192
 21927192819321939-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-1B4
 11B431B441B821BA11BA61BA71BAA1C24-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-1B
 B91C40-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-A60FA673A67EA6F
 2-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:"005F203F20402054FE33FE34FE
 4D-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-0608060B060E060F06E906FD06FE07F609F209F
 309FA09FB0AF10B700BF3-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-208
 C2140-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-2426
 2440-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-0A800A840A8E0A920AA
 90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-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-17FF180F
 181A-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-D7AFD7C
 7-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-1
 C4C1C80-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-FFF8FFFEF
 FFF"})}),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.$line
 s.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.r
 ow-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"],func
 tion(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.r
 ow}),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},th
 is.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.getCurre
 ntToken();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.$foldSty
 le=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);re
 turn}}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").R
 ange;(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.en
 d=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=functi
 on(){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.f
 indAll=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.removeEventListen
 er("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.comman
 ds[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(nu
 ll,"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:"got
 oright",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:"selectlinestar
 t",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()},mult
 iSelectAction:"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=pr
 ompt("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",bind
 Key: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.$und
 oStack.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+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8v
 bnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTQ4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTU4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBMjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBMzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkgXxbAAAAJbSURBVHjapFNNaBNBFH4zs5vdZLP5sQmNpT82QY209heh1ioWisaDRcSKF0WKJ0GQnrzrxasHsR6EnlrwD0TagxJabaVEpFYxLWlLSS822tr87m66ccfd2GKyVhA6MMybgfe97/vmPUQphd0sZjto9XIn9OOsvlu2nkqRzVU+6vvlzPf8W6bk8dxQ0NPbxAALgCgg2JkaQuhzQau/El0zbmUA7U0Es8v2CiYmKQJHGO1QICCLoqilMhkmurDAyapKgqItezi/USRdJqEYY4D5jCy03ht2yMkkvL91jTTX10qzyyu2hruPRN7jgbH+E
 OsXcMLgYiThEgAMhABW85oqy1DXdRIdvP1AHJ2acQXvDIrVHcdQNrEKNYSVMSZGMjEzIIAwDXIo+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+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAg
 ICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTg4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTk4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBNjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBNzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/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/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccll
 PAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRTk5MTVGREIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRTk5MTVGRUIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZFOTkxNUZCQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFOTkxNUZDQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDI
 i8+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-b
 ox;-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%14
 USO%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%0
 2%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%8
 2%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_cont
 ent {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 transparen
 t;}.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.$keepT
 extAreaAtCursor=!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(th
 is.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!=t
 his.$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.CHA
 NGE_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.getW
 idth()+"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.displayIndent
 Guides},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.co
 ntent.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=functi
 on(){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(th
 is.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.set
 Markers(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.te
 xtarea,"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.$them
 eValue},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.addGutterDecorat
 ion=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.chara
 cterWidth,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=th
 is.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.getNextFoldLi
 ne(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_V
 ALUE;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.bli
 nkInterval=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-curso
 rs"),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)}}).cal
 l(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").EditSessi
 on;(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.rectangularRangeB
 lock=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.sess
 ion.$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.c
 ommands.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.star
 t: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.$r
 eAlignText=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.r
 emoveEventListener("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.updateSelectionMar
 kers()},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",m
 ac:"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:"splitIntoLine
 s",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&&s
 etTimeout(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().$undoSt
 ack||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(ne
 w 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,col
 umn: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.foldingSto
 pMarker=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 0000000..2015555
--- /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|ma
 rquee-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|tr
 ansition-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|d
 otted|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|r
 ound|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"],r
 egex: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.lpar
 en",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","exp
 orts","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.recordAuto
 Insert(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 0000000..6ef94f8
--- /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 0000000..d8ef471
--- /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_ma
 rker-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 0000000..59ceeaf
--- /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.ge
 tOwnPropertyDescriptor=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(fun
 ction(){})}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)D
 ate.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;re
 turn 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\v\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.addEventListe
 ner=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.stri
 ngReverse=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.defer
 redUpdate=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.getAllL
 ines().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.le
 ngth},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())retu
 rn 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=fun
 ction(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.star
 t.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.colum
 n,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.$clipPositionT
 oDocument=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.crea
 teTokenData=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}funct
 ion 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=C
 olors[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 is
 NameStart(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",lig
 htgreen:"#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",saddlebrow
 n:"#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 EventTa
 rget,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_S
 YM)&&(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.mu
 stMatch(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._tok
 enStream,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.BOTTOMRIGHT
 CORNER_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._tokenSt
 ream;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._ne
 gation],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:"p
 roperty",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._readWh
 itespace()&&(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._r
 eadWhitespace(),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},parseStyleAttribut
 e: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:"n
 ormal | 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||ValidationType
 s.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:"<lengt
 h> | <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","bord
 er-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-b
 efore":"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 | tab
 le-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-pu
 nctuation":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 | hi
 dden | 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",rotat
 ion: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":"<in
 teger> | 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._mark
 s.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.createTok
 en(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&&isWhitespa
 ce(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:"TOPR
 IGHT_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:"DO
 T",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;whi
 le(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=="ident
 ifier"},"<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.roll
 up?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.add
 Listener("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){functi
 on 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.p
 ropCount==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=t
 his;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 0000000..65b01d6
--- /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 0000000..eef6ab4
--- /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 0000000..c42147c
--- /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 0000000..5ad188c
--- /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 c3bc7aa..b2a8015 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 0000000..9cd511e
--- /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 3678837..9edd15a 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 0000000..93e3f9c
--- /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 0000000..96fd609
--- /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 0000000..857ac6e
--- /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 0000000..dd39179
--- /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 0000000..7a76d8f
--- /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 0000000..ad57f1b
--- /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 0000000..cc23278
--- /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 0000000..a80ee81
--- /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 0000000..889abb3
--- /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 0000000..094cef9
--- /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 0000000..032c2c9
--- /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 0000000..f8b7701
--- /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 0000000..fb1473f
--- /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 4e4d9db..76066cd 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 0000000..753d4ab
--- /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 0000000..3885cac
--- /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 0000000..e2047e5
--- /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 0000000..4b5f4be
Binary files /dev/null and b/plugins/jetpack/modules/minileven/images/wp-app-devices.png differ

diff --git a/plugins/jetpack/modules/minileven/minileven.php b/plugins/jetpack/modules/minileven/minileven.php
new file mode 100644
index 0000000..ae2ab01
--- /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 0000000..55c3516
--- /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 0000000..cf69f25
--- /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 0000000..9ab0351
--- /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 0000000..b739fe4
--- /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 0000000..d13cb23
--- /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 0000000..7c5f9a6
--- /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 0000000..be8402b
--- /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 0000000..8a7a21e
--- /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 0000000..2fc5f6d
--- /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 0000000..35a9672
--- /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 0000000..71aa73b
--- /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 0000000..f6e1d06
--- /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 0000000..785137e
--- /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 0000000..7b67e1f
--- /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 0000000..348e94c
Binary files /dev/null and b/plugins/jetpack/modules/minileven/theme/pub/minileven/screenshot.png 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 0000000..b4fd79a
--- /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 0000000..5d1a4a0
--- /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 0000000..692a8f4
--- /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 0000000..8981348
--- /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 0000000..5013f7c
--- /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 d103820..218a9e8 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 0000000..e33f7ff
--- /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 0000000..06db868
--- /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 0000000..050e73b
--- /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 0000000..e8cd887
--- /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 0000000..c3b88de
--- /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 0000000..7ba14bd
--- /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 0000000..c9a37e5
--- /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 0000000..24e0c11
Binary files /dev/null and b/plugins/jetpack/modules/publicize/assets/connected.gif 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 0000000..b9181cc
Binary files /dev/null and b/plugins/jetpack/modules/publicize/assets/facebook-logo.png 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 0000000..27018dc
Binary files /dev/null and b/plugins/jetpack/modules/publicize/assets/linkedin-logo.png differ

diff --git a/plugins/jetpack/modules/publicize/assets/publicize.css b/plugins/jetpack/modules/publicize/assets/publicize.css
new file mode 100644
index 0000000..4065cb0
--- /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 0000000..bb1f8d4
--- /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 0000000..b56ab2f
--- /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 0000000..6e5bace
Binary files /dev/null and b/plugins/jetpack/modules/publicize/assets/spinner.gif 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 0000000..1ec62d3
Binary files /dev/null and b/plugins/jetpack/modules/publicize/assets/tumblr-logo.png 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 0000000..6c7b89b
Binary files /dev/null and b/plugins/jetpack/modules/publicize/assets/twitter-logo.png 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 0000000..b7ffe2b
Binary files /dev/null and b/plugins/jetpack/modules/publicize/assets/yahoo-logo.png differ

diff --git a/plugins/jetpack/modules/publicize/publicize-jetpack.php b/plugins/jetpack/modules/publicize/publicize-jetpack.php
new file mode 100644
index 0000000..58e2564
--- /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 0000000..16d4541
--- /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 0000000..d9d2b37
--- /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 fa7b36a..f6f4ad6 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 fd0e3d4..aea3079 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 0000000..a5c7194
Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.png 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 0000000..de6a8a1
Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/icon-facebook.png 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 0000000..85f2f34
Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/icon-twitter-2x.png 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 0000000..ec41046
Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/icon-twitter.png 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 0000000..4d81cab
Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/icon-wordpress-2x.png 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 0000000..86f1bd3
Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/icon-wordpress.png differ

diff --git a/plugins/jetpack/modules/sharedaddy/sharedaddy.php b/plugins/jetpack/modules/sharedaddy/sharedaddy.php
index 727005e..ab8085c 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 82d7293..c8efee3 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 bd8b2eb..256513c 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 fb45c92..95a09d0 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 a6c2949..68482c6 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 3dd6f8d..118f851 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 7b507a5..9c6b49e 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 0000000..167ec70
--- /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 0000000..e6d05b2
--- /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 8ced50e..fe79a9e 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 0000000..2c76ac0
Binary files /dev/null and b/plugins/jetpack/modules/shortcodes/img/slideshow-controls-2x.png 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 0000000..09ca487
Binary files /dev/null and b/plugins/jetpack/modules/shortcodes/img/slideshow-controls.png 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 0000000..ce1c594
Binary files /dev/null and b/plugins/jetpack/modules/shortcodes/img/slideshow-loader.gif 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 0000000..7697258
--- /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 0000000..89d583e
--- /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 0000000..5e13209
--- /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 bcb30f8..7eb30ed 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 0000000..ab1145d
--- /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 8aa3538..a748611 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 0000000..afd3596
--- /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 912ab4c..6aebae0 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 2225a5f..02b417e 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 ebf989f..74c497e 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 32c6cf2..260b3f5 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 2355867..39c639f 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 0000000..6db8714
--- /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 0000000..dab5fd2
--- /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 0000000..342e8a6
--- /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 0000000..007c0cc
--- /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 0000000..3a1924d
--- /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 0000000..90f8ed7
--- /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 3d9c2f8..5771cdb 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 64d03f8..f8ab251 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 230a3b1..1663ae0 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 c33e699..190427f 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 0e7e227..03d4d5c 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 0000000..7729ed3
--- /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 0000000..b6f2c8d
--- /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 0000000..ff49abf
--- /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 0000000..984016c
--- /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 0000000..a2d6295
--- /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 60de369..f4808dd 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 f448dc7..d373d5c 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 07a67b5..b3a4b12 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 d88eeac..d12aabd 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 0000000..c9d9779
--- /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 0000000..7370715
--- /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 0000000..2729138
--- /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 0000000..58b46bf
--- /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 0000000..d562e33
--- /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 0000000..3c60cea
--- /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 0000000..0c7d08f
--- /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 0000000..3e25b7d
--- /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 0000000..7b0c640
--- /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 0000000..e8f29ac
--- /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 0000000..c4e38c0
--- /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 0000000..074421a
--- /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 0000000..e6c4bdf
--- /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 0000000..eca6b9c
--- /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 0000000..dd02661
--- /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 0000000..80024ba
--- /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 0000000..fc10800
--- /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 0000000..9a5b20d
--- /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 0000000..a5299b3
--- /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 0000000..b83c591
--- /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 0000000..f08ca8b
--- /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 0000000..0461bdc
--- /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 0000000..d90e43e
--- /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 0000000..c040597
--- /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 0000000..4558fa1
--- /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 0000000..5ece707
--- /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 0000000..9887d1e
--- /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 0000000..69222a5
--- /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 0000000..000440b
--- /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 0000000..c051b55
--- /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 0000000..148cde1
--- /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 0000000..3f54fd0
--- /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 0000000..a5afa8e
--- /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 0000000..4848a2b
--- /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 0000000..6f0f8b7
--- /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 0000000..2689053
--- /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 0000000..cf1f5c4
--- /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 0000000..1f5af96
--- /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 0000000..0143a69
--- /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 0000000..5e11587
--- /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 0000000..9ea2db7
--- /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 6ea0dac..fe7feb4 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 5b12bfd..abada5c 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 4a553a7..f2ccf5f 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 174ac43..2187a72 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 0000000..2401f78
--- /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 f7b5a51..c6ff9ef 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 c00792e..5209c51 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 07f9eaf..203e04d 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 f4a4bd8..8042826 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 391e017..86aa479 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 d0f3a50..f46387a 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 8b510df..5acd261 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 276cf4f..08e5b49 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 ceaa61d..189d714 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 eb98c97..c4ef2c3 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 e9f19da..5b1e5aa 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', 'lon
 g_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', 'com
 plexarctan', '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', 'lon
 g 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', 'com
 plexarctan', '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 ddd4d6a..c944443 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 870ac0f..603fa4a 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 0512380..9f1ed04 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 0000000..8e3c0a3
--- /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 aebfa35..dd0a7ec 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 5f48f11..0096a16 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 0000000..8683588
--- /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','YZEqua
 ls','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','bibliography
 style','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','li
 st','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','xo
 utput','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','HookHe
 ad','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','Ri
 ghtSide','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','foregroundcolo
 r','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','pa
 geheight','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 3f35e8a..7a0f1ee 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 de2ad79..970684d 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 b51bd27..ab401b4 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 af11e98..88f6628 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 38d7de1..1ec239b 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 0000000..864f74e
--- /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 658111a..c69f005 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 ee25ca7..35c9274 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 dd83121..c06ca5b 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 9a6af63..51cb4ce 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 e431d3a..1d3c08d 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 13341f7..ca15cf9 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 37c6304..b68d442 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 1cdc24f..35d5b01 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 0000000..42b3d77
--- /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 3e73519..41c21ce 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 c09c84a..8b8b2f2 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 d56e571..3fa7ead 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 27ade0c..e40963f 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 80a7f72..2d165bd 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 a4dc431..f9d0a86 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 58bd42b..9872e75 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 4494fb2..0ad4e4a 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 00143bf..67277aa 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 9263370..b07be48 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/idl.php b/plugins/wp-syntax/geshi/geshi/coffeescript.php
similarity index 54%
copy from plugins/wp-syntax/geshi/geshi/idl.php
copy to plugins/wp-syntax/geshi/geshi/coffeescript.php
index 5e73027..194aecd 100644
--- a/plugins/wp-syntax/geshi/geshi/idl.php
+++ b/plugins/wp-syntax/geshi/geshi/coffeescript.php
@@ -1,15 +1,17 @@
 <?php
 /*************************************************************************************
- * idl.php
- * -------
- * Author: Cedric Bosdonnat (cedricbosdo@openoffice.org)
- * Copyright: (c) 2006 Cedric Bosdonnat
- * Release Version: 1.0.8.9
- * Date Started: 2006/08/20
+ * 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
  *
- * Unoidl language file for GeSHi.
+ * CoffeeScript language file for GeSHi.
  *
- * 2006/08/20 (1.0.0)
+ * CHANGES
+ * -------
+ * 2010/06/08 (1.0.8.9)
  *  -  First Release
  *
  *************************************************************************************
@@ -32,66 +34,83 @@
  *
  ************************************************************************************/
 
-
 $language_data = array (
-    'LANG_NAME' => 'Uno Idl',
-    'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
-    'COMMENT_MULTI' => array('/*' => '*/'),
+    'LANG_NAME' => 'CoffeeScript',
+    'COMMENT_SINGLE' => array(1 => '#'),
+    'COMMENT_MULTI' => array('###' => '###'),
     'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
-    'QUOTEMARKS' => array("'", '"'),
+    //Longest quotemarks ALWAYS first
+    'QUOTEMARKS' => array('"""', "'''", '"', "'"),
     'ESCAPE_CHAR' => '\\',
     'KEYWORDS' => array(
+
+        /*
+        ** Set 1: control keywords
+        */
         1 => array(
-            'published', 'get', 'set', 'service', 'singleton', 'type', 'module', 'interface', 'struct',
-            'const', 'constants', 'exception', 'enum', 'raises', 'typedef'
+            '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(
-            'bound', 'maybeambiguous', 'maybedefault', 'maybevoid', 'oneway', 'optional',
-            'readonly', 'in', 'out', 'inout', 'attribute', 'transient', 'removable'
+            'and', 'or', 'is', 'isnt', 'not'
             ),
+
+        /*
+        ** Set 3: other keywords
+        */
         3 => array(
-            'True', 'False', 'TRUE', 'FALSE'
+            'instanceof', 'new', 'delete', 'typeof',
+            'class', 'super', 'this', 'extends'
             ),
+
+        /*
+        ** Set 4: constants
+        */
         4 => array(
-            'string', 'long', 'byte', 'hyper', 'boolean', 'any', 'char', 'double',
-            'void', 'sequence', 'unsigned'
-            ),
+            '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,
+        4 => true
         ),
     'STYLES' => array(
         'KEYWORDS' => array(
-            1 => 'color: #990078; font-weight: bold',
-            2 => 'color: #36dd1c;',
-            3 => 'color: #990078; font-weight: bold',
-            4 => 'color: #0000ec;'
+            1 => 'color: #ff7700;font-weight:bold;',
+            2 => 'color: #008000;',
+            3 => 'color: #dc143c;',
+            4 => 'color: #0000cd;'
             ),
         'COMMENTS' => array(
-            1 => 'color: #3f7f5f;',
-            2 => 'color: #808080;',
-            'MULTI' => 'color: #4080ff; font-style: italic;'
+            1 => 'color: #808080; font-style: italic;',
+            'MULTI' => 'color: #808080; font-style: italic;'
             ),
         'ESCAPE_CHAR' => array(
-            0 => 'color: #666666; font-weight: bold;'
+            0 => 'color: #000099; font-weight: bold;'
             ),
         'BRACKETS' => array(
-            0 => 'color: #808080;'
+            0 => 'color: black;'
             ),
         'STRINGS' => array(
-            0 => 'color: #ff0000;'
+            0 => 'color: #483d8b;'
             ),
         'NUMBERS' => array(
-            0 => 'color: #0000dd;'
+            0 => 'color: #ff4500;'
             ),
         'METHODS' => array(
+            1 => 'color: black;'
             ),
         'SYMBOLS' => array(
             0 => 'color: #66cc66;'
@@ -107,17 +126,21 @@ $language_data = array (
         3 => '',
         4 => ''
         ),
-    'OOLANG' => false,
+    'OOLANG' => true,
     'OBJECT_SPLITTERS' => array(
-        1 => '::'
+        1 => '.'
         ),
     'REGEXPS' => array(
         ),
-    'STRICT_MODE_APPLIES' => GESHI_NEVER,
+    '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 07f0cf2..36626c9 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 48b7726..42ab311 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 1c7eea0..26024e9 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 2cb3f34..d09bea7 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 2820b04..ebaca95 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 af0468a..7f3e985 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 0000000..db12a4c
--- /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/m68k.php b/plugins/wp-syntax/geshi/geshi/dcpu16.php
similarity index 57%
copy from plugins/wp-syntax/geshi/geshi/m68k.php
copy to plugins/wp-syntax/geshi/geshi/dcpu16.php
index 3c0dfc2..5fcb25e 100644
--- a/plugins/wp-syntax/geshi/geshi/m68k.php
+++ b/plugins/wp-syntax/geshi/geshi/dcpu16.php
@@ -1,25 +1,21 @@
 <?php
 /*************************************************************************************
- * m68k.php
- * --------
+ * dcpu16.php
+ * -------
  * 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
- * Date Started: 2007/02/06
- *
- * Motorola 68000 Assembler language file for GeSHi.
+ * Copyright: (c) 2007-2012 Benny Baumann (http://geshi.org/)
+ * Release Version: 1.0.8.11
+ * Date Started: 2012/04/12
  *
- * Syntax definition as commonly used by the motorola documentation for the
- * MC68HC908GP32 Microcontroller (and maybe others).
+ * DCPU/16 Assembly language file for GeSHi.
+ * Syntax definition based on http://0x10c.com/doc/dcpu-16.txt
  *
  * CHANGES
  * -------
- * 2008/05/23 (1.0.7.22)
- *   -  Added description of extra language features (SF#1970248)
- * 2007/06/02 (1.0.0)
+ * 2012/04/12 (1.0.0)
  *   -  First Release
  *
- * TODO (updated 2007/06/02)
+ * TODO (updated 2012/04/12)
  * -------------------------
  *
  *************************************************************************************
@@ -43,50 +39,39 @@
  ************************************************************************************/
 
 $language_data = array (
-    'LANG_NAME' => 'Motorola 68000 Assembler',
+    '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(
-            'adc','add','ais','aix','and','asl','asr','bcc','bclr','bcs','beq',
-            'bge','bgt','bhcc','bhcs','bhi','bhs','bih','bil','bit','ble','blo',
-            'bls','blt','bmc','bmi','bms','bne','bpl','bra','brclr','brn',
-            'brset','bset','bsr','cbeq','clc','cli','clr','cmp','com','cphx',
-            'cpx','daa','dbnz','dec','div','eor','inc','jmp','jsr','lda','ldhx',
-            'ldx','lsl','lsr','mov','mul','neg','nop','nsa','ora','psha','pshh',
-            'pshx','pula','pulh','pulx','rol','ror','rsp','rti','rts','sbc',
-            'sec','sei','sta','sthx','stop','stx','sub','swi','tap','tax','tpa',
-            'tst','tsx','txa','txs','wait'
-        ),
+            'set','add','sub','mul','div','mod','shl','shr','and','bor','xor',
+            'ife','ifn','ifg','ifb',
+            'jsr'
+            ),
         /*registers*/
         2 => array(
-            'a','h','x',
-            'hx','sp'
-            ),
-        /*Directive*/
-        3 => array(
-            '#define','#endif','#else','#ifdef','#ifndef','#include','#undef',
-            '.db','.dd','.df','.dq','.dt','.dw','.end','.org','equ'
+            '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,
-        3 => false,
         ),
     'STYLES' => array(
         'KEYWORDS' => array(
-            1 => 'color: #0000ff; font-weight:bold;',
-            2 => 'color: #0000ff;',
-            3 => 'color: #46aa03; font-weight:bold;'
+            1 => 'color: #000088; font-weight:bold;',
+            2 => 'color: #0000ff;'
             ),
         'COMMENTS' => array(
             1 => 'color: #adadad; font-style: italic;',
@@ -95,13 +80,13 @@ $language_data = array (
             0 => 'color: #000099; font-weight: bold;'
             ),
         'BRACKETS' => array(
-            0 => 'color: #0000ff;'
+            0 => 'color: #000088;'
             ),
         'STRINGS' => array(
             0 => 'color: #7f007f;'
             ),
         'NUMBERS' => array(
-            0 => 'color: #dd22dd;'
+            0 => 'color: #880000;'
             ),
         'METHODS' => array(
             ),
@@ -109,35 +94,38 @@ $language_data = array (
             0 => 'color: #008000;'
             ),
         'REGEXPS' => array(
-            0 => 'color: #22bbff;',
-            1 => 'color: #22bbff;',
             2 => 'color: #993333;'
             ),
         'SCRIPT' => array(
             )
         ),
     'URLS' => array(
-        1 => '',
-        2 => '',
-        3 => ''
+        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]',
+        //0 => '0[0-9a-fA-F]{1,32}[hH]',
         //Binary numbers
-        1 => '\%[01]{1,64}[bB]',
+        //1 => '\%[01]{1,64}|[01]{1,64}[bB]?(?![^<]*>)',
         //Labels
-        2 => '^[_a-zA-Z][_a-zA-Z0-9]*?\:'
+        2 => '^:[_a-zA-Z][_a-zA-Z0-9]?(?=\s|$)'
         ),
     'STRICT_MODE_APPLIES' => GESHI_NEVER,
     'SCRIPT_DELIMITERS' => array(
         ),
     'HIGHLIGHT_STRICT_BLOCK' => array(
         ),
-    'TAB_WIDTH' => 8
+    '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 05f2d31..d32cfc5 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 1c252e3..d5596e0 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 bcf0c1d..5b68171 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 2bfa24d..aa11795 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 75fee1c..36d9983 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 698cf13..bdf240a 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 fb80fca..319bee0 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 2d3f09f..69a55c9 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 57e00b9..baa13c3 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 6becb1f..8a313d4 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 0000000..c575c0c
--- /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 1d4bccf..4b8d406 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 0000000..7bbf884
--- /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 dd3a812..7d76760 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 0000000..2111d9e
--- /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 9e08b9c..ba4a592 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 d8b104a..c21ccd1 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 77f75b5..b23f39b 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 0000000..c6fff27
--- /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 afff9dc..d85a7c7 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 a4dd43f..352830e 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 be94fa8..0a5e32c 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 5f752b8..e1b20b3 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 3c354ad..db05ec0 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 90c34a8..80b531c 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 dbb7ff6..3615cfe 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 9d0d88d..999251b 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 05e2601..d8445ea 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 941b74a..5b7a47d 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 e6f8ae0..45290d2 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 4b2b272..ecc1634 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 d459470..adae111 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 0000000..778637e
--- /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 532c83a..78a2bc2 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 a06fdc8..7ba1a73 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 6e0e2f0..97392fa 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/html4strict.php b/plugins/wp-syntax/geshi/geshi/html5.php
similarity index 68%
copy from plugins/wp-syntax/geshi/geshi/html4strict.php
copy to plugins/wp-syntax/geshi/geshi/html5.php
index 6e0e2f0..0d97559 100644
--- a/plugins/wp-syntax/geshi/geshi/html4strict.php
+++ b/plugins/wp-syntax/geshi/geshi/html5.php
@@ -1,13 +1,13 @@
 <?php
 /*************************************************************************************
- * html4strict.php
+ * html5.php
  * ---------------
  * 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.
+ * HTML 5 language file for GeSHi.
  *
  * CHANGES
  * -------
@@ -50,7 +50,7 @@
  ************************************************************************************/
 
 $language_data = array (
-    'LANG_NAME' => 'HTML',
+    'LANG_NAME' => 'HTML5',
     'COMMENT_SINGLE' => array(),
     'COMMENT_MULTI' => array(),
     'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
@@ -58,60 +58,64 @@ $language_data = array (
     'ESCAPE_CHAR' => '',
     'KEYWORDS' => array(
         2 => array(
-            'a', 'abbr', 'acronym', 'address', 'applet',
+            'a', 'abbr', 'address', 'article', 'area', 'aside', 'audio',
 
-            'base', 'basefont', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'b',
+            'base', 'bdo', 'blockquote', 'body', 'br', 'button', 'b',
 
-            'caption', 'center', 'cite', 'code', 'colgroup', 'col',
+            'caption', 'cite', 'code', 'colgroup', 'col', 'canvas', 'command', 'datalist', 'details',
 
-            'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt',
+            'dd', 'del', 'dfn', 'div', 'dl', 'dt',
 
-            'em',
+            'em', 'embed',
 
-            'fieldset', 'font', 'form', 'frame', 'frameset',
+            'fieldset', 'form', 'figcaption', 'figure', 'footer',
 
-            'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html',
+            'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html', 'header', 'hgroup',
 
             'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'i',
 
-            'kbd',
+            'kbd', 'keygen',
 
             'label', 'legend', 'link', 'li',
 
-            'map', 'meta',
+            'map', 'meta', 'mark', 'meter',
 
-            'noframes', 'noscript',
+            'noscript', 'nav',
 
-            'object', 'ol', 'optgroup', 'option',
+            'object', 'ol', 'optgroup', 'option', 'output',
 
-            'param', 'pre', 'p',
+            'param', 'pre', 'p', 'progress',
 
             'q',
 
-            'samp', 'script', 'select', 'small', 'span', 'strike', 'strong', 'style', 'sub', 'sup', 's',
+            'rp', 'rt', 'ruby',
 
-            'table', 'tbody', 'td', 'textarea', 'text', 'tfoot', 'thead', 'th', 'title', 'tr', 'tt',
+            'samp', 'script', 'select', 'small', 'span', 'strong', 'style', 'sub', 'sup', 's', 'section', 'source', 'summary',
 
-            'ul', 'u',
+            'table', 'tbody', 'td', 'textarea', 'text', 'tfoot', 'thead', 'th', 'title', 'tr', 'time',
 
-            'var',
+            'ul',
+
+            'var', 'video',
+
+            'wbr',
             ),
         3 => array(
-            'abbr', 'accept-charset', 'accept', 'accesskey', 'action', 'align', 'alink', 'alt', 'archive', 'axis',
+            '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',
-            'data', 'datetime', 'declare', 'defer', 'dir', 'disabled',
+            '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',
-            'headers', 'height', 'href', 'hreflang', 'hspace', 'http-equiv',
+            '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',
-            'name', 'nohref', 'noresize', 'noshade', 'nowrap',
-            'object', 'onblur', 'onchange', 'onclick', 'ondblclick', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onreset', 'onselect', 'onsubmit', 'onunload',
-            'profile', 'prompt',
-            'readonly', 'rel', 'rev', 'rowspan', 'rows', 'rules',
-            'scheme', 'scope', 'scrolling', 'selected', 'shape', 'size', 'span', 'src', 'standby', 'start', 'style', 'summary',
+            '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',
@@ -151,6 +155,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 +175,9 @@ $language_data = array (
         ),
     'STRICT_MODE_APPLIES' => GESHI_ALWAYS,
     'SCRIPT_DELIMITERS' => array(
+        -2 => array(
+            '<![CDATA[' => ']]>'
+            ),
         -1 => array(
             '<!--' => '-->'
             ),
@@ -184,6 +192,7 @@ $language_data = array (
             )
     ),
     'HIGHLIGHT_STRICT_BLOCK' => array(
+        -2 => false,
         -1 => false,
         0 => false,
         1 => false,
@@ -200,4 +209,4 @@ $language_data = array (
     )
 );
 
-?>
+?>
\ 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 8852e77..06383ea 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 5e73027..69bd14f 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 692a1aa..8e6ca76 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 af2aab5..1e2ee8b 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 e123dae..3c81b81 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 b6fcb81..51fad43 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 184385b..5565bb4 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 7fcc2e8..652b8dd 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 b51edab..af16bd1 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 f250e50..b96d1b5 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 bd7cd5c..a75320d 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 e2d7174..5b90919 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 9a33499..5f86e78 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 9018b78..6564c6b 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 51ca73f..386a0b9 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 6c93268..6c28828 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/properties.php b/plugins/wp-syntax/geshi/geshi/ldif.php
similarity index 72%
copy from plugins/wp-syntax/geshi/geshi/properties.php
copy to plugins/wp-syntax/geshi/geshi/ldif.php
index ba91639..4248183 100644
--- a/plugins/wp-syntax/geshi/geshi/properties.php
+++ b/plugins/wp-syntax/geshi/geshi/ldif.php
@@ -1,20 +1,20 @@
 <?php
 /*************************************************************************************
- * properties.php
+ * ldif.php
  * --------
- * Author: Edy Hinzen
- * Copyright: (c) 2009 Edy Hinzen
- * Release Version: 1.0.8.9
- * Date Started: 2009/04/03
+ * 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
  *
- * Property language file for GeSHi.
+ * LDIF language file for GeSHi.
  *
  * CHANGES
  * -------
- * 2008/04/03 (1.0.0)
+ * 2010/03/01 (1.0.8.11)
  *   -  First Release
+ *   -  Derived from ini.php (INI language), (c) 2005 deguix
  *
- * TODO
  * -------------------------
  *
  *************************************************************************************
@@ -38,31 +38,24 @@
  ************************************************************************************/
 
 $language_data = array (
-    'LANG_NAME' => 'PROPERTIES',
+    'LANG_NAME' => 'LDIF',
     'COMMENT_SINGLE' => array(1 => '#'),
     'COMMENT_MULTI' => array(),
     'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
-    'QUOTEMARKS' => array('"'),
+    'QUOTEMARKS' => array(),
     'ESCAPE_CHAR' => '',
     'KEYWORDS' => array(
-        /* Common used variables */
-        1 => array(
-            '${user.home}'
-            ),
         ),
     'SYMBOLS' => array(
-        '[', ']', '='
         ),
     'CASE_SENSITIVE' => array(
-        GESHI_COMMENTS => false,
-        1 => true
+        GESHI_COMMENTS => false
         ),
     'STYLES' => array(
         'KEYWORDS' => array(
-            1 => 'font-weight: bold;',
             ),
         'COMMENTS' => array(
-            1 => 'color: #808080; font-style: italic;'
+            1 => 'color: #666666; font-style: italic;'
             ),
         'ESCAPE_CHAR' => array(
             0 => ''
@@ -80,40 +73,36 @@ $language_data = array (
             0 => ''
             ),
         'SYMBOLS' => array(
-            0 => 'color: #000000;'
             ),
         'REGEXPS' => array(
-            0 => 'color: #000080; font-weight:bold;',
-            1 => 'color: #008000; font-weight:bold;'
+            0 => 'color: #000066; font-weight: bold;',
+            1 => 'color: #FF0000;'
             ),
         'SCRIPT' => array(
             0 => ''
             )
         ),
     'URLS' => array(
-        1 => ''
         ),
     'OOLANG' => false,
     'OBJECT_SPLITTERS' => array(
         ),
     'REGEXPS' => array(
-        //Entry names
         0 => array(
-            GESHI_SEARCH => '^(\s*)([.a-zA-Z0-9_\-]+)(\s*=)',
-            GESHI_REPLACE => '\\2',
-            GESHI_MODIFIERS => 'm',
-            GESHI_BEFORE => '\\1',
-            GESHI_AFTER => '\\3'
+            GESHI_SEARCH => '([a-zA-Z0-9_]+):(.+)',
+            GESHI_REPLACE => '\\1',
+            GESHI_MODIFIERS => '',
+            GESHI_BEFORE => '',
+            GESHI_AFTER => ':\\2'
             ),
-        //Entry values
         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_]+\s*)=(.*)',
+            GESHI_SEARCH => '([<>";a-zA-Z0-9_]+):(.+)',
             GESHI_REPLACE => '\\2',
             GESHI_MODIFIERS => '',
-            GESHI_BEFORE => '\\1=',
+            GESHI_BEFORE => '\\1:',
             GESHI_AFTER => ''
             )
         ),

diff --git a/plugins/wp-syntax/geshi/geshi/lisp.php b/plugins/wp-syntax/geshi/geshi/lisp.php
index c80ce23..be823a4 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 0000000..580099b
--- /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 1bc88c8..61c8a3c 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 90355ff..0573466 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 f161ff3..ab6088b 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 6542375..12257d7 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 412e6e4..b8b65f2 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 fb16d35..298af61 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 5e50d1f..f80cf4f 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 2d43b84..8a09ba2 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 3c0dfc2..9832157 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 5cb21af..612e160 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 fe49583..885fa17 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 c8cf0e1..8859c48 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 3922f50..7cdd50e 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 d6d8e29..fa2f307 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 75b69c2..60b6e28 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 0e3a9ae..1850834 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 e6a9a07..ae08dcf 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 e57f2c3..f724a94 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 fc1c424..0cc8287 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 873cff3..507da2d 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 0000000..32cbaef
--- /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 0000000..14a2d23
--- /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 b2e0f60..0dc6c16 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 2079169..35df9b4 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 1fd99e2..b43f814 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 a6a8b23..2f5162d 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 6bf17de..bf9dab5 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 f450342..b518adf 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 67d8a76..ac6c29b 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 0000000..ccffcd9
--- /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 6418059..ff75af6 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 0000000..62c6cc4
--- /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 8444d00..16259e6 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 7bd1343..145bda4 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 a079c84..bc2ee65 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 23be8d6..d24561b 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/ada.php b/plugins/wp-syntax/geshi/geshi/parasail.php
similarity index 68%
copy from plugins/wp-syntax/geshi/geshi/ada.php
copy to plugins/wp-syntax/geshi/geshi/parasail.php
index eb98c97..864eba1 100644
--- a/plugins/wp-syntax/geshi/geshi/ada.php
+++ b/plugins/wp-syntax/geshi/geshi/parasail.php
@@ -1,26 +1,22 @@
 <?php
 /*************************************************************************************
- * ada.php
+ * parasail.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
- * Date Started: 2004/07/29
+ * 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.
  *
- * Ada language file for GeSHi.
  * Words are from SciTe configuration file
  *
  * CHANGES
  * -------
- * 2004/11/27 (1.0.2)
- *  -  Added support for multiple object splitters
- * 2004/10/27 (1.0.1)
- *   -  Removed apostrophe as string delimiter
- *   -  Added URL support
- * 2004/08/05 (1.0.0)
+ * 2012/08/02 (1.0.0)
  *   -  First Release
  *
- * TODO (updated 2004/11/27)
+ * TODO (updated 2012/08/02)
  * -------------------------
  *
  *************************************************************************************
@@ -44,33 +40,35 @@
  ************************************************************************************/
 
 $language_data = array (
-    'LANG_NAME' => 'Ada',
-    'COMMENT_SINGLE' => array(1 => '--'),
-    'COMMENT_MULTI' => 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(
-            'begin', 'declare', 'do', 'else', 'elsif', 'exception', 'for', 'if',
-            'is', 'loop', 'while', 'then', 'end', 'select', 'case', 'until',
-            'goto', 'return'
+            'all', 'block', 'case', 'continue', 'each',
+            'else', 'elsif', 'exit', 'for',
+            'forward', 'if', 'loop', 'return', 'reverse', 'some',
+            'then', 'until', 'while', 'with'
             ),
         2 => array(
-            'abs', 'and', 'at', 'mod', 'not', 'or', 'rem', 'xor'
+            'abs', 'and','in', 'mod', 'not', 'null', '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'
+            '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,

diff --git a/plugins/wp-syntax/geshi/geshi/parigp.php b/plugins/wp-syntax/geshi/geshi/parigp.php
new file mode 100644
index 0000000..c9c7309
--- /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 769566f..de5ca87 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 b0bd297..13a2e02 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 797bcab..c42ddb5 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 e66b52f..309ebd8 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 57b8514..706eabc 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 26cfdcf..818e11b 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 945ea8b..a4804b4 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 a7e8a58..2827457 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 776a86d..46d7ac9 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 bc2843b..743f711 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 8cf0529..7b29ee6 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 0000000..c299851
--- /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 1a9378c..09f90a2 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 c0decd0..662fdd7 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 a0939bb..c0ce35c 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 c694bdb..d3fcf61 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 37747af..bd78d73 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 0000000..330db4b
--- /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 3816e58..7990026 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 7488497..a106a4e 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 ba91639..e1317b2 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 d6aab00..1e735bd 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 c3cfc08..d78ffe9 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 0000000..ac2b34d
--- /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/python.php b/plugins/wp-syntax/geshi/geshi/pys60.php
similarity index 62%
copy from plugins/wp-syntax/geshi/geshi/python.php
copy to plugins/wp-syntax/geshi/geshi/pys60.php
index 0db4632..59c67fa 100644
--- a/plugins/wp-syntax/geshi/geshi/python.php
+++ b/plugins/wp-syntax/geshi/geshi/pys60.php
@@ -1,27 +1,23 @@
 <?php
-/*************************************************************************************
- * python.php
+/**************************************************************************************
+ * pys60.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.9
- * Date Started: 2004/08/30
+ * 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 language file for GeSHi.
+ * Python for S60 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
+ * No Changes Till Date
  *
- * TODO (updated 2004/11/27)
- * -------------------------
+ * 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
  *
  *************************************************************************************
  *
@@ -44,36 +40,35 @@
  ************************************************************************************/
 
 $language_data = array (
-    'LANG_NAME' => 'Python',
+    'LANG_NAME' => 'Python for S60',
     'COMMENT_SINGLE' => array(1 => '#'),
     'COMMENT_MULTI' => array(),
     'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
-    //Longest quotemarks ALWAYS first
-    'QUOTEMARKS' => array('"""', '"', "'"),
+    'QUOTEMARKS' => array('"', "'", '"""',"'''",'""','""'),
     'ESCAPE_CHAR' => '\\',
     'KEYWORDS' => array(
 
         /*
-        ** Set 1: reserved words
-        ** http://python.org/doc/current/ref/keywords.html
-        */
+         ** 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', 'with', 'as'
+            'import', 'pass', 'yield', 'def', 'finally', 'in', 'print', "<<", ">>", "as"
             ),
 
         /*
-        ** Set 2: builtins
-        ** http://python.org/doc/current/lib/built-in-funcs.html
-        */
+         ** 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', 'reversed', 'round', 'set', 'setattr', 'slice',
+            '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
@@ -88,16 +83,16 @@ $language_data = array (
             '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',
-            // other
-            'any', 'all'
+            'self'
             ),
 
         /*
-        ** Set 3: standard library
-        ** http://python.org/doc/current/lib/modindex.html
-        */
+         ** 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',
@@ -118,7 +113,7 @@ $language_data = array (
             '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', 'repr', 'resource', 'rexec', 'rfc822', 'rgbimg', 'rlcompleter',
+            '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',
@@ -128,26 +123,66 @@ $language_data = array (
             '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',
-            // Python 3.0
-            'bytes', 'bytearray'
+            '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
-        */
+         ** 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',
-            */
+            ///*
+            //// 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__',
@@ -170,12 +205,13 @@ $language_data = array (
             '__rshift__','__rsub__','__rmul__','__rand__','__rxor__','__ror__',
             '__sub__','__xor__'
             )
+
         ),
     'SYMBOLS' => array(
-            '(', ')', '[', ']', '{', '}', '*', '&', '%', '!', ';', '<', '>', '?', '`'
+        '(', ')', '[', ']', '{', '}', '*', '&', '%', '!', ';', '<', '>', '?', '`'
         ),
     'CASE_SENSITIVE' => array(
-        GESHI_COMMENTS => false,
+        GESHI_COMMENTS => true,
         1 => true,
         2 => true,
         3 => true,
@@ -183,32 +219,32 @@ $language_data = array (
         ),
     'STYLES' => array(
         'KEYWORDS' => array(
-            1 => 'color: #ff7700;font-weight:bold;',    // Reserved
-            2 => 'color: #008000;',                        // Built-ins + self
-            3 => 'color: #dc143c;',                        // Standard lib
-            4 => 'color: #0000cd;'                        // Special methods
+            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;',
+            1 => 'color: #808080; font-style:italic;font-size:92%',
             'MULTI' => 'color: #808080; font-style: italic;'
             ),
         'ESCAPE_CHAR' => array(
-            0 => 'color: #000099; font-weight: bold;'
+            0 => 'color: #930; font-weight: bold;font-size:105%'
             ),
         'BRACKETS' => array(
-            0 => 'color: black;'
+            0 => 'color: maroon;font-size:102%;padding:2px'
             ),
         'STRINGS' => array(
-            0 => 'color: #483d8b;'
+            0 => 'color: #666;'
             ),
         'NUMBERS' => array(
-            0 => 'color: #ff4500;'
+            0 => 'color: #2356F8;'
             ),
         'METHODS' => array(
-            1 => 'color: black;'
+            1 => 'color: navy;'
             ),
         'SYMBOLS' => array(
-            0 => 'color: #66cc66;'
+            0 => 'color: #66ccFF;'
             ),
         'REGEXPS' => array(
             ),

diff --git a/plugins/wp-syntax/geshi/geshi/python.php b/plugins/wp-syntax/geshi/geshi/python.php
index 0db4632..ec9b17e 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 fa3717c..ade9928 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 e7d12ff..3345e3c 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 1982c67..65ddee8 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 02ec8de..ea86c21 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 2e0dd33..157b2bd 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 0000000..b3cb932
--- /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 838eddb..0b75f71 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 7f2a8e5..fd6a561 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 ef09b23..e8a4e72 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 69e395e..f6eb1b1 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 ba1f85a..dbf95a1 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 58e7d23..405f59d 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 7258914..a84b908 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 b2636c7..f011497 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 9bb8058..381161f 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 f8b3016..5b61bad 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 1f9f021..86e9d44 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/ada.php b/plugins/wp-syntax/geshi/geshi/spark.php
similarity index 87%
copy from plugins/wp-syntax/geshi/geshi/ada.php
copy to plugins/wp-syntax/geshi/geshi/spark.php
index eb98c97..0284a1a 100644
--- a/plugins/wp-syntax/geshi/geshi/ada.php
+++ b/plugins/wp-syntax/geshi/geshi/spark.php
@@ -2,25 +2,22 @@
 /*************************************************************************************
  * ada.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
- * Date Started: 2004/07/29
+ * 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
  *
- * Ada language file for GeSHi.
+ * SPARK language file for GeSHi.
+ *
+ * Created by modifying Ada file version 1.0.2
  * Words are from SciTe configuration file
  *
  * CHANGES
  * -------
- * 2004/11/27 (1.0.2)
- *  -  Added support for multiple object splitters
- * 2004/10/27 (1.0.1)
- *   -  Removed apostrophe as string delimiter
- *   -  Added URL support
- * 2004/08/05 (1.0.0)
+ * 2010/08/28 (1.0.0)
  *   -  First Release
  *
- * TODO (updated 2004/11/27)
+ * TODO (updated 2010/08/22)
  * -------------------------
  *
  *************************************************************************************
@@ -44,8 +41,8 @@
  ************************************************************************************/
 
 $language_data = array (
-    'LANG_NAME' => 'Ada',
-    'COMMENT_SINGLE' => array(1 => '--'),
+    'LANG_NAME' => 'SPARK',
+    'COMMENT_SINGLE' => array(1 => '--', 2 => '--#'),
     'COMMENT_MULTI' => array('/*' => '*/'),
     'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
     'QUOTEMARKS' => array('"'),
@@ -89,7 +86,7 @@ $language_data = array (
             ),
         'COMMENTS' => array(
             1 => 'color: #adadad; font-style: italic;',
-            'MULTI' => 'color: #808080; font-style: italic;'
+            2 => 'color: #adadad; font-style: italic; font-weight: bold;'
             ),
         'ESCAPE_CHAR' => array(
             0 => 'color: #000099; font-weight: bold;'

diff --git a/plugins/wp-syntax/geshi/geshi/sparql.php b/plugins/wp-syntax/geshi/geshi/sparql.php
new file mode 100644
index 0000000..282165a
--- /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 4d1d519..4d08a51 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 0000000..2844e88
--- /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 c30b976..f2ba92b 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 64da1fe..4dd7be8 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 5b29c1e..f125642 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 259af41..87fb711 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 b41471b..f54959e 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 42e2ce2..b4bf6bd 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 c1e3806..6751aaa 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 839bc09..6fe62d0 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/c.php b/plugins/wp-syntax/geshi/geshi/upc.php
similarity index 59%
copy from plugins/wp-syntax/geshi/geshi/c.php
copy to plugins/wp-syntax/geshi/geshi/upc.php
index 1cdc24f..e053032 100644
--- a/plugins/wp-syntax/geshi/geshi/c.php
+++ b/plugins/wp-syntax/geshi/geshi/upc.php
@@ -1,38 +1,22 @@
 <?php
 /*************************************************************************************
- * c.php
+ * upc.php
  * -----
- * Author: Nigel McNie (nigel@geshi.org)
+ * 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.9
+ * Release Version: 1.0.8.11
  * Date Started: 2004/06/04
  *
- * C language file for GeSHi.
+ * UPC language file for GeSHi.
  *
  * CHANGES
  * -------
- * 2009/01/22 (1.0.8.3)
- *   -  Made keywords case-sensitive.
- * 2008/05/23 (1.0.7.22)
- *   -  Added description of extra language features (SF#1970248)
- * 2004/XX/XX (1.0.4)
- *   -  Added a couple of new keywords (Jack Lloyd)
- * 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 support for symbols
- * 2004/07/14 (1.0.0)
- *   -  First Release
- *
- * TODO (updated 2009/02/08)
- * -------------------------
- *  -  Get a list of inbuilt functions to add (and explore C more
- *     to complete this rather bare language file
+ * 2011/06/14 (1.0.8.11)
+ *   -  This file is a revision of c.php with UPC keywords added
  *
  *************************************************************************************
  *
@@ -55,7 +39,7 @@
  ************************************************************************************/
 
 $language_data = array (
-    'LANG_NAME' => 'C',
+    'LANG_NAME' => 'UPC',
     'COMMENT_SINGLE' => array(1 => '//', 2 => '#'),
     'COMMENT_MULTI' => array('/*' => '*/'),
     'COMMENT_REGEXP' => array(
@@ -86,13 +70,93 @@ $language_data = array (
     'KEYWORDS' => array(
         1 => array(
             'if', 'return', 'while', 'case', 'continue', 'default',
-            'do', 'else', 'for', 'switch', 'goto'
+            '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(
-            '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 +175,11 @@ $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',
+
+            'upc_lock_t', 'shared', 'strict', 'relaxed', 'upc_blocksizeof',
+            'upc_localsizeof', 'upc_elemsizeof'
             ),
         ),
     'SYMBOLS' => array(

diff --git a/plugins/wp-syntax/geshi/geshi/urbi.php b/plugins/wp-syntax/geshi/geshi/urbi.php
new file mode 100644
index 0000000..a7353ea
--- /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 0000000..58cdb8d
--- /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 1e4cece..acac57e 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 638da5e..528e7cd 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 0121f8d..758df98 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/pike.php b/plugins/wp-syntax/geshi/geshi/vedit.php
similarity index 76%
copy from plugins/wp-syntax/geshi/geshi/pike.php
copy to plugins/wp-syntax/geshi/geshi/vedit.php
index bc2843b..19b2bdb 100644
--- a/plugins/wp-syntax/geshi/geshi/pike.php
+++ b/plugins/wp-syntax/geshi/geshi/vedit.php
@@ -1,21 +1,22 @@
 <?php
 /*************************************************************************************
- * pike.php
+ * vedit.php
  * --------
- * Author: Rick E. (codeblock@eighthbit.net)
- * Copyright: (c) 2009 Rick E.
- * Release Version: 1.0.8.9
- * Date Started: 2009/12/10
+ * 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
  *
- * Pike language file for GeSHi.
+ * Vedit macro language language file for GeSHi.
  *
  * CHANGES
  * -------
- * 2009/12/25 (1.0.8.6)
+ * 2009/12/16 (1.0.8.11)
  *  -  First Release
  *
- * TODO (updated 2009/12/25)
+ * TODO (updated 2009/12/16)
  * -------------------------
+ * - Add keyword groups 2, 3 and 4.
  *
  *
  *************************************************************************************
@@ -39,28 +40,27 @@
  ************************************************************************************/
 
 $language_data = array(
-    'LANG_NAME' => 'Pike',
+    'LANG_NAME' => 'Vedit macro language',
     'COMMENT_SINGLE' => array(1 => '//'),
-    'COMMENT_MULTI' => array('/*' => '*/'),
+    'COMMENT_MULTI' => array(),
     'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
-    'QUOTEMARKS' => array('"'),
-    'ESCAPE_CHAR' => '\\',
+    'QUOTEMARKS' => array('"', '\''),
+    'ESCAPE_CHAR' => '',
     'KEYWORDS' => array(
         1 => array(
-            'goto', 'break', 'continue', 'return', 'case', 'default', 'if',
-            'else', 'switch', 'while', 'foreach', 'do', 'for', 'gauge',
-            'destruct', 'lambda', 'inherit', 'import', 'typeof', 'catch',
-            'inline', 'nomask', 'private', 'protected', 'public', 'static'
+            'break', 'breakout', 'break_out', 'continue', 'do', 'else', 'for',
+            'goto', 'if', 'repeat', 'return', 'while'
             )
         ),
     'SYMBOLS' => array(
         1 => array(
-            '(', ')', '{', '}', '[', ']', '+', '-', '*', '/', '%', '=', '!', '&', '|', '?', ';'
+            '(', ')', '{', '}', '[', ']', '+', '-', '*', '/', '%',
+            '=', '<', '>', '!', '^', '&', '|', '?', ':', ';', ','
             )
         ),
     'CASE_SENSITIVE' => array(
         GESHI_COMMENTS => false,
-        1 => true
+        1 => false
         ),
     'STYLES' => array(
         'KEYWORDS' => array(
@@ -92,12 +92,12 @@ $language_data = array(
         'SCRIPT' => array()
         ),
     'URLS' => array(1 => ''),
-    'OOLANG' => true,
-    'OBJECT_SPLITTERS' => 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 3c3c224..2bf66d1 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 386604c..a8f37e6 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 0d63ccd..fe7e5e0 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 a14bed8..123a3db 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 2182719..d36f1c6 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 91186d3..58f3963 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 24065ed..a89e473 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 a39d1de..3599a02 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 b30c02c..2edede3 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 e85a556..6354e45 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 388850d..99edc66 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 367a1c6..a06e277 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 0000000..a2974eb
--- /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 5ab146b..47326bb 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 430e5f6..b1de472 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 0000000..f7f6c73
--- /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 3d195ea..d3a95ff 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


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [gentoo-commits] proj/blogs-gentoo:master commit in: plugins/jetpack/modules/publicize/assets/rtl/, ...
@ 2013-08-01  6:51 Theo Chatzimichos
  0 siblings, 0 replies; 2+ messages in thread
From: Theo Chatzimichos @ 2013-08-01  6:51 UTC (permalink / raw
  To: gentoo-commits

commit:     c65f25a29edb6d47fa7d99a69c274f906b61adea
Author:     Theo Chatzimichos <tampakrap <AT> gentoo <DOT> org>
AuthorDate: Thu Aug  1 06:53:46 2013 +0000
Commit:     Theo Chatzimichos <tampakrap <AT> gentoo <DOT> org>
CommitDate: Thu Aug  1 06:53:46 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/blogs-gentoo.git;a=commit;h=c65f25a2

Update jetpack, akismet and wordpress-importer

---
 plugins/akismet/.htaccess                          |    5 +
 plugins/akismet/admin.php                          |  452 +-
 plugins/akismet/akismet.css                        |   13 +-
 plugins/akismet/akismet.js                         |   12 +
 plugins/akismet/akismet.php                        |    4 +-
 plugins/akismet/readme.txt                         |   11 +-
 plugins/jetpack/_inc/gallery-settings.js           |   15 +-
 plugins/jetpack/_inc/images/a8c.png                |  Bin 2058 -> 845 bytes
 .../jetpack/_inc/images/alertbox-closeicon-2x.png  |  Bin 515 -> 245 bytes
 plugins/jetpack/_inc/images/alertbox-closeicon.png |  Bin 437 -> 240 bytes
 plugins/jetpack/_inc/images/alertbox-clouds-2x.png |  Bin 2247 -> 1308 bytes
 plugins/jetpack/_inc/images/alertbox-clouds.png    |  Bin 1088 -> 640 bytes
 plugins/jetpack/_inc/images/arrow-2x.png           |  Bin 460 -> 267 bytes
 .../jetpack/_inc/images/arrow-pointer-blue-2x.png  |  Bin 3022 -> 2052 bytes
 plugins/jetpack/_inc/images/arrow.png              |  Bin 296 -> 173 bytes
 plugins/jetpack/_inc/images/arrows-2x.png          |  Bin 1371 -> 978 bytes
 plugins/jetpack/_inc/images/arrows-dark-2x.png     |  Bin 1416 -> 958 bytes
 plugins/jetpack/_inc/images/arrows-dark-vs-2x.png  |  Bin 1287 -> 1093 bytes
 plugins/jetpack/_inc/images/arrows-vs-2x.png       |  Bin 1213 -> 1079 bytes
 plugins/jetpack/_inc/images/atdbuttontr-2x.png     |  Bin 1840 -> 1598 bytes
 plugins/jetpack/_inc/images/automattic-2x.png      |  Bin 5902 -> 3851 bytes
 plugins/jetpack/_inc/images/automattic.png         |  Bin 3056 -> 1904 bytes
 plugins/jetpack/_inc/images/bubble_bg-2x.png       |  Bin 570 -> 532 bytes
 .../jetpack/_inc/images/comment-grey-bubble-2x.png |  Bin 256 -> 175 bytes
 plugins/jetpack/_inc/images/delete-2x.png          |  Bin 4009 -> 3687 bytes
 plugins/jetpack/_inc/images/footer-clouds-2x.png   |  Bin 63998 -> 57101 bytes
 plugins/jetpack/_inc/images/footer-clouds.png      |  Bin 23583 -> 20077 bytes
 plugins/jetpack/_inc/images/generic-2x.png         |  Bin 2166 -> 1826 bytes
 plugins/jetpack/_inc/images/header-clouds-2x.png   |  Bin 78134 -> 50373 bytes
 .../jetpack/_inc/images/header-clouds-small-2x.png |  Bin 29032 -> 18157 bytes
 .../jetpack/_inc/images/header-clouds-small.png    |  Bin 12781 -> 7969 bytes
 plugins/jetpack/_inc/images/header-clouds.png      |  Bin 30454 -> 18565 bytes
 plugins/jetpack/_inc/images/icon-comingsoon-2x.png |  Bin 3096 -> 1960 bytes
 plugins/jetpack/_inc/images/icon-comingsoon.png    |  Bin 1482 -> 896 bytes
 .../jetpack/_inc/images/icon-pointer-flag-2x.png   |  Bin 2427 -> 1747 bytes
 plugins/jetpack/_inc/images/image-2x.png           |  Bin 5414 -> 2671 bytes
 plugins/jetpack/_inc/images/imgedit-icons-2x.png   |  Bin 17070 -> 15590 bytes
 .../jetpack/_inc/images/jetpack-closebox-icon.png  |  Bin 388 -> 189 bytes
 plugins/jetpack/_inc/images/list-2x.png            |  Bin 2052 -> 2000 bytes
 plugins/jetpack/_inc/images/logo-2x.png            |  Bin 52802 -> 50369 bytes
 plugins/jetpack/_inc/images/logo-small-2x.png      |  Bin 28124 -> 27389 bytes
 plugins/jetpack/_inc/images/logo-small.png         |  Bin 11205 -> 10611 bytes
 plugins/jetpack/_inc/images/logo.png               |  Bin 22543 -> 21731 bytes
 plugins/jetpack/_inc/images/media-button-2x.png    |  Bin 1206 -> 875 bytes
 plugins/jetpack/_inc/images/menuicon-sprite-2x.png |  Bin 4456 -> 3688 bytes
 plugins/jetpack/_inc/images/menuicon-sprite.png    |  Bin 1652 -> 1351 bytes
 plugins/jetpack/_inc/images/module-clouds-2x.png   |  Bin 5942 -> 5375 bytes
 plugins/jetpack/_inc/images/module-clouds.png      |  Bin 2646 -> 2378 bytes
 .../jetpack/_inc/images/module-icons-sprite-2x.png |  Bin 72735 -> 59781 bytes
 .../jetpack/_inc/images/module-icons-sprite.png    |  Bin 31542 -> 28049 bytes
 plugins/jetpack/_inc/images/press-this-2x.png      |  Bin 887 -> 821 bytes
 plugins/jetpack/_inc/images/publicize.png          |  Bin 113219 -> 81768 bytes
 plugins/jetpack/_inc/images/rss/blue-large.png     |  Bin 1797 -> 1776 bytes
 plugins/jetpack/_inc/images/rss/blue-medium.png    |  Bin 1213 -> 1195 bytes
 plugins/jetpack/_inc/images/rss/blue-small.png     |  Bin 618 -> 597 bytes
 plugins/jetpack/_inc/images/rss/green-large.png    |  Bin 1665 -> 1644 bytes
 plugins/jetpack/_inc/images/rss/green-medium.png   |  Bin 1057 -> 1036 bytes
 plugins/jetpack/_inc/images/rss/green-small.png    |  Bin 549 -> 528 bytes
 plugins/jetpack/_inc/images/rss/orange-large.png   |  Bin 2570 -> 2545 bytes
 plugins/jetpack/_inc/images/rss/orange-medium.png  |  Bin 1718 -> 1697 bytes
 plugins/jetpack/_inc/images/rss/orange-small.png   |  Bin 712 -> 672 bytes
 plugins/jetpack/_inc/images/rss/pink-large.png     |  Bin 3639 -> 3617 bytes
 plugins/jetpack/_inc/images/rss/pink-medium.png    |  Bin 1574 -> 1553 bytes
 plugins/jetpack/_inc/images/rss/purple-large.png   |  Bin 3778 -> 3755 bytes
 plugins/jetpack/_inc/images/rss/purple-medium.png  |  Bin 1723 -> 1702 bytes
 plugins/jetpack/_inc/images/rss/purple-small.png   |  Bin 707 -> 651 bytes
 plugins/jetpack/_inc/images/rss/red-large.png      |  Bin 3618 -> 3595 bytes
 plugins/jetpack/_inc/images/rss/red-medium.png     |  Bin 1579 -> 1558 bytes
 plugins/jetpack/_inc/images/rss/red-small.png      |  Bin 675 -> 609 bytes
 plugins/jetpack/_inc/images/rss/silver-large.png   |  Bin 2141 -> 2120 bytes
 plugins/jetpack/_inc/images/rss/silver-medium.png  |  Bin 874 -> 853 bytes
 plugins/jetpack/_inc/images/rss/silver-small.png   |  Bin 355 -> 336 bytes
 .../_inc/images/screenshots/beautifulmath.png      |  Bin 45978 -> 41588 bytes
 .../jetpack/_inc/images/screenshots/carousel.png   |  Bin 361672 -> 345257 bytes
 .../jetpack/_inc/images/screenshots/comments.png   |  Bin 36696 -> 31650 bytes
 .../_inc/images/screenshots/contactform.png        |  Bin 40668 -> 33236 bytes
 .../jetpack/_inc/images/screenshots/custom-css.png |  Bin 43048 -> 25789 bytes
 .../jetpack/_inc/images/screenshots/hovercards.png |  Bin 105102 -> 103110 bytes
 plugins/jetpack/_inc/images/screenshots/likes.png  |  Bin 48953 -> 45802 bytes
 .../screenshots/mobile-push-notifications.jpg      |  Bin 29830 -> 29242 bytes
 plugins/jetpack/_inc/images/screenshots/notes.png  |  Bin 27450 -> 24032 bytes
 .../_inc/images/screenshots/post-by-email.png      |  Bin 28349 -> 25973 bytes
 .../jetpack/_inc/images/screenshots/publicize.png  |  Bin 113219 -> 81768 bytes
 .../jetpack/_inc/images/screenshots/sharing.png    |  Bin 36342 -> 35544 bytes
 .../jetpack/_inc/images/screenshots/shortcodes.png |  Bin 46029 -> 35980 bytes
 .../jetpack/_inc/images/screenshots/shortlinks.png |  Bin 54587 -> 52873 bytes
 .../jetpack/_inc/images/screenshots/spelling.png   |  Bin 59981 -> 56568 bytes
 plugins/jetpack/_inc/images/screenshots/stats.png  |  Bin 80732 -> 74882 bytes
 .../_inc/images/screenshots/subscriptions.png      |  Bin 52112 -> 43275 bytes
 .../_inc/images/screenshots/tiled-gallery.png      |  Bin 192182 -> 186121 bytes
 .../jetpack/_inc/images/screenshots/vaultpress.png |  Bin 45517 -> 39774 bytes
 .../jetpack/_inc/images/screenshots/widgets.png    |  Bin 107072 -> 106129 bytes
 plugins/jetpack/_inc/images/stars-2x.png           |  Bin 1388 -> 1022 bytes
 plugins/jetpack/_inc/images/status-light-2x.png    |  Bin 2309 -> 1771 bytes
 plugins/jetpack/_inc/images/status-light.png       |  Bin 1006 -> 703 bytes
 plugins/jetpack/_inc/images/tb-close-2x.png        |  Bin 337 -> 197 bytes
 plugins/jetpack/_inc/jetpack-retina.css            |  191 +-
 plugins/jetpack/_inc/jetpack-rtl.css               |  238 +-
 plugins/jetpack/_inc/jetpack.css                   | 1728 +++--
 plugins/jetpack/_inc/jetpack.js                    |    1 +
 plugins/jetpack/_inc/jquery.inview.js              |    8 +-
 plugins/jetpack/_inc/jquery.jetpack-resize.js      |   17 +-
 plugins/jetpack/_inc/jquery.spin.js                |  180 +-
 plugins/jetpack/_inc/postmessage.js                |    6 +-
 plugins/jetpack/_inc/spin.js                       |  642 +-
 plugins/jetpack/class.jetpack-ixr-client.php       |    2 +-
 plugins/jetpack/class.jetpack-post-images.php      |   32 +-
 plugins/jetpack/class.jetpack-signature.php        |    4 +-
 plugins/jetpack/class.jetpack-user-agent.php       |  158 +-
 plugins/jetpack/class.jetpack-xmlrpc-server.php    |    6 +-
 plugins/jetpack/class.json-api-endpoints.php       |  466 +-
 plugins/jetpack/class.json-api.php                 |   81 +-
 plugins/jetpack/class.photon.php                   |    6 +-
 plugins/jetpack/functions.gallery.php              |    9 +-
 plugins/jetpack/functions.opengraph.php            |   24 +-
 plugins/jetpack/functions.photon.php               |    4 +-
 plugins/jetpack/jetpack.php                        | 4488 +----------
 plugins/jetpack/languages/jetpack-ar.mo            |  Bin 14004 -> 132582 bytes
 plugins/jetpack/languages/jetpack-az.mo            |  Bin 2886 -> 3077 bytes
 plugins/jetpack/languages/jetpack-bs_BA.mo         |  Bin 76528 -> 76232 bytes
 plugins/jetpack/languages/jetpack-ca.mo            |  Bin 76602 -> 79877 bytes
 plugins/jetpack/languages/jetpack-cs_CZ.mo         |  Bin 8242 -> 8967 bytes
 plugins/jetpack/languages/jetpack-da_DK.mo         |  Bin 44830 -> 44531 bytes
 plugins/jetpack/languages/jetpack-de_DE.mo         |  Bin 117625 -> 123046 bytes
 plugins/jetpack/languages/jetpack-el.mo            |  Bin 8337 -> 12312 bytes
 plugins/jetpack/languages/jetpack-es_ES.mo         |  Bin 49121 -> 73672 bytes
 plugins/jetpack/languages/jetpack-fa_IR.mo         |  Bin 47862 -> 58196 bytes
 plugins/jetpack/languages/jetpack-fi.mo            |  Bin 27526 -> 28822 bytes
 plugins/jetpack/languages/jetpack-fr_FR.mo         |  Bin 113684 -> 127742 bytes
 plugins/jetpack/languages/jetpack-gl_ES.mo         |  Bin 33955 -> 34697 bytes
 plugins/jetpack/languages/jetpack-he_IL.mo         |  Bin 75590 -> 75006 bytes
 plugins/jetpack/languages/jetpack-hr.mo            |  Bin 35895 -> 36776 bytes
 plugins/jetpack/languages/jetpack-hu_HU.mo         |  Bin 77710 -> 99073 bytes
 plugins/jetpack/languages/jetpack-id_ID.mo         |  Bin 52347 -> 51973 bytes
 plugins/jetpack/languages/jetpack-it_IT.mo         |  Bin 50000 -> 62055 bytes
 plugins/jetpack/languages/jetpack-ja.mo            |  Bin 116549 -> 131786 bytes
 plugins/jetpack/languages/jetpack-ko_KR.mo         |  Bin 110462 -> 121971 bytes
 plugins/jetpack/languages/jetpack-lt_LT.mo         |  Bin 12440 -> 14165 bytes
 plugins/jetpack/languages/jetpack-mk_MK.mo         |  Bin 23594 -> 24002 bytes
 plugins/jetpack/languages/jetpack-my_MM.mo         |  Bin 11071 -> 12429 bytes
 plugins/jetpack/languages/jetpack-nb_NO.mo         |  Bin 88203 -> 96717 bytes
 plugins/jetpack/languages/jetpack-nl_NL.mo         |  Bin 38043 -> 38431 bytes
 plugins/jetpack/languages/jetpack-nn_NO.mo         |  Bin 14701 -> 16249 bytes
 plugins/jetpack/languages/jetpack-pl_PL.mo         |  Bin 11997 -> 19309 bytes
 plugins/jetpack/languages/jetpack-pt_BR.mo         |  Bin 107473 -> 110039 bytes
 plugins/jetpack/languages/jetpack-pt_PT.mo         |  Bin 46165 -> 46473 bytes
 plugins/jetpack/languages/jetpack-ro_RO.mo         |  Bin 10652 -> 11212 bytes
 plugins/jetpack/languages/jetpack-ru_RU.mo         |  Bin 49300 -> 49671 bytes
 plugins/jetpack/languages/jetpack-sa_IN.mo         |  Bin 1006 -> 1006 bytes
 plugins/jetpack/languages/jetpack-sk_SK.mo         |  Bin 10517 -> 11359 bytes
 plugins/jetpack/languages/jetpack-sq.mo            |  Bin 112583 -> 111067 bytes
 plugins/jetpack/languages/jetpack-sr_RS.mo         |  Bin 44079 -> 54018 bytes
 plugins/jetpack/languages/jetpack-sv_SE.mo         |  Bin 24534 -> 33308 bytes
 plugins/jetpack/languages/jetpack-th.mo            |  Bin 18421 -> 20113 bytes
 plugins/jetpack/languages/jetpack-tr_TR.mo         |  Bin 35311 -> 36876 bytes
 plugins/jetpack/languages/jetpack-zh_CN.mo         |  Bin 7637 -> 8477 bytes
 plugins/jetpack/languages/jetpack-zh_TW.mo         |  Bin 93742 -> 91924 bytes
 plugins/jetpack/locales.php                        |   10 +-
 plugins/jetpack/modules/after-the-deadline.php     |   35 +-
 .../after-the-deadline/atd-autoproofread.js        |    6 +-
 .../after-the-deadline/atd-nonvis-editor-plugin.js |   20 +-
 .../jetpack/modules/after-the-deadline/atd.core.js |   58 +-
 plugins/jetpack/modules/after-the-deadline/atd.css |   32 +-
 .../modules/after-the-deadline/config-options.php  |   26 +-
 .../modules/after-the-deadline/config-unignore.php |   10 +-
 .../modules/after-the-deadline/install_atd_l10n.js |    4 +-
 .../modules/after-the-deadline/jquery.atd.js       |   44 +-
 .../jetpack/modules/after-the-deadline/proxy.php   |    8 +-
 .../after-the-deadline/tinymce/editor_plugin.js    |  126 +-
 plugins/jetpack/modules/carousel.php               |    1 +
 .../jetpack/modules/carousel/jetpack-carousel.css  |   34 +-
 .../jetpack/modules/carousel/jetpack-carousel.js   |  209 +-
 .../jetpack/modules/carousel/jetpack-carousel.php  |   69 +-
 .../modules/carousel/rtl/jetpack-carousel-rtl.css  |   36 +-
 plugins/jetpack/modules/comments.php               |    1 +
 plugins/jetpack/modules/comments/admin.php         |    2 +-
 plugins/jetpack/modules/comments/base.php          |   14 +-
 plugins/jetpack/modules/comments/comments.php      |   19 +-
 plugins/jetpack/modules/contact-form.php           |    3 +-
 plugins/jetpack/modules/contact-form/admin.php     |   47 +-
 .../jetpack/modules/contact-form/css/grunion.css   |    4 +-
 .../modules/contact-form/grunion-contact-form.php  |  414 +-
 .../modules/contact-form/grunion-form-view.php     |   22 +-
 plugins/jetpack/modules/contact-form/js/grunion.js |   34 +-
 plugins/jetpack/modules/custom-css.php             |    1 +
 .../modules/custom-css/csstidy/class.csstidy.php   |    7 +-
 .../custom-css/csstidy/class.csstidy_optimise.php  |    9 +-
 .../custom-css/csstidy/class.csstidy_print.php     |    4 +-
 .../modules/custom-css/csstidy/data-wp.inc.php     |    8 +
 .../modules/custom-css/csstidy/data.inc.php        |    4 +-
 .../modules/custom-css/csstidy/lang.inc.php        |    8 +-
 plugins/jetpack/modules/custom-css/custom-css.php  |  425 +-
 .../modules/custom-css/custom-css/js/ace/ace.js    |    1 -
 .../custom-css/custom-css/js/ace/worker-css.js     | 7887 +++++++++++++++++++-
 .../custom-css/custom-css/js/safecss-ace.js        |   53 +-
 .../custom-css/custom-css/preprocessors.php        |    2 +-
 plugins/jetpack/modules/enhanced-distribution.php  |    1 +
 .../modules/featured-content/featured-content.php  |    6 +-
 plugins/jetpack/modules/gravatar-hovercards.php    |   11 +-
 plugins/jetpack/modules/holiday-snow.php           |    1 +
 plugins/jetpack/modules/infinite-scroll.php        |    1 +
 .../jetpack/modules/infinite-scroll/infinity.css   |    5 +-
 .../jetpack/modules/infinite-scroll/infinity.js    |    9 +-
 .../jetpack/modules/infinite-scroll/infinity.php   |  134 +-
 plugins/jetpack/modules/json-api.php               |    1 +
 plugins/jetpack/modules/latex.php                  |    1 +
 plugins/jetpack/modules/likes.php                  |  214 +-
 plugins/jetpack/modules/likes/style.css            |   19 +-
 plugins/jetpack/modules/minileven.php              |    1 +
 plugins/jetpack/modules/minileven/minileven.php    |   17 +
 .../theme/pub/minileven/content-gallery.php        |    4 +-
 .../minileven/theme/pub/minileven/content.php      |   13 +-
 .../minileven/theme/pub/minileven/footer.php       |    2 -
 .../minileven/theme/pub/minileven/functions.php    |   56 +-
 .../minileven/theme/pub/minileven/header.php       |   20 +-
 .../minileven/theme/pub/minileven/image.php        |    2 +-
 .../theme/pub/minileven/inc/custom-header.php      |   36 +-
 .../theme/pub/minileven/inc/template-tags.php      |    5 +-
 .../minileven/theme/pub/minileven/inc/tweaks.php   |   22 +-
 .../minileven/theme/pub/minileven/index.php        |    2 +
 .../minileven/theme/pub/minileven/js/small-menu.js |   64 +-
 .../minileven/theme/pub/minileven/style.css        |  624 +-
 plugins/jetpack/modules/mobile-push.php            |    3 +-
 plugins/jetpack/modules/module-extras.php          |    2 +
 plugins/jetpack/modules/module-info.php            |   48 +-
 plugins/jetpack/modules/notes.php                  |   82 +-
 plugins/jetpack/modules/photon.php                 |    1 +
 plugins/jetpack/modules/post-by-email.php          |    5 +-
 .../jetpack/modules/post-by-email/post-by-email.js |    2 +-
 plugins/jetpack/modules/publicize.php              |    1 +
 .../jetpack/modules/publicize/assets/publicize.css |    5 +-
 .../jetpack/modules/publicize/assets/publicize.js  |    2 +-
 .../modules/publicize/assets/rtl/publicize-rtl.css |    7 +-
 .../modules/publicize/publicize-jetpack.php        |   93 +-
 plugins/jetpack/modules/publicize/publicize.php    |   45 +-
 plugins/jetpack/modules/publicize/ui.php           |   39 +-
 plugins/jetpack/modules/sharedaddy.php             |    3 +-
 .../jetpack/modules/sharedaddy/admin-sharing.css   |   46 +-
 .../jetpack/modules/sharedaddy/admin-sharing.js    |  108 +-
 .../jetpack/modules/sharedaddy/images/facebook.png |  Bin 838 -> 568 bytes
 .../modules/sharedaddy/images/facebook@2x.png      |  Bin 1533 -> 1036 bytes
 .../modules/sharedaddy/images/googleplus1.png      |  Bin 574 -> 722 bytes
 .../modules/sharedaddy/images/googleplus1@2x.png   |  Bin 1815 -> 1333 bytes
 .../modules/sharedaddy/images/icon-facebook-2x.png |  Bin 671 -> 1036 bytes
 .../modules/sharedaddy/images/icon-facebook.png    |  Bin 887 -> 568 bytes
 .../jetpack/modules/sharedaddy/recaptchalib.php    |   14 +-
 plugins/jetpack/modules/sharedaddy/sharedaddy.php  |    6 +-
 .../jetpack/modules/sharedaddy/sharing-service.php |   42 +-
 .../jetpack/modules/sharedaddy/sharing-sources.php |   91 +-
 plugins/jetpack/modules/sharedaddy/sharing.css     |   71 +-
 plugins/jetpack/modules/sharedaddy/sharing.js      |   11 +-
 plugins/jetpack/modules/sharedaddy/sharing.php     |    1 -
 plugins/jetpack/modules/shortcodes.php             |   35 +-
 plugins/jetpack/modules/shortcodes/archives.php    |    2 +-
 plugins/jetpack/modules/shortcodes/audio.php       |   31 +-
 plugins/jetpack/modules/shortcodes/blip.php        |    6 +-
 .../shortcodes/css/rtl/slideshow-shortcode-rtl.css |    4 +-
 .../modules/shortcodes/css/slideshow-shortcode.css |    2 +
 plugins/jetpack/modules/shortcodes/dailymotion.php |   32 +-
 plugins/jetpack/modules/shortcodes/diggthis.php    |   14 +-
 plugins/jetpack/modules/shortcodes/flickr.php      |   10 +-
 plugins/jetpack/modules/shortcodes/googlemaps.php  |    4 +
 plugins/jetpack/modules/shortcodes/googlevideo.php |    4 +-
 .../modules/shortcodes/js/audio-shortcode.js       |   12 +-
 .../jetpack/modules/shortcodes/js/jquery.cycle.js  |   40 +-
 plugins/jetpack/modules/shortcodes/polldaddy.php   |  168 +-
 plugins/jetpack/modules/shortcodes/slideshare.php  |    4 +-
 plugins/jetpack/modules/shortcodes/slideshow.php   |    2 +-
 plugins/jetpack/modules/shortcodes/ted.php         |    4 +
 plugins/jetpack/modules/shortcodes/videopress.php  |   18 +-
 plugins/jetpack/modules/shortcodes/vimeo.php       |   27 +-
 plugins/jetpack/modules/shortcodes/youtube.php     |   43 +-
 plugins/jetpack/modules/shortlinks.php             |    1 +
 plugins/jetpack/modules/stats.php                  |   73 +-
 plugins/jetpack/modules/subscriptions.php          |   53 +-
 plugins/jetpack/modules/tiled-gallery.php          |    1 +
 .../math/class-constrained-array-rounding.php      |    6 +-
 .../modules/tiled-gallery/tiled-gallery.php        |   34 +-
 .../tiled-gallery/rtl/tiled-gallery-rtl.css        |   15 +-
 .../tiled-gallery/tiled-gallery/tiled-gallery.css  |   12 +-
 .../tiled-gallery/tiled-gallery/tiled-gallery.js   |   15 +-
 plugins/jetpack/modules/vaultpress.php             |    5 +-
 plugins/jetpack/modules/widgets.php                |   11 +-
 .../jetpack/modules/widgets/facebook-likebox.php   |   78 +-
 .../jetpack/modules/widgets/gravatar-profile.css   |    2 +-
 plugins/jetpack/modules/widgets/readmill.php       |    2 +-
 .../jetpack/modules/widgets/rsslinks-widget.php    |    2 +-
 plugins/jetpack/modules/widgets/top-posts.php      |   16 +-
 plugins/jetpack/readme.txt                         |  210 +-
 plugins/wordpress-importer/parsers.php             |   19 +-
 plugins/wordpress-importer/readme.txt              |    6 +-
 plugins/wordpress-importer/wordpress-importer.php  |   40 +-
 292 files changed, 13632 insertions(+), 7930 deletions(-)

diff --git a/plugins/akismet/.htaccess b/plugins/akismet/.htaccess
index 18eed64..cfad468 100644
--- a/plugins/akismet/.htaccess
+++ b/plugins/akismet/.htaccess
@@ -3,4 +3,9 @@ Deny from all
 
 <FilesMatch "^akismet\.(css|js)$">
 	Allow from all
+</FilesMatch>
+
+#allow access to any image
+<FilesMatch "^(.+)\.(png|gif)$">
+	Allow from all
 </FilesMatch>
\ No newline at end of file

diff --git a/plugins/akismet/admin.php b/plugins/akismet/admin.php
index 9d7673f..481b0f3 100644
--- a/plugins/akismet/admin.php
+++ b/plugins/akismet/admin.php
@@ -10,9 +10,9 @@ function akismet_admin_init() {
     if ( !function_exists('is_multisite') && version_compare( $wp_version, '3.0', '<' ) ) {
         
         function akismet_version_warning() {
-            echo "
-            <div id='akismet-warning' class='updated fade'><p><strong>".sprintf(__('Akismet %s requires WordPress 3.0 or higher.'), AKISMET_VERSION) ."</strong> ".sprintf(__('Please <a href="%s">upgrade WordPress</a> to a current version, or <a href="%s">downgrade to version 2.4 of the Akismet plugin</a>.'), 'http://codex.wordpress.org/Upgrading_WordPress', 'http://wordpress.org/extend/plugins/akismet/download/'). "</p></div>
-            ";
+            echo '
+            <div id="akismet-warning" class="updated fade"><p><strong>'.sprintf(__('Akismet %s requires WordPress 3.0 or higher.'), AKISMET_VERSION) .'</strong> '.sprintf(__('Please <a href="%s">upgrade WordPress</a> to a current version, or <a href="%s">downgrade to version 2.4 of the Akismet plugin</a>.'), 'http://codex.wordpress.org/Upgrading_WordPress', 'http://wordpress.org/extend/plugins/akismet/download/'). '</p></div>
+            ';
         }
         add_action('admin_notices', 'akismet_version_warning'); 
         
@@ -31,13 +31,14 @@ add_action( 'admin_enqueue_scripts', 'akismet_load_js_and_css' );
 function akismet_load_js_and_css() {
 	global $hook_suffix;
 
-	if (
-		$hook_suffix == 'index.php'	# dashboard
-		|| $hook_suffix == 'edit-comments.php' 
-		|| $hook_suffix == 'comment.php' 
-		|| $hook_suffix == 'post.php' 
-		|| $hook_suffix == 'plugins_page_akismet-key-config'
-	) {
+	if ( in_array( $hook_suffix, array( 
+		'index.php', # dashboard
+		'edit-comments.php',
+		'comment.php',
+		'post.php',
+		'plugins_page_akismet-key-config', 
+		'jetpack_page_akismet-key-config',
+	) ) ) {
 		wp_register_style( 'akismet.css', AKISMET_PLUGIN_URL . 'akismet.css', array(), '2.5.4.4' );
 		wp_enqueue_style( 'akismet.css');
 	
@@ -64,35 +65,51 @@ function akismet_plugin_action_links( $links, $file ) {
 add_filter( 'plugin_action_links', 'akismet_plugin_action_links', 10, 2 );
 
 function akismet_conf() {
-	global $akismet_nonce, $wpcom_api_key;
+	global $akismet_nonce, $current_user;
+	
+	$new_key_link  = 'https://akismet.com/get/';
+	$api_key       = akismet_get_key();
+	$show_key_form = $api_key;
+	$key_status    = 'empty';
+	$saved_ok      = false;
+	
+	$ms = array();
 
-	if ( isset($_POST['submit']) ) {
+	if ( isset( $_POST['submit'] ) ) {
 		if ( function_exists('current_user_can') && !current_user_can('manage_options') )
 			die(__('Cheatin&#8217; uh?'));
+			
+		$show_key_form = true;
 
 		check_admin_referer( $akismet_nonce );
-		$key = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
+		$key      = preg_replace( '/[^a-h0-9]/i', '', $_POST['key'] );
 		$home_url = parse_url( get_bloginfo('url') );
-
-		if ( empty($key) ) {
-			$key_status = 'empty';
-			$ms[] = 'new_key_empty';
-			delete_option('wordpress_api_key');
-		} elseif ( empty($home_url['host']) ) {
-			$key_status = 'empty';
+		
+		if ( empty( $home_url['host'] ) )
 			$ms[] = 'bad_home_url';
-		} else {
+
+		if ( empty( $key ) ) {
+			if ( $api_key ) {
+				delete_option('wordpress_api_key');
+				$saved_ok = true;			
+				$ms[] = 'new_key_empty';
+			}
+			else
+				$ms[] = 'key_empty';
+		}  
+		else
 			$key_status = akismet_verify_key( $key );
-		}
 
-		if ( $key_status == 'valid' ) {
+		if ( $key != $api_key && $key_status == 'valid' ) {
 			update_option('wordpress_api_key', $key);
 			$ms[] = 'new_key_valid';
-		} else if ( $key_status == 'invalid' ) {
+		}
+		elseif ( $key_status == 'invalid' )
 			$ms[] = 'new_key_invalid';
-		} else if ( $key_status == 'failed' ) {
+		elseif ( $key_status == 'failed' )
 			$ms[] = 'new_key_failed';
-		}
+			
+		$api_key = $key_status == 'valid' ? $key : false;
 
 		if ( isset( $_POST['akismet_discard_month'] ) )
 			update_option( 'akismet_discard_month', 'true' );
@@ -103,157 +120,197 @@ function akismet_conf() {
 			update_option( 'akismet_show_user_comments_approved', 'true' );
 		else
 			update_option( 'akismet_show_user_comments_approved', 'false' );
+			
+		if ( empty( $ms ) )
+			$saved_ok = true;
 
-	} elseif ( isset($_POST['check']) ) {
+	} 
+	elseif ( isset( $_POST['check'] ) ) {
+		$show_key_form = true;
+		check_admin_referer( $akismet_nonce );
 		akismet_get_server_connectivity(0);
 	}
-
-	if ( empty( $key_status) ||  $key_status != 'valid' ) {
-		$key = get_option('wordpress_api_key');
-		if ( empty( $key ) ) {
-			if ( empty( $key_status ) || $key_status != 'failed' ) {
-				if ( akismet_verify_key( '1234567890ab' ) == 'failed' )
-					$ms[] = 'no_connection';
-				else
-					$ms[] = 'key_empty';
-			}
-			$key_status = 'empty';
-		} else {
-			$key_status = akismet_verify_key( $key );
+	
+	if ( $show_key_form ) {
+		//check current key status
+		//only get this if showing the key form otherwise takes longer for page to load for new user
+		//no need to get it if we already know it and its valid
+		if ( in_array( $key_status, array( 'invalid', 'failed', 'empty' ) ) ) {
+			$key = get_option('wordpress_api_key');
+			if ( empty( $key ) ) {
+				//no key saved yet - maybe connection to Akismet down?
+				if ( in_array( $key_status, array( 'invalid', 'empty' ) ) ) {
+					if ( akismet_verify_key( '1234567890ab' ) == 'failed' )
+						$ms[] = 'no_connection';
+				}
+			} 
+			else
+				$key_status = akismet_verify_key( $key );			
 		}
-		if ( $key_status == 'valid' ) {
-			$ms[] = 'key_valid';
-		} else if ( $key_status == 'invalid' ) {
-			$ms[] = 'key_invalid';
-		} else if ( !empty($key) && $key_status == 'failed' ) {
-			$ms[] = 'key_failed';
+		
+		if ( !isset( $_POST['submit'] ) ) {
+			if ( $key_status == 'invalid' )
+				$ms[] = 'key_invalid';
+			elseif ( !empty( $key ) && $key_status == 'failed' )
+				$ms[] = 'key_failed';
 		}
 	}
 
 	$messages = array(
-		'new_key_empty' => array('color' => 'aa0', 'text' => __('Your key has been cleared.')),
-		'new_key_valid' => array('color' => '4AB915', 'text' => __('Your key has been verified. Happy blogging!')),
-		'new_key_invalid' => array('color' => '888', 'text' => __('The key you entered is invalid. Please double-check it.')),
-		'new_key_failed' => array('color' => '888', 'text' => __('The key you entered could not be verified because a connection to akismet.com could not be established. Please check your server configuration.')),
-		'no_connection' => array('color' => '888', 'text' => __('There was a problem connecting to the Akismet server. Please check your server configuration.')),
-		'key_empty' => array('color' => 'aa0', 'text' => sprintf(__('Please enter an API key. (<a href="%s" style="color:#fff">Get your key.</a>)'), 'http://akismet.com/get/?return=true')),
-		'key_valid' => array('color' => '4AB915', 'text' => __('This key is valid.')),
-		'key_invalid' => array('color' => '888', 'text' => __('This key is invalid.')),
-		'key_failed' => array('color' => 'aa0', 'text' => __('The key below was previously validated but a connection to akismet.com can not be established at this time. Please check your server configuration.')),
-		'bad_home_url' => array('color' => '888', 'text' => sprintf( __('Your WordPress home URL %s is invalid.  Please fix the <a href="%s">home option</a>.'), esc_html( get_bloginfo('url') ), admin_url('options.php#home') ) ),
+		'new_key_empty'   => array( 'class' => 'updated fade', 'text' => __('Your key has been cleared.' ) ),
+		'new_key_valid'   => array( 'class' => 'updated fade', 'text' => __('Your Akismet account has been successfully set up and activated. Happy blogging!' ) ),
+		'new_key_invalid' => array( 'class' => 'error',        'text' => __('The key you entered is invalid. Please double-check it.' ) ),
+		'new_key_failed'  => array( 'class' => 'error',        'text' => __('The key you entered could not be verified because a connection to akismet.com could not be established. Please check your server configuration.' ) ),
+		'no_connection'   => array( 'class' => 'error',        'text' => __('There was a problem connecting to the Akismet server. Please check your server configuration.' ) ),
+		'key_empty'       => array( 'class' => 'updated fade', 'text' => __('Please enter an API key' ) ),
+		'key_invalid'     => array( 'class' => 'error',        'text' => __('This key is invalid.' ) ),
+		'key_failed'      => array( 'class' => 'error',        'text' => __('The key below was previously validated but a connection to akismet.com can not be established at this time. Please check your server configuration.' ) ),
+		'bad_home_url'    => array( 'class' => 'error',        'text' => sprintf( __('Your WordPress home URL %s is invalid.  Please fix the <a href="%s">home option</a>.'), esc_html( get_bloginfo('url') ), admin_url('options.php#home') ) )
 	);
 ?>
-<?php if ( !empty($_POST['submit'] ) ) : ?>
-<div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
-<?php endif; ?>
+
+
 <div class="wrap">
-<h2><?php _e('Akismet Configuration'); ?></h2>
-<?php if (isset($_GET['message']) && $_GET['message'] == 'success') { ?>
-	<div class="updated below-h2" id="message"><p><?php _e( '<strong>Sign up success!</strong> Please check your email for your Akismet API Key and enter it below.' ); ?></p></div>
-<?php } ?>
-<div class="narrow">
-<form action="" method="post" id="akismet-conf" style="margin: auto; width: 400px; ">
-<?php if ( !$wpcom_api_key ) { ?>
-	<p><?php printf(__('For many people, <a href="%1$s">Akismet</a> will greatly reduce or even completely eliminate the comment and trackback spam you get on your site. If one does happen to get through, simply mark it as "spam" on the moderation screen and Akismet will learn from the mistakes. If you don\'t have an API key yet, you can get one at <a href="%2$s">Akismet.com</a>.'), 'http://akismet.com/?return=true', 'http://akismet.com/get/?return=true'); ?></p>
-
-<h3><label for="key"><?php _e('Akismet API Key'); ?></label></h3>
-<?php foreach ( $ms as $m ) : ?>
-	<p style="padding: .5em; background-color: #<?php echo $messages[$m]['color']; ?>; color: #fff; font-weight: bold;"><?php echo $messages[$m]['text']; ?></p>
-<?php endforeach; ?>
-<p><input id="key" name="key" type="text" size="15" maxlength="12" value="<?php echo get_option('wordpress_api_key'); ?>" style="font-family: 'Courier New', Courier, mono; font-size: 1.5em;" /> (<?php _e('<a href="http://akismet.com/get/?return=true">What is this?</a>'); ?>)</p>
-<?php if ( isset( $invalid_key) && $invalid_key ) { ?>
-<h3><?php _e('Why might my key be invalid?'); ?></h3>
-<p><?php _e('This can mean one of two things, either you copied the key wrong or that the plugin is unable to reach the Akismet servers, which is most often caused by an issue with your web host around firewalls or similar.'); ?></p>
-<?php } ?>
-<?php } ?>
-<?php akismet_nonce_field($akismet_nonce) ?>
-<p><label><input name="akismet_discard_month" id="akismet_discard_month" value="true" type="checkbox" <?php if ( get_option('akismet_discard_month') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Auto-delete spam submitted on posts more than a month old.'); ?></label></p>
-<p><label><input name="akismet_show_user_comments_approved" id="akismet_show_user_comments_approved" value="true" type="checkbox" <?php if ( get_option('akismet_show_user_comments_approved') == 'true' ) echo ' checked="checked" '; ?> /> <?php _e('Show the number of comments you\'ve approved beside each comment author.'); ?></label></p>
-	<p class="submit"><input type="submit" name="submit" value="<?php _e('Update options &raquo;'); ?>" /></p>
-</form>
-
-<form action="" method="post" id="akismet-connectivity" style="margin: auto; width: 400px; ">
-
-<h3><?php _e('Server Connectivity'); ?></h3>
-<?php
-	if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) {
-		?>
-			<p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Network functions are disabled.'); ?></p>
-			<p><?php echo sprintf( __('Your web host or server administrator has disabled PHP\'s <code>fsockopen</code> or <code>gethostbynamel</code> functions.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet\'s system requirements</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
-		<?php
-	} else {
-		$servers = akismet_get_server_connectivity();
-		$fail_count = count($servers) - count( array_filter($servers) );
-		if ( is_array($servers) && count($servers) > 0 ) {
-			// some connections work, some fail
-			if ( $fail_count > 0 && $fail_count < count($servers) ) { ?>
-				<p style="padding: .5em; background-color: #aa0; color: #fff; font-weight:bold;"><?php _e('Unable to reach some Akismet servers.'); ?></p>
-				<p><?php echo sprintf( __('A network problem or firewall is blocking some connections from your web server to Akismet.com.  Akismet is working but this may cause problems during times of network congestion.  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
-			<?php
-			// all connections fail
-			} elseif ( $fail_count > 0 ) { ?>
-				<p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Unable to reach any Akismet servers.'); ?></p>
-				<p><?php echo sprintf( __('A network problem or firewall is blocking all connections from your web server to Akismet.com.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
-			<?php
-			// all connections work
-			} else { ?>
-				<p style="padding: .5em; background-color: #4AB915; color: #fff; font-weight:bold;"><?php  _e('All Akismet servers are available.'); ?></p>
-				<p><?php _e('Akismet is working correctly.  All servers are accessible.'); ?></p>
-			<?php
-			}
-		} else {
-			?>
-				<p style="padding: .5em; background-color: #888; color: #fff; font-weight:bold;"><?php _e('Unable to find Akismet servers.'); ?></p>
-				<p><?php echo sprintf( __('A DNS problem or firewall is preventing all access from your web server to Akismet.com.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
-			<?php
-		}
-	}
-	
-	if ( !empty($servers) ) {
-?>
-<table style="width: 100%;">
-<thead><th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th></thead>
-<tbody>
-<?php
-		asort($servers);
-		foreach ( $servers as $ip => $status ) {
-			$color = ( $status ? '#4AB915' : '#888');
-	?>
-		<tr>
-		<td><?php echo htmlspecialchars($ip); ?></td>
-		<td style="padding: 0 .5em; font-weight:bold; color: #fff; background-color: <?php echo $color; ?>"><?php echo ($status ? __('Accessible') : __('Re-trying') ); ?></td>
+	<?php if ( !$api_key ) : ?>
+	<h2 class="ak-header"><?php _e('Akismet'); ?></h2>
+	<?php else: ?>
+	<h2 class="ak-header"><?php printf( __( 'Akismet <a href="%s" class="add-new-h2">Stats</a>' ), esc_url( add_query_arg( array( 'page' => 'akismet-stats-display' ), class_exists( 'Jetpack' ) ? admin_url( 'admin.php' ) : admin_url( 'index.php' ) ) ) ); ?></h2>
+	<?php endif; ?>
+	<div class="no-key <?php echo $show_key_form ? 'hidden' : '';?>">
+		<p><?php _e('Akismet eliminates the comment and trackback spam you get on your site. To use Akismet you may need to sign up for an API key. Click the button below to get started.'); ?></p>
+		<form name="akismet_activate" action="https://akismet.com/get/" method="POST"> 
+			<input type="hidden" name="return" value="1"/> 
+			<input type="hidden" name="jetpack" value="<?php echo (string) class_exists( 'Jetpack' );?>"/>
+			<input type="hidden" name="user" value="<?php echo esc_attr( $current_user->user_login );?>"/>
+			<input type="submit" class="button button-primary" value="<?php echo esc_attr( __('Create a new Akismet Key') ); ?>"/>
+		</form>
+		<br/>
+		<a href="#" class="switch-have-key"><?php _e('I already have a key'); ?></a>
+	</div>
+	<div class="have-key <?php echo $show_key_form ? '' : 'hidden';?>">
+		<?php if ( !empty($_POST['submit'] ) && $saved_ok ) : ?>
+		<div id="message" class="updated fade"><p><strong><?php _e('Settings saved.') ?></strong></p></div>
+		<?php endif; ?>
+		<?php if ( isset($_GET['message']) && $_GET['message'] == 'success' ) : ?>
+		<div id="message" class="updated fade"><p><?php _e('<strong>Sign up success!</strong> Please check your email for your Akismet API Key and enter it below.') ?></p></div>
+		<?php endif; ?>
+		<?php foreach( $ms as $m ) : ?>
+		<div class="<?php echo $messages[$m]['class']; ?>"><p><strong><?php echo $messages[$m]['text']; ?></strong></p></div>
+		<?php endforeach; ?>		
+		<form action="" method="post" id="akismet-conf">
+			<table class="form-table">
+				<tbody>
+					<tr>
+						<th><label for="key"><?php _e('Akismet API Key');?></label></th>
+						<td>
+							<input id="key" name="key" type="text" size="15" maxlength="12" value="<?php echo esc_html( get_option('wordpress_api_key') ); ?>" class="regular-text code <?php echo $key_status;?>"><div class="under-input key-status <?php echo $key_status;?>"><?php echo ucfirst( $key_status );?></div>
+							<p class="need-key description"><?php printf( __('You must enter a valid Akismet API key here. If you need an API key, you can <a href="%s">create one here</a>'), '#' );?></p>
+						</td>
+					</tr>
+					<?php if ( $api_key ):?>
+					<tr valign="top">
+						<th scope="row"><?php _e('Settings');?></th>
+						<td>
+							<fieldset><legend class="screen-reader-text"><span><?php _e('Settings');?></span></legend>
+							<label for="akismet_discard_month" title="<?php echo esc_attr( __( 'Auto-detete old spam' ) ); ?>"><input name="akismet_discard_month" id="akismet_discard_month" value="true" type="checkbox" <?php echo get_option('akismet_discard_month') == 'true' ? 'checked="checked"':''; ?>> <span><?php _e('Auto-delete spam submitted on posts more than a month old.'); ?></span></label><br>
+							<label for="akismet_show_user_comments_approved" title="<?php echo esc_attr( __( 'Show approved comments' ) ); ?>"><input name="akismet_show_user_comments_approved" id="akismet_show_user_comments_approved" value="true" type="checkbox" <?php echo get_option('akismet_show_user_comments_approved') == 'true' ? 'checked="checked"':''; ?>> <span><?php _e('Show the number of comments you\'ve approved beside each comment author.'); ?></span></label>
+							</fieldset>
+						</td>
+					</tr>
+					<?php endif; ?>
+				</tbody>
+			</table>
+			<?php akismet_nonce_field($akismet_nonce) ?>
+			<p class="submit">
+				<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e('Save Changes');?>">
+			</p>
+		</form>	
 		
-	<?php
-		}
-	}
-?>
-</tbody>
-</table>
-	<p><?php if ( get_option('akismet_connectivity_time') ) echo sprintf( __('Last checked %s ago.'), human_time_diff( get_option('akismet_connectivity_time') ) ); ?></p>
-	<p class="submit"><input type="submit" name="check" value="<?php _e('Check network status &raquo;'); ?>" /></p>
-	<p><?php printf( __('<a href="%s" target="_blank">Click here</a> to confirm that <a href="%s" target="_blank">Akismet.com is up</a>.'), 'http://status.automattic.com/9931/136079/Akismet-API', 'http://status.automattic.com/9931/136079/Akismet-API' ); ?></p>
-</form>
-
-</div>
+		<?php if ( $api_key ) : ?>
+		<h3><?php _e('Server Connectivity'); ?></h3>
+		<form action="" method="post" id="akismet-connectivity">
+			<table class="form-table">
+				<tbody>
+					<tr>
+						<th><label for="key"><?php _e('Server Status');?></label></th>
+						<td>
+						<?php if ( !function_exists('fsockopen') || !function_exists('gethostbynamel') ) : ?>
+							<p class="key-status failed"><?php _e('Network functions are disabled.'); ?></p>
+							<p class="description"><?php echo sprintf( __('Your web host or server administrator has disabled PHP\'s <code>fsockopen</code> or <code>gethostbynamel</code> functions.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet\'s system requirements</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
+							<?php else :
+									$servers    = akismet_get_server_connectivity();
+									$fail_count = count( $servers ) - count( array_filter( $servers ) );
+									if ( is_array( $servers ) && count( $servers ) > 0 ) { 
+										if ( $fail_count > 0 && $fail_count < count( $servers ) ) { // some connections work, some fail ?>
+							<p class="key-status some"><?php _e('Unable to reach some Akismet servers.'); ?></p>
+							<p class="description"><?php echo sprintf( __('A network problem or firewall is blocking some connections from your web server to Akismet.com.  Akismet is working but this may cause problems during times of network congestion.  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
+									<?php } elseif ( $fail_count > 0 ) { // all connections fail ?>
+							<p class="key-status failed"><?php _e('Unable to reach any Akismet servers.'); ?></p>
+							<p class="description"><?php echo sprintf( __('A network problem or firewall is blocking all connections from your web server to Akismet.com.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
+									<?php } else { // all connections work ?>
+							<p class="key-status valid"><?php  _e('All Akismet servers are available.'); ?></p>
+							<p class="description"><?php _e('Akismet is working correctly.  All servers are accessible.'); ?></p>
+									<?php }
+									} else { //can't connect to any server ?>
+							<p class="key-status failed"><?php _e('Unable to find Akismet servers.'); ?></p>
+							<p class="description"><?php echo sprintf( __('A DNS problem or firewall is preventing all access from your web server to Akismet.com.  <strong>Akismet cannot work correctly until this is fixed.</strong>  Please contact your web host or firewall administrator and give them <a href="%s" target="_blank">this information about Akismet and firewalls</a>.'), 'http://blog.akismet.com/akismet-hosting-faq/'); ?></p>
+								<?php }
+							endif; ?>							
+						</td>
+					</tr>
+					<?php if ( !empty( $servers ) ) : ?>
+					<tr valign="top">
+						<th scope="row"><?php _e('Network Status');?></th>
+						<td>
+							<table class="network-status">
+								<thead>
+										<th><?php _e('Akismet server'); ?></th><th><?php _e('Network Status'); ?></th>
+								</thead>
+								<tbody>
+								<?php
+										asort($servers);
+										foreach ( $servers as $ip => $status ) : ?>
+										<tr>
+											<td align="center"><?php echo esc_html( $ip ); ?></td>
+											<td class="key-status <?php echo $status ? 'valid' : 'failed'; ?>"><?php echo $status ? __('Accessible') : __('Re-trying'); ?></td>
+										</tr>										
+									<?php endforeach; ?>
+								</tbody>
+							</table>
+							<br/>
+							<input type="submit" name="check" id="submit" class="button" style="margin-left: 13.3em;" value="<?php _e('Check Network Status');?>">
+						</td>
+					</tr>
+					<?php endif; ?>
+					<tr valign="top">
+						<th scope="row"><?php _e('Last Checked');?></th>
+						<td>
+							<p><strong><?php echo get_option('akismet_connectivity_time') ? sprintf( __('%s Ago'), ucwords( human_time_diff( get_option('akismet_connectivity_time') ) ) ) : __( 'Not yet' ); ?></strong></p>
+							<p class="description"><?php printf( __('You can confirm that Akismet.com is up by <a href="%s" target="_blank">clicking here</a>.'), 'http://status.automattic.com/9931/136079/Akismet-API' ); ?></p>
+						</td>
+				</tbody>
+			</table>
+			<?php akismet_nonce_field($akismet_nonce) ?>
+		</form>
+		<?php endif;?>
+	</div>
 </div>
 <?php
 }
 
 function akismet_stats_display() {
-	global $akismet_api_host, $akismet_api_port, $wpcom_api_key;
-	$blog = urlencode( get_bloginfo('url') );
-
-	$url = 'http://';
-	if ( is_ssl() )
-		$url = 'https://';
-
-	$url .= 'akismet.com/web/1.0/user-stats.php';
-	$url .= "?blog={$blog}&api_key=" . akismet_get_key();
-	?>
-	<div class="wrap">
-	<iframe src="<?php echo $url; ?>" width="100%" height="2500px" frameborder="0" id="akismet-stats-frame"></iframe>
-	</div>
-	<?php
+	global $akismet_api_host, $akismet_api_port;
+	
+	$blog    = urlencode( get_bloginfo('url') );
+	$api_key = akismet_get_key();?>
+	
+<div class="wrap"><?php	
+	if ( !$api_key ) :?>
+	<div id="akismet-warning" class="updated fade"><p><strong><?php _e('Akismet is almost ready.');?></strong> <?php printf( __( 'You must <a href="%1$s">enter your Akismet API key</a> for it to work.' ), esc_url( add_query_arg( array( 'page' => 'akismet-key-config' ), admin_url( 'admin.php' ) ) ) );?></p></div><?php
+	else :?>
+	<iframe src="<?php echo esc_url( sprintf( '%s://akismet.com/web/1.0/user-stats.php?blog=%s&api_key=%s', is_ssl()?'https':'http', $blog, $api_key ) ); ?>" width="100%" height="2500px" frameborder="0" id="akismet-stats-frame"></iframe><?php
+	endif;?>
+</div><?php
 }
 
 function akismet_stats() {
@@ -288,9 +345,11 @@ function akismet_admin_warnings() {
 				);
 			?>
 				<div class='error'>
-					<p><strong>Akismet Error Code: <?php echo $alert['code']; ?></strong></p>
+					<p><strong><?php _e( 'Akismet Error Code');?>: <?php echo $alert['code']; ?></strong></p>
 					<p><?php esc_html_e( $alert['msg'] ); ?></p>
-					<p>More information is available at <a href="https://akismet.com/errors/<?php echo $alert['code']; ?>">https://akismet.com/errors/<?php echo $alert['code']; ?></a></p>
+					<p><?php //FIXME: need to revert this to using __() in next version
+						printf( translate( 'For more information:' ) . ' <a href="%s">%s</a>' , 'https://akismet.com/errors/'.$alert['code'], 'https://akismet.com/errors/'.$alert['code'] );?>
+					</p>
 				</div>
 			<?php
 			}
@@ -301,10 +360,33 @@ function akismet_admin_warnings() {
 
 	if ( !get_option('wordpress_api_key') && !$wpcom_api_key && !isset($_POST['submit']) ) {
 		function akismet_warning() {
-			echo "
-			<div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet is almost ready.')."</strong> ".sprintf(__('You must <a href="%1$s">enter your Akismet API key</a> for it to work.'), "admin.php?page=akismet-key-config")."</p></div>
-			";
+			global $hook_suffix, $current_user;
+				
+			if ( $hook_suffix == 'plugins.php' ) {              
+               	echo '  
+				<div class="updated" style="padding: 0; margin: 0; border: none; background: none;">  
+					<style type="text/css">  
+.akismet_activate{min-width:825px;border:1px solid #4F800D;padding:5px;margin:15px 0;background:#83AF24;background-image:-webkit-gradient(linear,0% 0,80% 100%,from(#83AF24),to(#4F800D));background-image:-moz-linear-gradient(80% 100% 120deg,#4F800D,#83AF24);-moz-border-radius:3px;border-radius:3px;-webkit-border-radius:3px;position:relative;overflow:hidden}.akismet_activate .aa_a{position:absolute;top:-5px;right:10px;font-size:140px;color:#769F33;font-family:Georgia, "Times New Roman", Times, serif;z-index:1}.akismet_activate .aa_button{font-weight:bold;border:1px solid #029DD6;border-top:1px solid #06B9FD;font-size:15px;text-align:center;padding:9px 0 8px 0;color:#FFF;background:#029DD6;background-image:-webkit-gradient(linear,0% 0,0% 100%,from(#029DD6),to(#0079B1));background-image:-moz-linear-gradient(0% 100% 90deg,#0079B1,#029DD6);-moz-border-radius:2px;border-radius:2px;-webkit-border-radius:2px}.akismet_activate .aa_button:hover{text-decoration:none !important;border:1px solid 
 #029DD6;border-bottom:1px solid #00A8EF;font-size:15px;text-align:center;padding:9px 0 8px 0;color:#F0F8FB;background:#0079B1;background-image:-webkit-gradient(linear,0% 0,0% 100%,from(#0079B1),to(#0092BF));background-image:-moz-linear-gradient(0% 100% 90deg,#0092BF,#0079B1);-moz-border-radius:2px;border-radius:2px;-webkit-border-radius:2px}.akismet_activate .aa_button_border{border:1px solid #006699;-moz-border-radius:2px;border-radius:2px;-webkit-border-radius:2px;background:#029DD6;background-image:-webkit-gradient(linear,0% 0,0% 100%,from(#029DD6),to(#0079B1));background-image:-moz-linear-gradient(0% 100% 90deg,#0079B1,#029DD6)}.akismet_activate .aa_button_container{cursor:pointer;display:inline-block;background:#DEF1B8;padding:5px;-moz-border-radius:2px;border-radius:2px;-webkit-border-radius:2px;width:266px}.akismet_activate .aa_description{position:absolute;top:22px;left:285px;margin-left:25px;color:#E5F2B1;font-size:15px;z-index:1000}.akismet_activate .aa_description strong{
 color:#FFF;font-weight:normal}
+					</style>                       
+					<form name="akismet_activate" action="https://akismet.com/get/" method="POST"> 
+						<input type="hidden" name="return" value="1"/>
+						<input type="hidden" name="jetpack" value="'.(string) class_exists( 'Jetpack' ).'"/>
+						<input type="hidden" name="user" value="'.esc_attr( $current_user->user_login ).'"/>
+						<div class="akismet_activate">  
+							<div class="aa_a">A</div>     
+							<div class="aa_button_container" onclick="document.akismet_activate.submit();">  
+								<div class="aa_button_border">          
+									<div class="aa_button">Activate your Akismet account</div>  
+								</div>  
+							</div>  
+							<div class="aa_description"><strong>Almost done</strong> - activate your account and say goodbye to comment spam.</div>  
+						</div>  
+					</form>  
+				</div>  
+               ';      
+   			}
 		}
+
 		add_action('admin_notices', 'akismet_warning');
 		return;
 	} elseif ( ( empty($_SERVER['SCRIPT_FILENAME']) || basename($_SERVER['SCRIPT_FILENAME']) == 'edit-comments.php' ) &&  wp_next_scheduled('akismet_schedule_cron_recheck') ) {
@@ -314,9 +396,9 @@ function akismet_admin_warnings() {
 				$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 "
-			<div id='akismet-warning' class='updated fade'><p><strong>".__('Akismet has detected a problem.')."</strong> ".sprintf(__('Some comments have not yet been checked for spam by Akismet. They have been temporarily held for moderation. Please check your <a href="%s">Akismet configuration</a> and contact your web host if problems persist.'), 'admin.php?page=akismet-key-config')."</p></div>
-			";
+					echo '
+			<div id="akismet-warning" class="updated fade"><p><strong>'.__('Akismet has detected a problem.').'</strong> '.sprintf(__('Some comments have not yet been checked for spam by Akismet. They have been temporarily held for moderation. Please check your <a href="%s">Akismet configuration</a> and contact your web host if problems persist.'), 'admin.php?page=akismet-key-config').'</p></div>
+			';
 		}
 		add_action('admin_notices', 'akismet_warning');
 		return;
@@ -332,8 +414,8 @@ function akismet_comment_row_action( $a, $comment ) {
 		return $a;
 
 	$akismet_result = get_comment_meta( $comment->comment_ID, 'akismet_result', true );
-	$akismet_error = get_comment_meta( $comment->comment_ID, 'akismet_error', true );
-	$user_result = get_comment_meta( $comment->comment_ID, 'akismet_user_result', true);
+	$akismet_error  = get_comment_meta( $comment->comment_ID, 'akismet_error', true );
+	$user_result    = get_comment_meta( $comment->comment_ID, 'akismet_user_result', true);
 	$comment_status = wp_get_comment_status( $comment->comment_ID );
 	$desc = null;
 	if ( $akismet_error ) {
@@ -369,7 +451,7 @@ function akismet_comment_row_action( $a, $comment ) {
 	}
 		
 	if ( $desc )
-		echo '<span class="akismet-status" commentid="'.$comment->comment_ID.'"><a href="comment.php?action=editcomment&amp;c='.$comment->comment_ID.'#akismet-status" title="' . esc_attr__( 'View comment history' ) . '">'.htmlspecialchars($desc).'</a></span>';
+		echo '<span class="akismet-status" commentid="'.$comment->comment_ID.'"><a href="comment.php?action=editcomment&amp;c='.$comment->comment_ID.'#akismet-status" title="' . esc_attr__( 'View comment history' ) . '">'.esc_html( $desc ).'</a></span>';
 		
 	if ( apply_filters( 'akismet_show_user_comments_approved', get_option('akismet_show_user_comments_approved') ) == 'true' ) {
 		$comment_count = akismet_get_user_comments_approved( $comment->user_id, $comment->comment_author_email, $comment->comment_author, $comment->comment_author_url );
@@ -390,7 +472,7 @@ function akismet_comment_status_meta_box($comment) {
 		foreach ( $history as $row ) {
 			$time = date( 'D d M Y @ h:i:m a', $row['time'] ) . ' GMT';
 			echo '<div style="margin-bottom: 13px;"><span style="color: #999;" alt="' . $time . '" title="' . $time . '">' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '</span> - ';
-			echo htmlspecialchars( $row['message'] ) . '</div>';
+			echo esc_html( $row['message'] ) . '</div>';
 		}
 		
 		echo '</div>';
@@ -418,7 +500,7 @@ function akismet_comment_column_row( $column, $comment_id ) {
 		echo '<dl class="akismet-history">';
 		foreach ( $history as $row ) {
 			echo '<dt>' . sprintf( __('%s ago'), human_time_diff( $row['time'] ) ) . '</dt>';
-			echo '<dd>' . htmlspecialchars( $row['message'] ) . '</dd>';
+			echo '<dd>' . esc_html( $row['message'] ) . '</dd>';
 		}
 		
 		echo '</dl>';
@@ -430,18 +512,16 @@ function akismet_comment_column_row( $column, $comment_id ) {
 // END FIXME
 
 // call out URLS in comments
-function akismet_text_add_link_callback( $m ) {
-	
-		// bare link?
-        if ( $m[4] == $m[2] )
-                return '<a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a>';
-        else
-                return '<span title="'.$m[2].'" class="comment-link"><a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a></span>';
+function akismet_text_add_link_callback( $m ) {	
+	// bare link?
+	if ( $m[4] == $m[2] )
+		return '<a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a>';
+	else
+	    return '<span title="'.$m[2].'" class="comment-link"><a '.$m[1].' href="'.$m[2].'" '.$m[3].' class="comment-link">'.$m[4].'</a></span>';
 }
 
 function akismet_text_add_link_class( $comment_text ) {
-
-        return preg_replace_callback( '#<a ([^>]*)href="([^"]+)"([^>]*)>(.*?)</a>#i', 'akismet_text_add_link_callback', $comment_text );
+	return preg_replace_callback( '#<a ([^>]*)href="([^"]+)"([^>]*)>(.*?)</a>#i', 'akismet_text_add_link_callback', $comment_text );
 }
 
 add_filter('comment_text', 'akismet_text_add_link_class');
@@ -516,7 +596,6 @@ function akismet_submit_nonspam_comment ( $comment_id ) {
 	$comment->blog_lang = get_locale();
 	$comment->blog_charset = get_option('blog_charset');
 	$comment->permalink = get_permalink($comment->comment_post_ID);
-	$comment->reporter_ip = $_SERVER['REMOTE_ADDR'];
 	if ( is_object($current_user) ) {
 	    $comment->reporter = $current_user->user_login;
 	}
@@ -568,7 +647,6 @@ function akismet_submit_spam_comment ( $comment_id ) {
 	$comment->blog_lang = get_locale();
 	$comment->blog_charset = get_option('blog_charset');
 	$comment->permalink = get_permalink($comment->comment_post_ID);
-	$comment->reporter_ip = $_SERVER['REMOTE_ADDR'];
 	if ( is_object($current_user) ) {
 	    $comment->reporter = $current_user->user_login;
 	}
@@ -822,12 +900,12 @@ function akismet_admin_menu() {
 	}
 }
 
-function akismet_load_menu() {
+function akismet_load_menu() {	
 	if ( class_exists( 'Jetpack' ) ) {
-		add_submenu_page( 'jetpack', __( 'Akismet Configuration' ), __( 'Akismet Configuration' ), 'manage_options', 'akismet-key-config', 'akismet_conf' );
+		add_submenu_page( 'jetpack', __( 'Akismet' ), __( 'Akismet' ), 'manage_options', 'akismet-key-config', 'akismet_conf' );
 		add_submenu_page( 'jetpack', __( 'Akismet Stats' ), __( 'Akismet Stats' ), 'manage_options', 'akismet-stats-display', 'akismet_stats_display' );
 	} else {
-		add_submenu_page('plugins.php', __('Akismet Configuration'), __('Akismet Configuration'), 'manage_options', 'akismet-key-config', 'akismet_conf');
+		add_submenu_page('plugins.php', __('Akismet'), __('Akismet'), 'manage_options', 'akismet-key-config', 'akismet_conf');
 		add_submenu_page('index.php', __('Akismet Stats'), __('Akismet Stats'), 'manage_options', 'akismet-stats-display', 'akismet_stats_display');
 	}
 }

diff --git a/plugins/akismet/akismet.css b/plugins/akismet/akismet.css
index dccc9c4..e96bc8a 100644
--- a/plugins/akismet/akismet.css
+++ b/plugins/akismet/akismet.css
@@ -1,12 +1 @@
-#submitted-on { position: relative; }
-#the-comment-list .author .akismet-user-comment-count { display: inline; }
-#the-comment-list .author a span { text-decoration: none; color: #999; }
-#the-comment-list .remove_url { margin-left: 3px; color: #999; padding: 2px 3px 2px 0; }
-#the-comment-list .remove_url:hover { color: #A7301F; font-weight: bold; padding: 2px 2px 2px 0; }
-#dashboard_recent_comments .akismet-status { display: none; } /* never show the flagged by text on the dashboard */
-.akismet-status { float: right; }
-.akismet-status a { color: #AAA; font-style: italic; }
-span.comment-link a { text-decoration: underline; }
-span.comment-link:after { content: " " attr(title) " "; color: #aaa; text-decoration: none; }
-.mshot-arrow { width: 0; height: 0; border-top: 10px solid transparent; border-bottom: 10px solid transparent; border-right:10px solid #5C5C5C; position: absolute; left: -6px; top: 91px; }
-.mshot-container { background: #5C5C5C; position: absolute; top: -94px; padding: 7px; width: 450px; height: 338px; z-index: 20000; -moz-border-radius:6px; border-radius:6px; -webkit-border-radius:6px; }
\ No newline at end of file
+#submitted-on{position:relative}#the-comment-list .author .akismet-user-comment-count{display:inline}#the-comment-list .author a span{text-decoration:none;color:#999}#the-comment-list .remove_url{margin-left:3px;color:#999;padding:2px 3px 2px 0}#the-comment-list .remove_url:hover{color:#A7301F;font-weight:bold;padding:2px 2px 2px 0}#dashboard_recent_comments .akismet-status{display:none}.akismet-status{float:right}.akismet-status a{color:#AAA;font-style:italic}span.comment-link a{text-decoration:underline}span.comment-link:after{content:" "attr(title) " ";color:#aaa;text-decoration:none}.mshot-arrow{width:0;height:0;border-top:10px solid transparent;border-bottom:10px solid transparent;border-right:10px solid #5C5C5C;position:absolute;left:-6px;top:91px}.mshot-container{background:#5C5C5C;position:absolute;top:-94px;padding:7px;width:450px;height:338px;z-index:20000;-moz-border-radius:6px;border-radius:6px;-webkit-border-radius:6px}h2.ak-header{padding-left:38px;background:url('img/
 logo.png') no-repeat 0 9px;margin-bottom:14px;line-height:32px}.key-status{padding:0.4em 1em;color:#fff;font-weight:bold;text-align:center;-webkit-border-radius:3px;border-radius:3px;border-width:1px;border-style:solid;max-width:23.3em}input#key{width:25.3em !important}input#key.valid{border-color:#4F800D}input#key.invalid,input#key.failed{border-color:#888}.key-status.under-input{margin-top:-5px;padding-bottom:0px}.key-status.invalid,.key-status.failed{background-color:#888}.key-status.valid{background-color:#4F800D}.key-status.some{background-color:#993300}.key-status.empty{display:none}table.network-status th,table.network-status td{padding:0.4em;margin:0;text-align:center}table.network-status{border-color:#dfdfdf;border-width:0 0 1px 1px;border-style:solid;border-spacing:0;width:25.6em}table.network-status th,table.network-status td{border-color:#dfdfdf;border-width:1px 1px 0 0;border-style:solid;margin:0;border-spacing:0}table.network-status td.key-status{border-radius:0px;-web
 kit-border-radius:0px}
\ No newline at end of file

diff --git a/plugins/akismet/akismet.js b/plugins/akismet/akismet.js
index 8925c51..f3da8fd 100644
--- a/plugins/akismet/akismet.js
+++ b/plugins/akismet/akismet.js
@@ -1,4 +1,16 @@
 jQuery(document).ready(function () {
+	jQuery( '.switch-have-key' ).click( function() {
+		var no_key = jQuery( this ).parents().find('div.no-key');		
+		var have_key = jQuery( this ).parents().find('div.have-key');
+		
+		no_key.addClass( 'hidden' );
+		have_key.removeClass( 'hidden' );		
+		
+		return false;
+	});
+	jQuery( 'p.need-key a' ).click( function(){
+		document.akismet_activate.submit();
+	});
 	jQuery('.akismet-status').each(function () {
 		var thisId = jQuery(this).attr('commentid');
 		jQuery(this).prependTo('#comment-' + thisId + ' .column-comment div:first-child');

diff --git a/plugins/akismet/akismet.php b/plugins/akismet/akismet.php
index 4c3aef7..1e622f6 100644
--- a/plugins/akismet/akismet.php
+++ b/plugins/akismet/akismet.php
@@ -6,7 +6,7 @@
 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 Akismet configuration page, and save your API key.
-Version: 2.5.7
+Version: 2.5.8
 Author: Automattic
 Author URI: http://automattic.com/wordpress-plugins/
 License: GPLv2 or later
@@ -34,7 +34,7 @@ if ( !function_exists( 'add_action' ) ) {
 	exit;
 }
 
-define('AKISMET_VERSION', '2.5.7');
+define('AKISMET_VERSION', '2.5.8');
 define('AKISMET_PLUGIN_URL', plugin_dir_url( __FILE__ ));
 
 /** If you hardcode a WP.com API key here, all key config screens will be hidden */

diff --git a/plugins/akismet/readme.txt b/plugins/akismet/readme.txt
index 4d61fe9..597749e 100644
--- a/plugins/akismet/readme.txt
+++ b/plugins/akismet/readme.txt
@@ -1,9 +1,9 @@
 === Akismet ===
-Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, automattic
+Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eoigal, automattic
 Tags: akismet, comments, spam
 Requires at least: 3.0
-Tested up to: 3.5
-Stable tag: 2.5.7
+Tested up to: 3.6
+Stable tag: 2.5.8
 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,11 @@ Upload the Akismet plugin to your blog, Activate it, then enter your [Akismet.co
 
 == Changelog ==
 
+= 2.5.8 =
+* Simplify the activation process for new users
+* Remove the reporter_ip parameter
+* Minor preventative security improvements
+
 = 2.5.7 =
 * FireFox Stats iframe preview bug
 * Fix mshots preview when using https

diff --git a/plugins/jetpack/_inc/gallery-settings.js b/plugins/jetpack/_inc/gallery-settings.js
index 0ce38f0..4b5316b 100644
--- a/plugins/jetpack/_inc/gallery-settings.js
+++ b/plugins/jetpack/_inc/gallery-settings.js
@@ -7,12 +7,25 @@
 	// Wrap the render() function to append controls.
 	media.view.Settings.Gallery = media.view.Settings.Gallery.extend({
 		render: function() {
+			var $el = this.$el;
+
 			media.view.Settings.prototype.render.apply( this, arguments );
 
 			// Append the type template and update the settings.
-			this.$el.append( media.template( 'jetpack-gallery-settings' ) );
+			$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'] );
+
+			// Hide the Columns setting for all types except Default
+			$el.find( 'select[name=type]' ).on( 'change', function () {
+				var columnSetting = $el.find( 'select[name=columns]' ).closest( 'label.setting' );
+
+				if ( 'default' == $( this ).val() )
+					columnSetting.show();
+				else
+					columnSetting.hide();
+			} ).change();
+
 			return this;
 		}
 	});

diff --git a/plugins/jetpack/_inc/images/a8c.png b/plugins/jetpack/_inc/images/a8c.png
index b6c84df..d31d6e3 100644
Binary files a/plugins/jetpack/_inc/images/a8c.png and b/plugins/jetpack/_inc/images/a8c.png differ

diff --git a/plugins/jetpack/_inc/images/alertbox-closeicon-2x.png b/plugins/jetpack/_inc/images/alertbox-closeicon-2x.png
index 5c64a0e..e78f448 100644
Binary files a/plugins/jetpack/_inc/images/alertbox-closeicon-2x.png and b/plugins/jetpack/_inc/images/alertbox-closeicon-2x.png differ

diff --git a/plugins/jetpack/_inc/images/alertbox-closeicon.png b/plugins/jetpack/_inc/images/alertbox-closeicon.png
index c293daf..ad3a326 100644
Binary files a/plugins/jetpack/_inc/images/alertbox-closeicon.png and b/plugins/jetpack/_inc/images/alertbox-closeicon.png differ

diff --git a/plugins/jetpack/_inc/images/alertbox-clouds-2x.png b/plugins/jetpack/_inc/images/alertbox-clouds-2x.png
index 770390f..bfa71b2 100644
Binary files a/plugins/jetpack/_inc/images/alertbox-clouds-2x.png and b/plugins/jetpack/_inc/images/alertbox-clouds-2x.png differ

diff --git a/plugins/jetpack/_inc/images/alertbox-clouds.png b/plugins/jetpack/_inc/images/alertbox-clouds.png
index 207dd2a..4a40a7e 100644
Binary files a/plugins/jetpack/_inc/images/alertbox-clouds.png and b/plugins/jetpack/_inc/images/alertbox-clouds.png differ

diff --git a/plugins/jetpack/_inc/images/arrow-2x.png b/plugins/jetpack/_inc/images/arrow-2x.png
index 668bd22..6b83e7c 100644
Binary files a/plugins/jetpack/_inc/images/arrow-2x.png and b/plugins/jetpack/_inc/images/arrow-2x.png differ

diff --git a/plugins/jetpack/_inc/images/arrow-pointer-blue-2x.png b/plugins/jetpack/_inc/images/arrow-pointer-blue-2x.png
index 5c567fa..29c7dcf 100644
Binary files a/plugins/jetpack/_inc/images/arrow-pointer-blue-2x.png and b/plugins/jetpack/_inc/images/arrow-pointer-blue-2x.png differ

diff --git a/plugins/jetpack/_inc/images/arrow.png b/plugins/jetpack/_inc/images/arrow.png
index 995148c..25d2f02 100644
Binary files a/plugins/jetpack/_inc/images/arrow.png and b/plugins/jetpack/_inc/images/arrow.png differ

diff --git a/plugins/jetpack/_inc/images/arrows-2x.png b/plugins/jetpack/_inc/images/arrows-2x.png
index 752f3e2..5004253 100644
Binary files a/plugins/jetpack/_inc/images/arrows-2x.png and b/plugins/jetpack/_inc/images/arrows-2x.png differ

diff --git a/plugins/jetpack/_inc/images/arrows-dark-2x.png b/plugins/jetpack/_inc/images/arrows-dark-2x.png
index cc66581..9e1b44f 100644
Binary files a/plugins/jetpack/_inc/images/arrows-dark-2x.png and b/plugins/jetpack/_inc/images/arrows-dark-2x.png differ

diff --git a/plugins/jetpack/_inc/images/arrows-dark-vs-2x.png b/plugins/jetpack/_inc/images/arrows-dark-vs-2x.png
index 908daa6..4b667c4 100644
Binary files a/plugins/jetpack/_inc/images/arrows-dark-vs-2x.png and b/plugins/jetpack/_inc/images/arrows-dark-vs-2x.png differ

diff --git a/plugins/jetpack/_inc/images/arrows-vs-2x.png b/plugins/jetpack/_inc/images/arrows-vs-2x.png
index 50af738..1ecd829 100644
Binary files a/plugins/jetpack/_inc/images/arrows-vs-2x.png and b/plugins/jetpack/_inc/images/arrows-vs-2x.png differ

diff --git a/plugins/jetpack/_inc/images/atdbuttontr-2x.png b/plugins/jetpack/_inc/images/atdbuttontr-2x.png
index 8d3617e..5086e08 100644
Binary files a/plugins/jetpack/_inc/images/atdbuttontr-2x.png and b/plugins/jetpack/_inc/images/atdbuttontr-2x.png differ

diff --git a/plugins/jetpack/_inc/images/automattic-2x.png b/plugins/jetpack/_inc/images/automattic-2x.png
index 412bee1..661556a 100644
Binary files a/plugins/jetpack/_inc/images/automattic-2x.png and b/plugins/jetpack/_inc/images/automattic-2x.png differ

diff --git a/plugins/jetpack/_inc/images/automattic.png b/plugins/jetpack/_inc/images/automattic.png
index dc1c3a7..9c0c388 100644
Binary files a/plugins/jetpack/_inc/images/automattic.png and b/plugins/jetpack/_inc/images/automattic.png differ

diff --git a/plugins/jetpack/_inc/images/bubble_bg-2x.png b/plugins/jetpack/_inc/images/bubble_bg-2x.png
index f535313..8757def 100644
Binary files a/plugins/jetpack/_inc/images/bubble_bg-2x.png and b/plugins/jetpack/_inc/images/bubble_bg-2x.png differ

diff --git a/plugins/jetpack/_inc/images/comment-grey-bubble-2x.png b/plugins/jetpack/_inc/images/comment-grey-bubble-2x.png
index 72e0240..57fbeac 100644
Binary files a/plugins/jetpack/_inc/images/comment-grey-bubble-2x.png and b/plugins/jetpack/_inc/images/comment-grey-bubble-2x.png differ

diff --git a/plugins/jetpack/_inc/images/delete-2x.png b/plugins/jetpack/_inc/images/delete-2x.png
index 5c869b1..9436624 100644
Binary files a/plugins/jetpack/_inc/images/delete-2x.png and b/plugins/jetpack/_inc/images/delete-2x.png differ

diff --git a/plugins/jetpack/_inc/images/footer-clouds-2x.png b/plugins/jetpack/_inc/images/footer-clouds-2x.png
index f6b7454..4616c0a 100644
Binary files a/plugins/jetpack/_inc/images/footer-clouds-2x.png and b/plugins/jetpack/_inc/images/footer-clouds-2x.png differ

diff --git a/plugins/jetpack/_inc/images/footer-clouds.png b/plugins/jetpack/_inc/images/footer-clouds.png
index e7c8d05..d8dc03a 100644
Binary files a/plugins/jetpack/_inc/images/footer-clouds.png and b/plugins/jetpack/_inc/images/footer-clouds.png differ

diff --git a/plugins/jetpack/_inc/images/generic-2x.png b/plugins/jetpack/_inc/images/generic-2x.png
index 85c6f85..0f7b28f 100644
Binary files a/plugins/jetpack/_inc/images/generic-2x.png and b/plugins/jetpack/_inc/images/generic-2x.png differ

diff --git a/plugins/jetpack/_inc/images/header-clouds-2x.png b/plugins/jetpack/_inc/images/header-clouds-2x.png
index 0762edf..2fdf221 100644
Binary files a/plugins/jetpack/_inc/images/header-clouds-2x.png and b/plugins/jetpack/_inc/images/header-clouds-2x.png differ

diff --git a/plugins/jetpack/_inc/images/header-clouds-small-2x.png b/plugins/jetpack/_inc/images/header-clouds-small-2x.png
index a5ab65c..0438767 100644
Binary files a/plugins/jetpack/_inc/images/header-clouds-small-2x.png and b/plugins/jetpack/_inc/images/header-clouds-small-2x.png differ

diff --git a/plugins/jetpack/_inc/images/header-clouds-small.png b/plugins/jetpack/_inc/images/header-clouds-small.png
index c1a6b27..00bbf16 100644
Binary files a/plugins/jetpack/_inc/images/header-clouds-small.png and b/plugins/jetpack/_inc/images/header-clouds-small.png differ

diff --git a/plugins/jetpack/_inc/images/header-clouds.png b/plugins/jetpack/_inc/images/header-clouds.png
index a766222..ce8fea9 100644
Binary files a/plugins/jetpack/_inc/images/header-clouds.png and b/plugins/jetpack/_inc/images/header-clouds.png differ

diff --git a/plugins/jetpack/_inc/images/icon-comingsoon-2x.png b/plugins/jetpack/_inc/images/icon-comingsoon-2x.png
index baede10..ea426d4 100644
Binary files a/plugins/jetpack/_inc/images/icon-comingsoon-2x.png and b/plugins/jetpack/_inc/images/icon-comingsoon-2x.png differ

diff --git a/plugins/jetpack/_inc/images/icon-comingsoon.png b/plugins/jetpack/_inc/images/icon-comingsoon.png
index 3814c86..ecfce9b 100644
Binary files a/plugins/jetpack/_inc/images/icon-comingsoon.png and b/plugins/jetpack/_inc/images/icon-comingsoon.png differ

diff --git a/plugins/jetpack/_inc/images/icon-pointer-flag-2x.png b/plugins/jetpack/_inc/images/icon-pointer-flag-2x.png
index 057545a..b130901 100644
Binary files a/plugins/jetpack/_inc/images/icon-pointer-flag-2x.png and b/plugins/jetpack/_inc/images/icon-pointer-flag-2x.png differ

diff --git a/plugins/jetpack/_inc/images/image-2x.png b/plugins/jetpack/_inc/images/image-2x.png
index a47dd71..8a5e57a 100644
Binary files a/plugins/jetpack/_inc/images/image-2x.png and b/plugins/jetpack/_inc/images/image-2x.png differ

diff --git a/plugins/jetpack/_inc/images/imgedit-icons-2x.png b/plugins/jetpack/_inc/images/imgedit-icons-2x.png
index 155f541..c9a0f02 100644
Binary files a/plugins/jetpack/_inc/images/imgedit-icons-2x.png and b/plugins/jetpack/_inc/images/imgedit-icons-2x.png differ

diff --git a/plugins/jetpack/_inc/images/jetpack-closebox-icon.png b/plugins/jetpack/_inc/images/jetpack-closebox-icon.png
index 1c014d9..5f48b49 100644
Binary files a/plugins/jetpack/_inc/images/jetpack-closebox-icon.png and b/plugins/jetpack/_inc/images/jetpack-closebox-icon.png differ

diff --git a/plugins/jetpack/_inc/images/list-2x.png b/plugins/jetpack/_inc/images/list-2x.png
index 27a67b8..043b869 100644
Binary files a/plugins/jetpack/_inc/images/list-2x.png and b/plugins/jetpack/_inc/images/list-2x.png differ

diff --git a/plugins/jetpack/_inc/images/logo-2x.png b/plugins/jetpack/_inc/images/logo-2x.png
index 9f7f693..80d789e 100644
Binary files a/plugins/jetpack/_inc/images/logo-2x.png and b/plugins/jetpack/_inc/images/logo-2x.png differ

diff --git a/plugins/jetpack/_inc/images/logo-small-2x.png b/plugins/jetpack/_inc/images/logo-small-2x.png
index c39fbf9..2126ab7 100644
Binary files a/plugins/jetpack/_inc/images/logo-small-2x.png and b/plugins/jetpack/_inc/images/logo-small-2x.png differ

diff --git a/plugins/jetpack/_inc/images/logo-small.png b/plugins/jetpack/_inc/images/logo-small.png
index 997dbb1..634b5a9 100644
Binary files a/plugins/jetpack/_inc/images/logo-small.png and b/plugins/jetpack/_inc/images/logo-small.png differ

diff --git a/plugins/jetpack/_inc/images/logo.png b/plugins/jetpack/_inc/images/logo.png
index 2d49b67..9882b7a 100644
Binary files a/plugins/jetpack/_inc/images/logo.png and b/plugins/jetpack/_inc/images/logo.png differ

diff --git a/plugins/jetpack/_inc/images/media-button-2x.png b/plugins/jetpack/_inc/images/media-button-2x.png
index 8ad6eb4..1c6b785 100644
Binary files a/plugins/jetpack/_inc/images/media-button-2x.png and b/plugins/jetpack/_inc/images/media-button-2x.png differ

diff --git a/plugins/jetpack/_inc/images/menuicon-sprite-2x.png b/plugins/jetpack/_inc/images/menuicon-sprite-2x.png
index aa9a368..302b336 100644
Binary files a/plugins/jetpack/_inc/images/menuicon-sprite-2x.png and b/plugins/jetpack/_inc/images/menuicon-sprite-2x.png differ

diff --git a/plugins/jetpack/_inc/images/menuicon-sprite.png b/plugins/jetpack/_inc/images/menuicon-sprite.png
index 3bebcf1..15a3351 100644
Binary files a/plugins/jetpack/_inc/images/menuicon-sprite.png and b/plugins/jetpack/_inc/images/menuicon-sprite.png differ

diff --git a/plugins/jetpack/_inc/images/module-clouds-2x.png b/plugins/jetpack/_inc/images/module-clouds-2x.png
index 1bab9fb..905a430 100644
Binary files a/plugins/jetpack/_inc/images/module-clouds-2x.png and b/plugins/jetpack/_inc/images/module-clouds-2x.png differ

diff --git a/plugins/jetpack/_inc/images/module-clouds.png b/plugins/jetpack/_inc/images/module-clouds.png
index 2414fef..1e0f72d 100644
Binary files a/plugins/jetpack/_inc/images/module-clouds.png and b/plugins/jetpack/_inc/images/module-clouds.png differ

diff --git a/plugins/jetpack/_inc/images/module-icons-sprite-2x.png b/plugins/jetpack/_inc/images/module-icons-sprite-2x.png
index 11f4204..f73023f 100644
Binary files a/plugins/jetpack/_inc/images/module-icons-sprite-2x.png and b/plugins/jetpack/_inc/images/module-icons-sprite-2x.png differ

diff --git a/plugins/jetpack/_inc/images/module-icons-sprite.png b/plugins/jetpack/_inc/images/module-icons-sprite.png
index c6979f6..90a42f8 100644
Binary files a/plugins/jetpack/_inc/images/module-icons-sprite.png and b/plugins/jetpack/_inc/images/module-icons-sprite.png differ

diff --git a/plugins/jetpack/_inc/images/press-this-2x.png b/plugins/jetpack/_inc/images/press-this-2x.png
index a335aec..be6ee74 100644
Binary files a/plugins/jetpack/_inc/images/press-this-2x.png and b/plugins/jetpack/_inc/images/press-this-2x.png differ

diff --git a/plugins/jetpack/_inc/images/publicize.png b/plugins/jetpack/_inc/images/publicize.png
index 428b886..8cf9ede 100644
Binary files a/plugins/jetpack/_inc/images/publicize.png and b/plugins/jetpack/_inc/images/publicize.png differ

diff --git a/plugins/jetpack/_inc/images/rss/blue-large.png b/plugins/jetpack/_inc/images/rss/blue-large.png
index b4a6c52..fd62327 100644
Binary files a/plugins/jetpack/_inc/images/rss/blue-large.png and b/plugins/jetpack/_inc/images/rss/blue-large.png differ

diff --git a/plugins/jetpack/_inc/images/rss/blue-medium.png b/plugins/jetpack/_inc/images/rss/blue-medium.png
index f64e354..9411018 100644
Binary files a/plugins/jetpack/_inc/images/rss/blue-medium.png and b/plugins/jetpack/_inc/images/rss/blue-medium.png differ

diff --git a/plugins/jetpack/_inc/images/rss/blue-small.png b/plugins/jetpack/_inc/images/rss/blue-small.png
index c281155..8e4b053 100644
Binary files a/plugins/jetpack/_inc/images/rss/blue-small.png and b/plugins/jetpack/_inc/images/rss/blue-small.png differ

diff --git a/plugins/jetpack/_inc/images/rss/green-large.png b/plugins/jetpack/_inc/images/rss/green-large.png
index 4bf8643..a9c2c83 100644
Binary files a/plugins/jetpack/_inc/images/rss/green-large.png and b/plugins/jetpack/_inc/images/rss/green-large.png differ

diff --git a/plugins/jetpack/_inc/images/rss/green-medium.png b/plugins/jetpack/_inc/images/rss/green-medium.png
index 13304ce..f8e8fbc 100644
Binary files a/plugins/jetpack/_inc/images/rss/green-medium.png and b/plugins/jetpack/_inc/images/rss/green-medium.png differ

diff --git a/plugins/jetpack/_inc/images/rss/green-small.png b/plugins/jetpack/_inc/images/rss/green-small.png
index 8833c9e..299905b 100644
Binary files a/plugins/jetpack/_inc/images/rss/green-small.png and b/plugins/jetpack/_inc/images/rss/green-small.png differ

diff --git a/plugins/jetpack/_inc/images/rss/orange-large.png b/plugins/jetpack/_inc/images/rss/orange-large.png
index 966b1c1..1250349 100644
Binary files a/plugins/jetpack/_inc/images/rss/orange-large.png and b/plugins/jetpack/_inc/images/rss/orange-large.png differ

diff --git a/plugins/jetpack/_inc/images/rss/orange-medium.png b/plugins/jetpack/_inc/images/rss/orange-medium.png
index 8f5aaa2..7c47f76 100644
Binary files a/plugins/jetpack/_inc/images/rss/orange-medium.png and b/plugins/jetpack/_inc/images/rss/orange-medium.png differ

diff --git a/plugins/jetpack/_inc/images/rss/orange-small.png b/plugins/jetpack/_inc/images/rss/orange-small.png
index 9e0bf22..4f326d5 100644
Binary files a/plugins/jetpack/_inc/images/rss/orange-small.png and b/plugins/jetpack/_inc/images/rss/orange-small.png differ

diff --git a/plugins/jetpack/_inc/images/rss/pink-large.png b/plugins/jetpack/_inc/images/rss/pink-large.png
index 49b94c7..1273b77 100644
Binary files a/plugins/jetpack/_inc/images/rss/pink-large.png and b/plugins/jetpack/_inc/images/rss/pink-large.png differ

diff --git a/plugins/jetpack/_inc/images/rss/pink-medium.png b/plugins/jetpack/_inc/images/rss/pink-medium.png
index cd8e957..feb154c 100644
Binary files a/plugins/jetpack/_inc/images/rss/pink-medium.png and b/plugins/jetpack/_inc/images/rss/pink-medium.png differ

diff --git a/plugins/jetpack/_inc/images/rss/purple-large.png b/plugins/jetpack/_inc/images/rss/purple-large.png
index 1ddb70f..704765e 100644
Binary files a/plugins/jetpack/_inc/images/rss/purple-large.png and b/plugins/jetpack/_inc/images/rss/purple-large.png differ

diff --git a/plugins/jetpack/_inc/images/rss/purple-medium.png b/plugins/jetpack/_inc/images/rss/purple-medium.png
index 8d375a5..f785cbb 100644
Binary files a/plugins/jetpack/_inc/images/rss/purple-medium.png and b/plugins/jetpack/_inc/images/rss/purple-medium.png differ

diff --git a/plugins/jetpack/_inc/images/rss/purple-small.png b/plugins/jetpack/_inc/images/rss/purple-small.png
index 75f3c60..d21d59b 100644
Binary files a/plugins/jetpack/_inc/images/rss/purple-small.png and b/plugins/jetpack/_inc/images/rss/purple-small.png differ

diff --git a/plugins/jetpack/_inc/images/rss/red-large.png b/plugins/jetpack/_inc/images/rss/red-large.png
index 88d9bf8..5e03f14 100644
Binary files a/plugins/jetpack/_inc/images/rss/red-large.png and b/plugins/jetpack/_inc/images/rss/red-large.png differ

diff --git a/plugins/jetpack/_inc/images/rss/red-medium.png b/plugins/jetpack/_inc/images/rss/red-medium.png
index 838db55..d01e0d8 100644
Binary files a/plugins/jetpack/_inc/images/rss/red-medium.png and b/plugins/jetpack/_inc/images/rss/red-medium.png differ

diff --git a/plugins/jetpack/_inc/images/rss/red-small.png b/plugins/jetpack/_inc/images/rss/red-small.png
index 85fd61c..d42b135 100644
Binary files a/plugins/jetpack/_inc/images/rss/red-small.png and b/plugins/jetpack/_inc/images/rss/red-small.png differ

diff --git a/plugins/jetpack/_inc/images/rss/silver-large.png b/plugins/jetpack/_inc/images/rss/silver-large.png
index af67da9..d10b884 100644
Binary files a/plugins/jetpack/_inc/images/rss/silver-large.png and b/plugins/jetpack/_inc/images/rss/silver-large.png differ

diff --git a/plugins/jetpack/_inc/images/rss/silver-medium.png b/plugins/jetpack/_inc/images/rss/silver-medium.png
index 5559c8c..3455231 100644
Binary files a/plugins/jetpack/_inc/images/rss/silver-medium.png and b/plugins/jetpack/_inc/images/rss/silver-medium.png differ

diff --git a/plugins/jetpack/_inc/images/rss/silver-small.png b/plugins/jetpack/_inc/images/rss/silver-small.png
index 4a41080..ef8be0e 100644
Binary files a/plugins/jetpack/_inc/images/rss/silver-small.png and b/plugins/jetpack/_inc/images/rss/silver-small.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/beautifulmath.png b/plugins/jetpack/_inc/images/screenshots/beautifulmath.png
index eaf8d1d..3599a42 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/beautifulmath.png and b/plugins/jetpack/_inc/images/screenshots/beautifulmath.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/carousel.png b/plugins/jetpack/_inc/images/screenshots/carousel.png
index 5bcc94c..bc56e4d 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/carousel.png and b/plugins/jetpack/_inc/images/screenshots/carousel.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/comments.png b/plugins/jetpack/_inc/images/screenshots/comments.png
index 86f6530..04f37ba 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/comments.png and b/plugins/jetpack/_inc/images/screenshots/comments.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/contactform.png b/plugins/jetpack/_inc/images/screenshots/contactform.png
index b41760b..02934a5 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/contactform.png and b/plugins/jetpack/_inc/images/screenshots/contactform.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/custom-css.png b/plugins/jetpack/_inc/images/screenshots/custom-css.png
index 4be5cb2..1e35ad4 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/custom-css.png and b/plugins/jetpack/_inc/images/screenshots/custom-css.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/hovercards.png b/plugins/jetpack/_inc/images/screenshots/hovercards.png
index 63977a5..1220549 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/hovercards.png and b/plugins/jetpack/_inc/images/screenshots/hovercards.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/likes.png b/plugins/jetpack/_inc/images/screenshots/likes.png
index 1c7670a..9f5404a 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/likes.png and b/plugins/jetpack/_inc/images/screenshots/likes.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpg b/plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpg
index 94ca6dd..d09d391 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpg and b/plugins/jetpack/_inc/images/screenshots/mobile-push-notifications.jpg differ

diff --git a/plugins/jetpack/_inc/images/screenshots/notes.png b/plugins/jetpack/_inc/images/screenshots/notes.png
index 4506db1..bf3a6b9 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/notes.png and b/plugins/jetpack/_inc/images/screenshots/notes.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/post-by-email.png b/plugins/jetpack/_inc/images/screenshots/post-by-email.png
index b114088..e63e9a7 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/post-by-email.png and b/plugins/jetpack/_inc/images/screenshots/post-by-email.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/publicize.png b/plugins/jetpack/_inc/images/screenshots/publicize.png
index 428b886..8cf9ede 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/publicize.png and b/plugins/jetpack/_inc/images/screenshots/publicize.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/sharing.png b/plugins/jetpack/_inc/images/screenshots/sharing.png
index 9c36d17..0949b5e 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/sharing.png and b/plugins/jetpack/_inc/images/screenshots/sharing.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/shortcodes.png b/plugins/jetpack/_inc/images/screenshots/shortcodes.png
index 8bff1d6..5434e12 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/shortcodes.png and b/plugins/jetpack/_inc/images/screenshots/shortcodes.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/shortlinks.png b/plugins/jetpack/_inc/images/screenshots/shortlinks.png
index 2de8477..bfc99cf 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/shortlinks.png and b/plugins/jetpack/_inc/images/screenshots/shortlinks.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/spelling.png b/plugins/jetpack/_inc/images/screenshots/spelling.png
index a6986d4..b28142e 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/spelling.png and b/plugins/jetpack/_inc/images/screenshots/spelling.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/stats.png b/plugins/jetpack/_inc/images/screenshots/stats.png
index 836c139..ceb3fbe 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/stats.png and b/plugins/jetpack/_inc/images/screenshots/stats.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/subscriptions.png b/plugins/jetpack/_inc/images/screenshots/subscriptions.png
index a1c5563..113800b 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/subscriptions.png and b/plugins/jetpack/_inc/images/screenshots/subscriptions.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/tiled-gallery.png b/plugins/jetpack/_inc/images/screenshots/tiled-gallery.png
index 8168590..0da99ee 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/tiled-gallery.png and b/plugins/jetpack/_inc/images/screenshots/tiled-gallery.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/vaultpress.png b/plugins/jetpack/_inc/images/screenshots/vaultpress.png
index f1f80c7..64645bc 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/vaultpress.png and b/plugins/jetpack/_inc/images/screenshots/vaultpress.png differ

diff --git a/plugins/jetpack/_inc/images/screenshots/widgets.png b/plugins/jetpack/_inc/images/screenshots/widgets.png
index e0749c6..ad609ae 100644
Binary files a/plugins/jetpack/_inc/images/screenshots/widgets.png and b/plugins/jetpack/_inc/images/screenshots/widgets.png differ

diff --git a/plugins/jetpack/_inc/images/stars-2x.png b/plugins/jetpack/_inc/images/stars-2x.png
index a370aaf..503c83a 100644
Binary files a/plugins/jetpack/_inc/images/stars-2x.png and b/plugins/jetpack/_inc/images/stars-2x.png differ

diff --git a/plugins/jetpack/_inc/images/status-light-2x.png b/plugins/jetpack/_inc/images/status-light-2x.png
index adff497..461d987 100644
Binary files a/plugins/jetpack/_inc/images/status-light-2x.png and b/plugins/jetpack/_inc/images/status-light-2x.png differ

diff --git a/plugins/jetpack/_inc/images/status-light.png b/plugins/jetpack/_inc/images/status-light.png
index 9a6665c..c9ffb7b 100644
Binary files a/plugins/jetpack/_inc/images/status-light.png and b/plugins/jetpack/_inc/images/status-light.png differ

diff --git a/plugins/jetpack/_inc/images/tb-close-2x.png b/plugins/jetpack/_inc/images/tb-close-2x.png
index 9f5f6b6..9530278 100644
Binary files a/plugins/jetpack/_inc/images/tb-close-2x.png and b/plugins/jetpack/_inc/images/tb-close-2x.png differ

diff --git a/plugins/jetpack/_inc/jetpack-retina.css b/plugins/jetpack/_inc/jetpack-retina.css
index c5c69ff..295f6ca 100644
--- a/plugins/jetpack/_inc/jetpack-retina.css
+++ b/plugins/jetpack/_inc/jetpack-retina.css
@@ -1,5 +1,9 @@
 /* Retina core icons */
-@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) {
+@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) {
+
 	/* TinyMCE buttons */
 	.wp_themeSkin .mceToolbar span.mce_undo,
 	.wp_themeSkin .mceToolbar span.mce_redo,
@@ -36,7 +40,7 @@
 	.wp_themeSkin .mceToolbar .mceSplitButton .mce_forecolor span.mce_forecolor,
 	.wp_themeSkin .mceToolbar .mceSplitButton span.mce_numlist,
 	.wp_themeSkin .mceToolbar .mceSplitButton span.mce_bullist {
-		background-image: url('images/wpicons-2x.png');
+		background-image: url(images/wpicons-2x.png);
 		background-size: 560px 40px;
 	}
 
@@ -44,7 +48,7 @@
 	.view-switch .current #view-switch-list,
 	.view-switch #view-switch-excerpt,
 	.view-switch .current #view-switch-excerpt {
-		background-image: url('images/list-2x.png');
+		background-image: url(images/list-2x.png);
 		background-size: 80px 20px;
 	}
 
@@ -55,74 +59,76 @@
 	.imgedit-fliph,
 	.imgedit-undo,
 	.imgedit-redo {
-		background-image: url('images/imgedit-icons-2x.png');
+		background-image: url(images/imgedit-icons-2x.png);
 		background-size: 260px 64px;
 	}
 
 	/* Welcome screen close button */
 	.welcome-panel .welcome-panel-close:before {
-		background-image: url('images/xit-2x.gif');
+		background-image: url(images/xit-2x.gif);
 		background-size: 20px 10px;
 	}
 
 	/* Dismiss tag buttons */
-	.tagchecklist span a, #bulk-titles div a {
-		background-image: url('images/xit-2x.gif') !important;
+	.tagchecklist span a,
+	#bulk-titles div a {
+		background-image: url(images/xit-2x.gif) !important;
 		background-size: 20px 10px !important;
 	}
-	.tagchecklist span a:hover, #bulk-titles div a:hover {
-		background-image: url('images/xit-2x.gif') !important;
+	.tagchecklist span a:hover,
+	#bulk-titles div a:hover {
+		background-image: url(images/xit-2x.gif) !important;
 		background-size: 20px 10px !important;
 	}
 
 	/* Pointer dismiss button */
 	.wp-pointer-buttons a.close::before {
-		background-image: url('images/xit-2x.gif');
-		background-size: 20px 10px; 
+		background-image: url(images/xit-2x.gif);
+		background-size: 20px 10px;
 	}
 
 	/* Pointer icon */
 	.wp-pointer-content h3::before {
-		background-image: url('images/icon-pointer-flag-2x.png');
+		background-image: url(images/icon-pointer-flag-2x.png);
 		background-size: 36px 37px;
 	}
 
 	/* Pointer arrow */
 	.wp-pointer-arrow {
-		background-image: url('images/arrow-pointer-blue-2x.png') !important;
+		background-image: url(images/arrow-pointer-blue-2x.png) !important;
 		background-size: 30px 60px !important;
 	}
 
 	/* Screen options links */
 	#screen-meta-links a.show-settings {
-		background-image: url('images/arrows-2x.png') !important;
+		background-image: url(images/arrows-2x.png) !important;
 		background-size: 15px 123px !important;
 	}
 	body.admin-color-classic #screen-meta-links a.show-settings {
-		background-image: url('images/arrows-vs-2x.png') !important;
+		background-image: url(images/arrows-vs-2x.png) !important;
 	}
-	
+
 	/* Collapse button divs */
 	#collapse-button div {
-		background-image: url('images/arrows-2x.png') !important;
+		background-image: url(images/arrows-2x.png) !important;
 		background-size: 15px 123px !important;
 	}
 	body.admin-color-classic #collapse-button div {
-		background-image: url('images/arrows-vs-2x.png') !important;
+		background-image: url(images/arrows-vs-2x.png) !important;
 	}
 
 	/* Metabox handle arrows */
 	.meta-box-sortables .postbox:hover .handlediv {
-		background-image: url('images/arrows-2x.png') !important;
+		background-image: url(images/arrows-2x.png) !important;
 		background-size: 15px 123px !important;
 	}
 	body.admin-color-classic .meta-box-sortables .postbox:hover .handlediv {
-		background-image: url('images/arrows-vs-2x.png') !important;
+		background-image: url(images/arrows-vs-2x.png) !important;
 	}
 
 	/* Date button */
 	.curtime #timestamp {
-		background-image: url('images/date-button-2x.gif') !important;
+		background-image: url(images/date-button-2x.gif) !important;
 		background-size: 16px 16px;
 		display: inline-block;
 		height: 16px;
@@ -133,77 +139,88 @@
 		padding-top: 12px;
 		height: 0;
 		width: 12px;
-		background: transparent url('images/comment-grey-bubble-2x.png') no-repeat center center;
+		background: transparent url(images/comment-grey-bubble-2x.png) no-repeat center center;
 		background-size: 12px 12px;
 	}
 	.post-com-count {
-		background-image: url('images/bubble_bg-2x.png') !important;
+		background-image: url(images/bubble_bg-2x.png) !important;
 		background-size: 18px 100px;
 	}
 
 	/* Post sorting indicator */
 	.sorting-indicator {
-		background-image: url('images/sort-2x.gif');
+		background-image: url(images/sort-2x.gif);
 		background-size: 14px 4px;
 	}
 
 	/* Widget arrows */
 	.sidebar-name-arrow {
-		background-image: url('images/arrows-2x.png') !important;
+		background-image: url(images/arrows-2x.png) !important;
 		background-size: 15px 123px !important;
 	}
+
 	body.admin-color-classic .sidebar-name-arrow {
-		background-image: url('images/arrows-vs-2x.png') !important;
+		background-image: url(images/arrows-vs-2x.png) !important;
 	}
+
 	.sidebar-name:hover .sidebar-name-arrow {
-		background-image: url('images/arrows-dark-2x.png') !important;
+		background-image: url(images/arrows-dark-2x.png) !important;
 	}
+
 	body.admin-color-classic .sidebar-name:hover .sidebar-name-arrow {
-		background-image: url('images/arrows-dark-vs-2x.png') !important;
+		background-image: url(images/arrows-dark-vs-2x.png) !important;
 	}
+
 	.widget-top a.widget-action {
-		background-image: url('images/arrows-2x.png') !important;
+		background-image: url(images/arrows-2x.png) !important;
 		background-size: 15px 123px !important;
 	}
+
 	body.admin-color-classic .widget-top a.widget-action {
-		background-image: url('images/arrows-vs-2x.png') !important;
+		background-image: url(images/arrows-vs-2x.png) !important;
 	}
+
 	.widget-top a.widget-action:hover {
-		background-image: url('images/arrows-dark-2x.png') !important;
+		background-image: url(images/arrows-dark-2x.png) !important;
 	}
+
 	body.admin-color-classic .widget-top a.widget-action:hover {
-		background-image: url('images/arrows-dark-vs-2x.png') !important;
+		background-image: url(images/arrows-dark-vs-2x.png) !important;
 	}
 
 	/* Menu editor item arrows */
 	.item-edit {
-		background-image: url('images/arrows-2x.png') !important;
+		background-image: url(images/arrows-2x.png) !important;
 		background-size: 15px 123px !important;
 	}
+
 	body.admin-color-classic .item-edit {
-		background-image: url('images/arrows-vs-2x.png') !important;
+		background-image: url(images/arrows-vs-2x.png) !important;
 	}
+
 	.item-edit:hover {
-		background-image: url('images/arrows-dark-2x.png') !important;
+		background-image: url(images/arrows-dark-2x.png) !important;
 		background-size: 15px 123px !important;
 	}
+
 	body.admin-color-classic .item-edit:hover {
-		background-image: url('images/arrows-dark-vs-2x.png') !important;
+		background-image: url(images/arrows-dark-vs-2x.png) !important;
 	}
 
 	/* Plugin install star ratings */
 	div.star-holder {
-		background-image: url('images/stars-2x.png');
+		background-image: url(images/stars-2x.png);
 		background-size: 21px 37px;
 	}
+
 	div.star-holder .star-rating {
-		background-image: url('images/stars-2x.png');
+		background-image: url(images/stars-2x.png);
 		background-size: 21px 37px;
 	}
 
 	/* Press This bookmarklet icon */
 	.pressthis a span {
-		background-image: url('images/press-this-2x.png');
+		background-image: url(images/press-this-2x.png);
 		background-size: 24px 20px;
 	}
 
@@ -212,7 +229,7 @@
 		padding-top: 15px;
 		width: 15px;
 		height: 0;
-		background: url('images/media-button-2x.png') no-repeat center center;
+		background: url(images/media-button-2x.png) no-repeat center center;
 		background-size: 15px 15px;
 	}
 
@@ -221,28 +238,28 @@
 		padding-top: 20px;
 		width: 20px;
 		height: 0;
-		background: url('images/atdbuttontr-2x.png') no-repeat center center;
+		background: url(images/atdbuttontr-2x.png) no-repeat center center;
 		background-size: 20px 20px;
 	}
 
 	/* Resize editor */
 	#post-body .wp_themeSkin .mceStatusbar a.mceResize {
-		background-image: url('images/resize-2x.gif') !important;
+		background-image: url(images/resize-2x.gif) !important;
 		background-size: 11px 11px !important;
 	}
 
 	/* MCE dropdowns */
 	.wp_themeSkin .mceListBox .mceOpen span, .wp_themeSkin .mceSplitButton a.mceOpen {
-		background-image: url("images/down_arrow-2x.gif") !important;
+		background-image: url(images/down_arrow-2x.gif) !important;
 		background-size: 10px 20px;
 	}
-	
+
 	/* Img overlay buttons */
 	#wp_editimgbtn, #wp_delimgbtn, #wp_editgallery, #wp_delgallery {
 		padding-top: 24px !important;
 		height: 0;
 		width: 24px;
-		background: url("images/delete-2x.png") no-repeat center center !important;
+		background: url(images/delete-2x.png) no-repeat center center !important;
 		background-size: 24px 24px;
 	}
 
@@ -254,40 +271,40 @@
 	}
 
 	#wp_editimgbtn, #wp_editgallery {
-		background: #eee url("images/image-2x.png") no-repeat center center !important;
+		background: #eee url(images/image-2x.png) no-repeat center center !important;
 	}
 
 	#wp_delimgbtn, #wp_delgallery {
-		background: #eee url("images/delete-2x.png") no-repeat center center !important;
+		background: #eee url(images/delete-2x.png) no-repeat center center !important;
 	}
-		
+
 	/* AJAX loading spinners */
 	img.ajax-loading, img.ajax-feedback {
 		width: 16px;
 		height: 0;
 		padding-top: 19px !important;
-		background: url("images/wpspin_light-2x.gif") no-repeat center center !important;
+		background: url(images/wpspin_light-2x.gif) no-repeat center center !important;
 		background-size: 16px 16px;
 	}
 
 	/* Align buttons (in image properties in the media library) */
 	.image-align-none-label {
-		background: url('images/align-none-2x.png') no-repeat center left;
+		background: url(images/align-none-2x.png) no-repeat center left;
 		background-size: 21px 15px;
 	}
 
 	.image-align-left-label {
-		background: url('images/align-left-2x.png') no-repeat center left;
+		background: url(images/align-left-2x.png) no-repeat center left;
 		background-size: 22px 15px;
 	}
 
 	.image-align-center-label {
-		background: url('images/align-center-2x.png') no-repeat center left;
+		background: url(images/align-center-2x.png) no-repeat center left;
 		background-size: 21px 15px;
 	}
 
 	.image-align-right-label {
-		background: url('images/align-right-2x.png') no-repeat center left;
+		background: url(images/align-right-2x.png) no-repeat center left;
 		background-size: 22px 15px;
 	}
 
@@ -345,88 +362,88 @@
 
 	/* Uploader close button */
 	#TB_closeWindowButton img {
-		background: url('images/tb-close-2x.png') no-repeat center center;
+		background: url(images/tb-close-2x.png) no-repeat center center;
 		padding-top: 15px;
 		width: 15px;
 		height: 0;
 		background-size: 15px 15px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/archive.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/archive.png'] {
-		background: url('images/archive-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/archive.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/archive.png"] {
+		background: url(images/archive-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
 		background-size: 46px 60px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/audio.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/audio.png'] {
-		background: url('images/audio-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/audio.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/audio.png"] {
+		background: url(images/audio-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
 		background-size: 46px 60px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/code.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/code.png'] {
-		background: url('images/code-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/code.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/code.png"] {
+		background: url(images/code-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
 		background-size: 46px 60px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/default.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/default.png'] {
-		background: url('images/default-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/default.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/default.png"] {
+		background: url(images/default-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
 		background-size: 46px 60px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/document.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/document.png'] {
-		background: url('images/document-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/document.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/document.png"] {
+		background: url(images/document-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
 		background-size: 46px 60px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/interactive.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/interactive.png'] {
-		background: url('images/interactive-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/interactive.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/interactive.png"] {
+		background: url(images/interactive-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
 		background-size: 46px 60px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/spreadsheet.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/spreadsheet.png'] {
-		background: url('images/spreadsheet-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/spreadsheet.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/spreadsheet.png"] {
+		background: url(images/spreadsheet-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
 		background-size: 46px 60px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/text.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/text.png'] {
-		background: url('images/text-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/text.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/text.png"] {
+		background: url(images/text-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
 		background-size: 46px 60px;
 	}
 
-	td.media-icon img[src$='wp-includes/images/crystal/video.png'],
-	td.A1B1 img[src$='wp-includes/images/crystal/video.png'] {
-		background: url('images/video-2x.png') no-repeat center center;
+	td.media-icon img[src$="wp-includes/images/crystal/video.png"],
+	td.A1B1 img[src$="wp-includes/images/crystal/video.png"] {
+		background: url(images/video-2x.png) no-repeat center center;
 		padding-top: 60px;
 		width: 46px;
 		height: 0;
@@ -434,23 +451,23 @@
 	}
 
 	.farbtastic .marker {
-		background-image: url('images/marker-2x.png');
+		background-image: url(images/marker-2x.png);
 		background-size: 17px 17px;
 	}
 
 	.farbtastic .wheel {
-		background-image: url('images/wheel-2x.png');
+		background-image: url(images/wheel-2x.png);
 		background-size: 195px 195px;
 	}
 
 	.farbtastic .overlay {
-		background-image: url('images/mask-2x.png');
+		background-image: url(images/mask-2x.png);
 		background-size: 101px 101px;
 	}
 
 	/* Generic admin menu icon */
-	#adminmenu img[src$='wp-admin/images/generic.png'] {
-		background: url('images/generic-2x.png') no-repeat center center;
+	#adminmenu img[src$="wp-admin/images/generic.png"] {
+		background: url(images/generic-2x.png) no-repeat center center;
 		padding-top: 25px;
 		width: 16px;
 		height: 0;
@@ -463,7 +480,7 @@
 	.clearlooks2 .mceMed,
 	.clearlooks2 .mceMax,
 	.wp-dialog .ui-dialog-titlebar-close {
-		background-image: url('images/buttons-2x.gif') !important;
+		background-image: url(images/buttons-2x.gif) !important;
 		background-size: 116px 48px !important;
 	}
 }

diff --git a/plugins/jetpack/_inc/jetpack-rtl.css b/plugins/jetpack/_inc/jetpack-rtl.css
index 45c676b..f1fad50 100644
--- a/plugins/jetpack/_inc/jetpack-rtl.css
+++ b/plugins/jetpack/_inc/jetpack-rtl.css
@@ -1,128 +1,120 @@
-	#jp-header #jp-clouds {
-		background-position: -632px 100%;
-	}
-		#jp-header.small #jp-clouds {
-			background-position: -425px 100%;
-		}
-
-		#jp-header #jp-clouds #jp-disconnect {
-			float: left;
-			margin: -35px 0 0 25px;
-			text-align: left;
-		}
-
-		#jp-header #jp-clouds #jp-disconnect a {
-			background-position: 100% 90%;
-			padding: 4px 30px 3px 10px;
-		}
-			#jp-header #jp-clouds #jp-disconnect a:hover {
-				background-position: 100% 3%;
-			}
-
-	#jp-header h3 {
-		background-position: top right;
-		right: 25px;
-		left: auto;
-	}
-
-	#jp-header p {
-		right: 390px;
-		left: auto;
-		text-align: right;
-	}
-
-	#jp-info {
-		margin: 0 28px 0 12px;
-	}
-
-		#jp-info p {
-			float:right;
-		}
-
-		#jp-info a.jp-button {
-			float: left;
-			margin: 8px 20px 0 0;
-		}
-
-	.jp-connect { padding: 10px 0 5px !important; }
-	
-	#jetpack-settings > .jetpack-message { margin: 10px 15px 10px 13px }
-
-	.jetpack-message .squeezer {
-		text-align: right;
-	}
-	.jetpack-message h4 {
-		margin: 0 0 10px 10px;
-	}
-
-	.more-info {
-		margin: 0 15px 5px 12px;
-		background: transparent url( images/header-clouds-sm.png ) bottom right repeat-x;
-	}
-		.more-info .jp-close {
-			left: 0;
-			right: auto;
-			padding: 0 6px 0 4px;
-			-moz-border-radius: 3px;
-			-webkit-border-radius: 3px;
-			border-radius: 3px;
-			-moz-border-radius-topright: 0;
-			-moz-border-radius-bottomright: 0;
-			-webkit-border-top-left-radius: 0;
-			-webkit-border-bottom-left-radius: 0;
-			border-top-left-radius: 0;
-			border-bottom-left-radius: 0;
-		}
-
-		.more-info div.jp-info-img {
-			float: left;
-			margin: 0 20px 0 30px;
-		}
-		
+#jp-header #jp-clouds {
+	background-position: -632px 100%;
+}
+
+#jp-header.small #jp-clouds {
+	background-position: -425px 100%;
+}
+
+#jp-header #jp-clouds #jp-disconnect {
+	float: left;
+	margin: -35px 0 0 25px;
+	text-align: left;
+}
+
+#jp-header #jp-clouds #jp-disconnect a {
+	background-position: 100% 90%;
+	padding: 4px 30px 3px 10px;
+}
+
+#jp-header #jp-clouds #jp-disconnect a:hover {
+	background-position: 100% 3%;
+}
+
+#jp-header h3 {
+	background-position: top right;
+	right: 25px;
+	left: auto;
+}
+
+#jp-header p {
+	right: 390px;
+	left: auto;
+	text-align: right;
+}
+
+#jp-info {
+	margin: 0 28px 0 12px;
+}
+
+#jp-info p {
+	float:right;
+}
+
+#jp-info a.jp-button {
+	float: left;
+	margin: 8px 20px 0 0;
+}
+
+.jp-connect {
+	padding: 10px 0 5px !important;
+}
+
+#jetpack-settings > .jetpack-message {
+	margin: 10px 15px 10px 13px;
+}
+
+.jetpack-message .squeezer {
+	text-align: right;
+}
+
+.jetpack-message h4 {
+	margin: 0 0 10px 10px;
+}
+
+.more-info {
+	margin: 0 15px 5px 12px;
+	background: transparent url(images/header-clouds-sm.png) bottom right repeat-x;
+}
+
+.more-info .jp-close {
+	left: 0;
+	right: auto;
+	padding: 0 6px 0 4px;
+	border-radius: 3px;
+	border-top-left-radius: 0;
+	border-bottom-left-radius: 0;
+}
+
+.more-info div.jp-info-img {
+	float: left;
+	margin: 0 20px 0 30px;
+}
+
 .jetpack-module {
 	float: right;
 	margin: 0 15px 15px 0;
 	padding: 15px 15px 35px 0;
 }
-	.jetpack-module div.module-image {
-		float: left;
-		margin: 0 10px 5px 0;
-		-webkit-border-radius: 0;
-		-moz-border-radius: 0;
-		border-radius: 0;
-		-webkit-border-top-right-radius: 5px;
-		-moz-border-radius-topleft: 5px;
-		border-top-right-radius: 5px;
-		-webkit-border-bottom-right-radius: 5px;
-		-moz-border-radius-bottomleft: 5px;
-		border-bottom-right-radius: 5px;
-	}
-
-		.jetpack-module div.module-image p {
-			-webkit-border-radius: 0;
-			-moz-border-radius: 0;
-			border-radius: 0;
-			-webkit-border-bottom-right-radius: 5px;
-			-moz-border-radius-bottomleft: 5px;
-			border-bottom-right-radius: 5px;
-		}
-
-
-	.jetpack-module .jetpack-module-actions {
-		right: 15px;
-		left: auto;
-	}
-
-		.placeholder h3 {
-			margin-left: 15px;
-			margin-right: auto;
-		}
-
-	#jp-footer .automattic {
-		padding-right: 3px;
-		padding-left: 0;
-	}
-
-		#jp-footer .automattic span {
-			margin: 0 1px 0 5px;
-		}
+
+.jetpack-module div.module-image {
+	float: left;
+	margin: 0 10px 5px 0;
+	border-radius: 0;
+	border-top-right-radius: 5px;
+	border-bottom-right-radius: 5px;
+}
+
+.jetpack-module div.module-image p {
+	border-radius: 0;
+	border-bottom-right-radius: 5px;
+}
+
+.jetpack-module .jetpack-module-actions {
+	right: 15px;
+	left: auto;
+}
+
+.placeholder h3 {
+	margin-left: 15px;
+	margin-right: auto;
+}
+
+#jp-footer .automattic {
+	padding-right: 3px;
+	padding-left: 0;
+}
+
+#jp-footer .automattic span {
+	margin: 0 1px 0 5px;
+}

diff --git a/plugins/jetpack/_inc/jetpack.css b/plugins/jetpack/_inc/jetpack.css
index b684f7c..9c2c977 100644
--- a/plugins/jetpack/_inc/jetpack.css
+++ b/plugins/jetpack/_inc/jetpack.css
@@ -1,439 +1,566 @@
+/*
+ * Consolidate the font-family declarations:
+ */
+
+#jp-header p,
+#jp-info a.jp-button,
+.jetpack-message h4,
+.jetpack-message h5,
+.jetpack-message p a.button-primary,
+.jetpack-activated h3,
+.jetpack-activated p,
+.jetpack-module div.module-image p,
+.jetpack-module h3,
+.jetpack-module .jetpack-module-actions a,
+#jp-settings-screen h3,
+.jp-survey h4,
+.jetpack-install-container p a.button-connector {
+	font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", Verdana, "Bitstream Vera Sans", sans-serif;
+}
+
+#jp-info p,
+.more-info p,
+.more-info ul,
+.jetpack-module-description p {
+	font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;
+}
+
+/*
+ * Jetpack:
+ */
+
+/* Force the menu not to be sticky, so we can color the arrow. */
+.toplevel_page_jetpack.admin-color-mp6.sticky-menu #adminmenuwrap,
+body[class*=" jetpack_page_jetpack_"].admin-color-mp6.sticky-menu #adminmenuwrap {
+	position: relative;
+	z-index: auto;
+	top: 0;
+}
+
+.toplevel_page_jetpack.admin-color-mp6 ul#adminmenu a.wp-has-current-submenu:after,
+.toplevel_page_jetpack.admin-color-mp6 ul#adminmenu > li.current > a.current:after,
+body[class*=" jetpack_page_jetpack_"].admin-color-mp6 ul#adminmenu a.wp-has-current-submenu:after,
+body[class*=" jetpack_page_jetpack_"].admin-color-mp6 ul#adminmenu > li.current > a.current:after {
+	border-right-color:#8fad4b;
+}
+
+.toplevel_page_jetpack.jetpack-disconnected #wpwrap,
+body[class*=" jetpack_page_jetpack_"].jetpack-disconnected #wpwrap {
+	background: url(images/header-clouds.png) -150px -60px repeat-x;
+}
+
+.toplevel_page_jetpack.jetpack-disconnected.admin-color-mp6 #wpwrap,
+body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.admin-color-mp6 #wpwrap {
+	background-position: -143px -60px;
+}
+
+.toplevel_page_jetpack.jetpack-disconnected.folded #wpwrap,
+body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.folded #wpwrap {
+	background-position: -263px -60px;
+}
+
+.toplevel_page_jetpack.jetpack-disconnected.admin-color-mp6.folded #wpwrap,
+body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.admin-color-mp6.folded #wpwrap {
+	background-position: -257px -60px;
+}
+
+.toplevel_page_jetpack.jetpack-connected #wpwrap,
+body[class*=" jetpack_page_jetpack_"].jetpack-connected #wpwrap {
+	background: url(images/header-clouds-small.png) 45px 0 repeat-x;
+}
+
+.toplevel_page_jetpack.jetpack-connected.admin-color-mp6 #wpwrap,
+body[class*=" jetpack_page_jetpack_"].jetpack-connected.admin-color-mp6 #wpwrap {
+	background-position: 52px 0;
+}
+
+.toplevel_page_jetpack.jetpack-connected.folded #wpwrap,
+body[class*=" jetpack_page_jetpack_"].jetpack-connected.folded #wpwrap {
+	background-position: -68px 0;
+}
+
+.toplevel_page_jetpack.jetpack-connected.admin-color-mp6.folded #wpwrap,
+body[class*=" jetpack_page_jetpack_"].jetpack-connected.admin-color-mp6.folded #wpwrap {
+	background-position: -62px 0;
+}
+
+@media only screen and (max-width: 900px) {
+
+	.toplevel_page_jetpack.jetpack-disconnected.auto-fold #wpwrap,
+	body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.auto-fold #wpwrap {
+		background-position: -263px -60px;
+	}
+
+	.toplevel_page_jetpack.jetpack-disconnected.admin-color-mp6.auto-fold #wpwrap,
+	body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.admin-color-mp6.auto-fold #wpwrap {
+		background-position: -257px -60px;
+	}
+
+	.toplevel_page_jetpack.jetpack-connected.auto-fold #wpwrap,
+	body[class*=" jetpack_page_jetpack_"].jetpack-connected.auto-fold #wpwrap {
+		background-position: -68px 0;
+	}
+
+	.toplevel_page_jetpack.jetpack-connected.admin-color-mp6.auto-fold #wpwrap,
+	body[class*=" jetpack_page_jetpack_"].jetpack-connected.admin-color-mp6.auto-fold #wpwrap {
+		background-position: -62px 0;
+	}
+
+}
+
+.toplevel_page_jetpack.screen-meta-wrap {
+	position: absolute;
+	top: 0;
+	width: 100%;
+	z-index: 2;
+}
+
 #jp-header {
 	min-width: 741px;
 	z-index: 0;
 	margin: 30px 0 -30px 0;
 }
-	#jp-header.small {
-		margin-bottom: 50px;
+
+#jp-header.small {
+	margin: 20px 0 50px;
+}
+
+#jp-header #jp-clouds {
+	position: relative;
+	padding-top: 110px;
+}
+
+#jp-header.small #jp-clouds {
+	padding: 50px 0 0 0;
+	height: 70px;
+}
+
+#jp-header #jp-clouds #jp-disconnectors {
+	font-size: 12px;
+	color: #fff;
+	float: right;
+	margin-top: -35px;
+	text-align: left;
+	position: relative;
+	left: -45px;
+}
+
+#jp-header #jp-clouds .jp-disconnect a {
+	background: #8caa46 url(images/status-light.png) 3px 85% no-repeat;
+	display: inline-block;
+	position: relative;
+	width: 100%;
+	height: 1.7em;
+	overflow: hidden;
+	padding: 4px 0 3px 30px;
+	margin: 0 -20px 3px 0;
+	color: #fff;
+	text-decoration: none;
+	border: 1px solid #7a943d;
+	border-radius: 5px;
+	box-shadow: inset 0 0 2px rgba(255, 255, 255, 0.4);
+	text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
+}
+
+#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 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) {
+
+	.toplevel_page_jetpack.jetpack-disconnected #wpwrap,
+	body[class*=" jetpack_page_jetpack_"].jetpack-disconnected #wpwrap {
+		background-image: url(images/header-clouds-2x.png);
+		background-size: 1600px 400px;
 	}
 
-	#jp-header #jp-clouds {
-		position: relative;
-		background: transparent url( images/header-clouds.png ) -315px 100% repeat-x;
-		padding-top: 110px;
-		-webkit-border-radius: 3px;
-		-moz-border-radius: 3px;
-		border-radius: 3px;
+	.toplevel_page_jetpack.jetpack-connected #wpwrap,
+	body[class*=" jetpack_page_jetpack_"].jetpack-connected #wpwrap {
+		background-image: url(images/header-clouds-small-2x.png);
+		background-size: 980px 140px;
 	}
-		#jp-header.small #jp-clouds {
-			background: transparent url( images/header-clouds-small.png ) -120px 100% repeat-x;
-			padding: 50px 0 0 0;
-			height: 70px;
-		}
-
-
-		#jp-header #jp-clouds #jp-disconnectors {
-			font-size: 12px;
-			color: #fff;
-			float: right;
-			margin-top: -35px;
-			text-align: left;
-			position: relative;
-			left: -45px;
-		}
-
-		#jp-header #jp-clouds .jp-disconnect a {
-			background: #8caa46 url( images/status-light.png ) 3px 85% no-repeat;
-			display: inline-block;
-			position: relative;
-			width: 100%;
-			height: 1.7em;
-			overflow: hidden;
-			padding: 4px 0 3px 30px;
-			margin: 0 -20px 3px 0;
-			color: #fff;
-			text-decoration: none;
-			border: 1px solid #7a943d;
-			-moz-border-radius: 5px;
-			-webkit-border-radius: 5px;
-			border-radius: 5px;
-			-moz-box-shadow: inset 0 0 2px rgba( 255, 255, 255, 0.4 );
-			-webkit-box-shadow: inset 0 0 2px rgba( 255, 255, 255, 0.4 );
-			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 -2% no-repeat;
-				background-color: #839f40;
-				border-color: #6a8037;
-			}
-
-			#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 {
-	    	background: transparent url( images/header-clouds-2x.png ) -315px 100% repeat-x;
-			background-size:1600px 400px;
-	    }
-	    	#jp-header.small #jp-clouds {
-	    		background: transparent url( images/header-clouds-small-2x.png ) -120px 100% repeat-x;
-	    		background-size:980px 140px;
-	    	}
-
-	    #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 -2% no-repeat;
-	    		background-size:25px 57px;
-	    	}
+
+	#jp-header #jp-clouds .jp-disconnect a {
+		background-image: url(images/status-light-2x.png);
+		background-size: 25px 57px;
+	}
+
+	#jp-header #jp-clouds .jp-disconnect a:hover {
+		background-image: url(images/status-light-2x.png);
+		background-size: 25px 57px;
 	}
 
+}
+
+#jp-header h3 {
+	position: relative;
+	background: transparent url(images/logo.png) top left no-repeat;
+	width: 252px;
+	height: 200px;
+	overflow: hidden;
+	text-indent: -999em;
+	top: -95px;
+	left: 25px;
+	margin: 0;
+	padding: 0;
+}
+
+#jp-header.small h3 {
+	background: transparent url(images/logo-small.png) top left no-repeat;
+	width: 149px;
+	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 {
-		position: relative;
-		background: transparent url( images/logo.png ) top left no-repeat;
-		width: 252px;
-		height: 200px;
-		overflow: hidden;
-		text-indent: -999em;
-		top: -95px;
-		left: 25px;
-		margin: 0;
-		padding: 0;
+		background-image: url(images/logo-2x.png);
+		background-size: 250px 200px;
 	}
-		#jp-header.small h3 {
-			background: transparent url( images/logo-small.png ) top left no-repeat;
-			width: 149px;
-			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 {
-	    	background: transparent url( images/logo-2x.png ) top left no-repeat;
-			background-size:250px 200px;
-	    }
-	    	#jp-header.small h3 {
-	    		background: transparent url( images/logo-small-2x.png ) top left no-repeat;
-				background-size:150px 120px;
-	    	}
+
+	#jp-header.small h3 {
+		background-image: url(images/logo-small-2x.png);
+		background-size: 150px 120px;
 	}
 
+}
 
+#jp-header p {
+	position: absolute;
+	left: 390px;
+	text-align: left;
+	top: 30px;
+	width: 48%;
+	color: #fff;
+	font-size: 25px;
+	line-height: 130%;
+	text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
+	-webkit-font-smoothing: antialiased;
+}
 
-	#jp-header p {
-		position: absolute;
-		left: 390px;
-		text-align: left;
-		top: 30px;
-		width: 48%;
-		color: #fff;
-		font-size: 25px;
-		line-height: 130%;
-		text-shadow: 0px 1px 1px rgba(0,0,0,0.5);
-		font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-		-webkit-font-smoothing: antialiased;
-	}
+#jp-info {
+	position: relative;
+	overflow: visible;
+	z-index: 50;
+	margin: 0 12px 0 28px;
+	min-width: 780px;
+}
 
-	#jp-info {
-		position: relative;
-		overflow: visible;
-		z-index: 50;
-		margin: 0 12px 0 28px;
-		min-width: 780px;
-	}
+#jp-info p {
+	font-size: 17px;
+	line-height: 150%;
+	text-shadow: 0 1px 0 #fff;
+	color: #666;
+	margin: 0 0 40px;
+	float: left;
+	width: 58%;
+}
 
-		#jp-info p {
-			font-size: 17px;
-			line-height: 150%;
-			text-shadow: 0px 1px 0px #fff;
-			font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
-			color: #666;
-			margin: 0 0 40px;
-			float:left;
-			width: 58%;
-		}
-			#jp-info p.small {
-				font-size: 14px;
-			}
-
-		#jp-info a.jp-button {
-			font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-			float: right;
-			margin: 8px 0 0 20px;
-			display: inline-block;
-			background: #69acce;
-			-moz-box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
-			-webkit-box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
-			box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
-			padding: 12px 20px;
-			border: 1px solid #2a8cba;
-			-moz-border-radius: 5px;
-			-webkit-border-radius: 5px;
-			border-radius: 5px;
-			line-height: 100%;
-			color: #fff;
-			text-align: center;
-			font-size: 20px;
-			font-weight: bold;
-			text-decoration: none;
-			text-shadow: 0px 1px 2px rgba( 0,0,0,0.5);
-			-webkit-transition-duration: .3s;
-			-moz-transition-duration: .3s;
-			cursor: pointer;
-		}
-			#jp-info a.jp-button:hover, #jp-info a.jp-button:active {
-				background-color: #f0a000;
-				border-color: #c87800;
-				-webkit-transition-duration: .3s;
-				outline: none;
-				-moz-box-shadow: inset 0 0 2px #fff, 0 1px 7px rgba(240,160,0,0.5);
-				-webkit-box-shadow: inset 0 0 2px #fff, 0 1px 7px rgba(240,160,0,0.5);
-				box-shadow: inset 0 0 2px #fff, 0 1px 7spx rgba(240,160,0,0.5);
-			}
+#jp-info p.small {
+	font-size: 14px;
+}
+
+#jp-info a.jp-button {
+	float: right;
+	margin: 8px 0 0 20px;
+	display: inline-block;
+	background: #69acce;
+	box-shadow: inset 0 0 2px #fff,
+	            0 1px 5px rgba(0, 0, 0, 0.3);
+	padding: 12px 20px;
+	border: 1px solid #2a8cba;
+	border-radius: 5px;
+	line-height: 100%;
+	color: #fff;
+	text-align: center;
+	font-size: 20px;
+	font-weight: bold;
+	text-decoration: none;
+	text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
+	-webkit-transition-duration: 0.3s;
+	transition-duration:         0.3s;
+	cursor: pointer;
+}
+
+#jp-info a.jp-button:hover,
+#jp-info a.jp-button:active {
+	background-color: #f0a000;
+	border-color: #c87800;
+	outline: none;
+	box-shadow: inset 0 0 2px #fff,
+	            0 1px 7px rgba(240, 160, 0, 0.5);
+}
 
 .jetpack-message {
 	position: relative;
 	z-index: 100;
 	border: 1px solid #2a8cba !important;
-	-moz-border-radius: 3px;
-	-webkit-border-radius: 3px;
 	border-radius: 3px;
-	background: url( images/alertbox-clouds.png ) 100% 100% no-repeat;
+	background: url(images/alertbox-clouds.png) 100% 100% no-repeat;
 	background-color: #6aafcf !important;
-	-webkit-box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
-	-moz-box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
-	box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
+	box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.04);
 	padding: 18px 90px 8px 15px !important;
 	overflow: hidden;
 	line-height: 180%;
 }
 
 /* Retina alertbox 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) {
-    .jetpack-message {
-    	background: url( images/alertbox-clouds-2x.png ) 100% 100% no-repeat;
-		background-size:95px 55px;
-    }
+@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-message {
+		background-image: url(images/alertbox-clouds-2x.png);
+		background-size: 95px 55px;
+	}
+
 }
 
-	.jp-connect { padding: 10px 0 5px !important; }
+.jp-connect {
+	padding: 10px 0 5px !important;
+}
 
-	#jetpack-settings > .jetpack-message { margin: 10px 13px 10px 15px }
+#jetpack-settings > .jetpack-message {
+	margin: 10px 13px 10px 15px;
+}
 
-	.jetpack-message .squeezer {
-		max-width: 940px;
-		margin: 0 0 2px;
-		padding: 0 10px;
-		text-align: left;
-		overflow: hidden;
-	}
-	.jetpack-message h4 {
-		margin: 0 10px 10px 0;
-		font-size: 18px;
-		font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-		font-weight: normal;
-		color: #fff;
-		text-shadow: 0px 1px 1px rgba(0,0,0,0.4);
-		-moz-border-radius: 5px;
-		-webkit-border-radius: 5px;
-		border-radius: 5px;
-		display: inline-block;
-	}
+.jetpack-message .squeezer {
+	max-width: 940px;
+	margin: 0 0 2px;
+	padding: 0 10px;
+	text-align: left;
+	overflow: hidden;
+}
 
-	.jetpack-message h5 {
-		font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-		margin: 0;
-	}
+.jetpack-message h4 {
+	margin: 0 10px 10px 0;
+	font-size: 18px;
+	font-weight: normal;
+	color: #fff;
+	text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
+	border-radius: 5px;
+	display: inline-block;
+}
 
-	.jetpack-message .squeezer a, .jetpack-message .squeezer a:visited {
-		color: #fff;
-		text-decoration: underline;
-	}
+.jetpack-message h5 {
+	margin: 0;
+}
 
-	.jetpack-message .squeezer a:hover {
-		color: #f0a000;
-	}
+.jetpack-message .squeezer a,
+.jetpack-message .squeezer a:visited {
+	color: #fff;
+	text-decoration: underline;
+}
 
-	.jetpack-message code, .jetpack-err p {
-		background: rgba( 0,0,0,0.2 );
-		font-size: 14px;
-		padding: 3px 5px !important;
-		text-shadow: 0px 1px 1px rgba(0,0,0,0.4);
-		color: #fff;
-	}
+.jetpack-message .squeezer a:hover {
+	color: #f0a000;
+}
 
-	.jetpack-message p {
-		margin: -1px 0 0 0 !important;
-		padding: 0;
-		display: inline-block;
-	}
-		.jetpack-err p {
-			overflow: hidden;
-			margin-bottom: 10px !important;
-		}
-
-		.jetpack-message p a.button-primary {
-			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;
-			cursor: pointer;
-			font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-		}
-			.jetpack-message p a.button-primary:hover, .jetpack-message p a.button-primary:active {
-				background-color: #f0a000;
-				border-color: #c87800;
-				-webkit-transition-duration: .3s;
-				outline: none;
-			}
-
-		.inline-message p strong { display: block; }
+.jetpack-message code, .jetpack-err p {
+	background: rgba(0, 0, 0, 0.2);
+	font-size: 14px;
+	padding: 3px 5px !important;
+	text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
+	color: #fff;
+}
+
+.jetpack-message p {
+	margin: -1px 0 0 0 !important;
+	padding: 0;
+	display: inline-block;
+}
+
+.jetpack-err p {
+	overflow: hidden;
+	margin-bottom: 10px !important;
+}
+
+.jetpack-message p a.button-primary {
+	font-size: 16px !important;
+	display: inline-block;
+	padding: 8px 15px;
+	color: #fff;
+	text-align: center;
+	font-size: 20px;
+	text-decoration: none;
+	border-radius: 5px;
+	border: 1px solid #8caa46;
+	background: #b4d278;
+	box-shadow: inset 0 0 2px #fff,
+	            0 1px 1px rgba(0, 0, 0, 0.1);
+	text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
+	-webkit-transition-duration: 0.3s;
+	transition-duration:         0.3s;
+	cursor: pointer;
+}
+
+.jetpack-message p a.button-primary:hover,
+.jetpack-message p a.button-primary:active {
+	background-color: #f0a000;
+	border-color: #c87800;
+	outline: none;
+}
+
+.inline-message p strong {
+	display: block;
+}
+
+.more-info {
+	position: relative;
+	top: -5px;
+	margin: 0 15px 5px 15px;
+	height: 230px; /* Have to set height otherwise slideDown() doesn't work. */
+	padding-right: 15px !important;
+	padding-bottom: 15px;
+	clear: both;
+	overflow: visible !important;
+	color: #666 !important;
+	background: transparent url(images/module-clouds.png) bottom left repeat-x;
+	background-color: #f0f0f0 !important;
+	border-color: #dcdcdc !important;
+	text-shadow: 0 1px 0 #fff;
+	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 {
-		position: relative;
-		top: -5px;
-		margin: 0 15px 5px 15px;
-		height: 230px; /* Have to set height otherwise slideDown() doesn't work. */
-		padding-right: 15px !important;
-		padding-bottom: 15px;
-		clear: both;
-		overflow: visible !important;
-		color: #666 !important;
-		background: transparent url( images/module-clouds.png ) bottom left repeat-x;
-		background-color: #f0f0f0 !important;
-		border-color: #dcdcdc !important;
-		text-shadow: 0px 1px 0px #fff;
-		-webkit-box-shadow: inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
-		-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 );
+		background-image: url(images/module-clouds-2x.png);
+		background-size: 980px 140px;
 	}
 
-	/* 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 {
-	    	background: transparent url( images/module-clouds-2x.png ) bottom left repeat-x;
-			background-size:980px 140px;
-	    }
+}
+
+.more-info h4 {
+	padding: 0;
+	background: none;
+	font-weight: normal;
+	color: #000;
+	font-size: 19px;
+	text-shadow: 0 1px 0 #fff;
+}
+
+.more-info h5 {
+	margin-left: 0;
+	font-size: 12px !important;
+}
+
+.more-info .arrow {
+	position: absolute;
+	width: 29px;
+	height: 18px;
+	top: -16px;
+	left: 0;
+	background: url(images/arrow.png) top left no-repeat;
+}
+
+.more-info .arrow:after {
+	display: none;
+}
+
+/* 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 {
+		background-image: url(images/arrow-2x.png);
+		background-size: 29px 16px;
 	}
 
+}
+
+.more-info p {
+	margin: 0 0 10px 0 !important;
+	font-size: 14px;
+	line-height: 150%;
+	display: block;
+}
+
+.more-info ul {
+	font-size: 14px;
+	line-height: 150%;
+}
+
+.more-info li {
+	list-style-type: disc;
+	list-style-position: inside;
+}
+
+.more-info code {
+	background: rgba(0, 0, 0, 0.05);
+	font-size: 12px;
+	padding: 1px;
+	text-shadow: none;
+	color: #555;
+}
+
+.more-info .jp-close {
+	position: absolute;
+	top: 18px;
+	right: 0;
+	background: #888;
+	background: rgba(0, 0, 0, 0.4);
+	color: #fff;
+	font-size: 14px !important;
+	height: 22px;
+	line-height: 20px;
+	padding: 0 6px 0 6px;
+	font-weight: bold !important;
+	border-radius: 3px;
+	border-top-right-radius: 0;
+	border-bottom-right-radius: 0;
+	cursor: pointer;
+	text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
+}
+
+.more-info .jp-close:hover {
+	background: #69acce;
+}
+
+.more-info div.jp-info-img {
+	float: right;
+	width: 320px;
+	margin: 0 30px 0 20px;
+}
 
-		.more-info h4 {
-			padding: 0;
-			background: none;
-			font-weight: normal;
-			color: #000;
-			font-size: 19px;
-			text-shadow: 0px 1px 0px #fff;
-		}
-
-		.more-info h5 {
-			margin-left: 0;
-			font-size: 12px !important;
-		}
-		.more-info .arrow {
-			position: absolute;
-			width: 29px;
-			height: 18px;
-			top: -16px;
-			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 {
-		    	background: url( images/arrow-2x.png ) top left no-repeat;
-				background-size:29px 16px;
-		    }
-		}
-
-		.more-info p {
-			margin: 0 0 10px 0 !important;
-			font-size: 14px;
-			font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
-			line-height: 150%;
-			display: block;
-		}
-
-		.more-info ul {
-			font-size: 14px;
-			font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
-			line-height: 150%;
-		}
-
-		.more-info li {
-			list-style-type: disc;
-			list-style-position: inside;
-		}
-
-		.more-info code {
-			background: rgba( 0,0,0,0.05 );
-			font-size: 12px;
-			padding: 1px;
-			text-shadow: none;
-			color: #555;
-		}
-
-		.more-info .jp-close {
-			position: absolute;
-			top: 18px;
-			right: 0;
-			background: #888;
-			background: rgba(0,0,0,0.4);
-			color: #fff;
-			font-size: 14px !important;
-			height: 22px;
-			line-height: 20px;
-			padding: 0 6px 0 6px;
-			font-weight: bold !important;
-			-moz-border-radius: 3px;
-			-webkit-border-radius: 3px;
-			border-radius: 3px;
-			-moz-border-radius-topright: 0;
-			-moz-border-radius-bottomright: 0;
-			-webkit-border-top-right-radius: 0;
-			-webkit-border-bottom-right-radius: 0;
-			border-top-right-radius: 0;
-			border-bottom-right-radius: 0;
-			cursor: pointer;
-			text-shadow: 0 1px 0 rgba(0,0,0,0.2);
-		}
-			.more-info .jp-close:hover {
-				background: #69acce;
-			}
-
-		.more-info div.jp-info-img {
-			float: right;
-			width: 320px;
-			margin: 0 30px 0 20px;
-		}
-
-		.more-info img.jp-info-img {
-			padding: 3px;
-			background: rgba( 255, 255, 255, 0.65 );
-			border: 5px solid #ddd;
-		}
+.more-info img.jp-info-img {
+	padding: 3px;
+	background: rgba(255, 255, 255, 0.65);
+	border: 5px solid #ddd;
+}
 
 .jetpack-activated {
-	background: #fffff5 url( images/jp-enabled-bg.jpg ) top left repeat-x !important;
+	background: #fffff5 url(images/jp-enabled-bg.jpg) top left repeat-x !important;
 	height: 154px;
 	padding: 60px 0 0 200px !important;
 	position: relative;
@@ -442,59 +569,55 @@
 	z-index: 5;
 	position: relative;
 }
-	.jetpack-activated h3 {
-		position: relative;
-		z-index: 5;
-		color: #444;
-		font-size: 42px;
-		font-weight: bold;
-		font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-		margin: 0;
-		padding: 0;
-		background: none;
-		display: block;
-		text-transform: uppercase;
-	}
-	.jetpack-activated p {
-		position: relative;
-		z-index: 3;
-		top: 3px;
-		left: 10px;
-		font-size: 16px;
-		font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-		font-weight: normal;
-		color: #666;
-		background: rgba( 255, 255, 255, 0.75 );
-		padding: 7px 10px 6px;
-		-moz-border-radius: 5px;
-		-webkit-border-radius: 5px;
-		border-radius: 5px;
-		display: inline-block;
-	}
-	.jetpack-activated .jetpack {
-		position: absolute;
-		top: 0;
-		left: 0;
-		width: 238px;
-		height: 214px;
-		background: url( images/jp-enabled-jetpack.jpg ) top left no-repeat;
-		z-index: 2;
-	}
-	.jetpack-activated .clouds {
-		position: absolute;
-		right: 0;
-		bottom: 0;
-		width: 566px;
-		height: 214px;
-		background: url( images/jp-enabled-clouds.png ) bottom left no-repeat;
-		z-index: 0;
-		-webkit-border-bottom-right-radius: 5px;
-		-moz-border-radius-bottomright: 5px;
-		border-bottom-right-radius: 5px;
-		-webkit-box-shadow: inset -7px -7px 10px rgba( 0,0,0,0.05 );
-		-moz-box-shadow: inset -7px -7px 10px rgba( 0,0,0,0.05 );
-		box-shadow: inset -7px -7px 10px rgba( 0,0,0,0.05 );
-	}
+
+.jetpack-activated h3 {
+	position: relative;
+	z-index: 5;
+	color: #444;
+	font-size: 42px;
+	font-weight: bold;
+	margin: 0;
+	padding: 0;
+	background: none;
+	display: block;
+	text-transform: uppercase;
+}
+
+.jetpack-activated p {
+	position: relative;
+	z-index: 3;
+	top: 3px;
+	left: 10px;
+	font-size: 16px;
+	font-weight: normal;
+	color: #666;
+	background: rgba(255, 255, 255, 0.75);
+	padding: 7px 10px 6px;
+	border-radius: 5px;
+	display: inline-block;
+}
+
+.jetpack-activated .jetpack {
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 238px;
+	height: 214px;
+	background: url(images/jp-enabled-jetpack.jpg) top left no-repeat;
+	z-index: 2;
+}
+
+.jetpack-activated .clouds {
+	position: absolute;
+	right: 0;
+	bottom: 0;
+	width: 566px;
+	height: 214px;
+	background: url(images/jp-enabled-clouds.png) bottom left no-repeat;
+	z-index: 0;
+	border-bottom-right-radius: 5px;
+	box-shadow: inset -7px -7px 10px rgba(0, 0, 0, 0.05);
+}
 
 p.jp-help {
 	padding: 10px 0 15px;
@@ -515,346 +638,397 @@ p.jp-help {
 	max-height: 220px;
 	margin: 0 0 15px 15px;
 	border: 1px solid #dedede;
-	-moz-border-radius: 3px;
-	-webkit-border-radius: 3px;
 	border-radius: 3px;
 	background: #fff;
 	padding: 15px 0 35px 15px;
-	-webkit-box-shadow: inset 0 1px 0 #fff, inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
-	-moz-box-shadow: inset 0 1px 0 #fff, inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
-	box-shadow: inset 0 1px 0 #fff, inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
-	-webkit-transition-duration: .4s;
-	-moz-transition-duration: .4s
+	box-shadow: inset 0 1px 0 #fff,
+	            inset 0 0 20px rgba(0, 0, 0, 0.05),
+	            0 1px 2px rgba(0, 0, 0, 0.1);
+	-webkit-transition-duration: 0.4s;
+	transition-duration:         0.4s;
 }
+
 /*
-	.jetpack-module:hover {
-		border-color: #bbb;
-		-webkit-box-shadow: 0 1px 2px rgba( 0,0,0,0.2 );
-		-moz-box-shadow: 0 1px 2px rgba( 0,0,0,0.2 );
-		box-shadow: 0 1px 2px rgba( 0,0,0,0.2 );
-		-webkit-transition-duration: .4s;
-		-moz-transition-duration: .4s
-	}
+.jetpack-module:hover {
+	border-color: #bbb;
+	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+	-webkit-transition-duration: 0.4s;
+	transition-duration:         0.4s;
+}
 */
+
+.jetpack-module div.module-image {
+	float: right;
+	margin: 0 0 5px 10px;
+	padding: 60px 0 0;
+	background: #cbe0a1;
+	width: 80px;
+	border-top-left-radius: 3px;
+	border-bottom-left-radius: 3px;
+	background-repeat: no-repeat;
+	background-image: url(images/module-icons-sprite.png);
+	background-size: 2705px 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 {
-		float: right;
-		margin: 0 0 5px 10px;
-		padding: 60px 0 0;
-		background: #cbe0a1;
-		width: 80px;
-		-webkit-border-top-left-radius: 3px;
-		-moz-border-radius-topleft: 3px;
-		border-top-left-radius: 3px;
-		-webkit-border-bottom-left-radius: 3px;
-		-moz-border-radius-bottomleft: 3px;
-		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! */
+		background-image: url(images/module-icons-sprite-2x.png);
 	}
 
+}
 
-	@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 );
-		}
-	}
+#stats.jetpack-module div.module-image {
+	background-position: -510px 5px;
+}
 
-		#stats.jetpack-module div.module-image {
-			background-position: -510px 5px;
-		}
-		#comments.jetpack-module div.module-image {
-			background-position: -1210px 5px;
-		}
-		#subscriptions.jetpack-module div.module-image {
-			background-position: -1009px 5px;
-		}
-		#sharedaddy.jetpack-module div.module-image {
-			background-position: -710px 5px;
-		}
-		#after-the-deadline.jetpack-module div.module-image {
-			background-position: -308px 5px;
-		}
-		#vaultpress.jetpack-module div.module-image {
-			background-position: -910px 5px;
-		}
-		#gravatar-hovercards.jetpack-module div.module-image {
-			background-position: -410px 5px;
-		}
-		#contact-form.jetpack-module div.module-image {
-			background-position: -1107px 5px;
-		}
-		#shortlinks.jetpack-module div.module-image {
-			background-position: -108px 5px;
-		}
-		#shortcodes.jetpack-module div.module-image {
-			background-position: -608px 5px;
-		}
-		#latex.jetpack-module div.module-image {
-			background-position: -208px 5px;
-		}
-		#widgets.jetpack-module div.module-image {
-			background-position: -5px 5px;
-		}
-		#enhanced-distribution.jetpack-module div.module-image {
-			background-position: -808px 5px;
-		}
-		#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;
-			color: #fff;
-			text-shadow: 1px 1px 0px rgba(0,0,0,0.2);
-			text-align: center;
-			margin: 0;
-			padding: 0;
-			clear: both;
-			font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-			font-weight: bold;
-			-webkit-font-smoothing: antialiased;
-			-webkit-border-bottom-left-radius: 2px;
-			-moz-border-radius-bottomleft: 2px;
-			border-bottom-left-radius: 2px;
-		}
-
-		.jetpack-new-module div.module-image p {
-			background-color: #f5bd4d;
-		}
-
-		.jetpack-updated-module div.module-image p {
-			background-color: #6aafcf;
-		}
-
-		.jetpack-new-module:hover div.module-image p {
-			background-color: #b4d278;
-		}
-
-		.jetpack-updated-module:hover div.module-image p {
-			background-color: #b4d278;
-		}
-
-		.jetpack-new-module:hover div.module-image span.module-image-free,
-		.jetpack-updated-module:hover div.module-image span.module-image-free {
-			display: inline !important;
-		}
-
-		.jetpack-new-module:hover div.module-image span.module-image-badge,
-		.jetpack-updated-module:hover div.module-image span.module-image-badge {
-			display: none;
-		}
-
-	.jetpack-toggle {
-		float: right;
-		padding: 2px 4px 4px;
-	}
-		.jetpack-toggle a {
-			text-decoration: none;
-			font-weight: bold;
-			font-size: 180%;
-			color: #bbb;
-		}
-
-		.jetpack-active .jetpack-toggle-button:hover { color: #b90000;  }
-
-	.jetpack-module h3 {
-		line-height: 1.1;
-		margin: 0;
-		padding: 0;
-		font-size: 17px;
-		font-weight: normal;
-		font-style: normal;
-		color: #000;
-		font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-	}
+#comments.jetpack-module div.module-image {
+	background-position: -1210px 5px;
+}
 
-	.jetpack-module-description p {
-		line-height: 150%;
-		font-size: 12px;
-		font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
-		margin-bottom: 20px;
-		color: #666;
-	}
+#subscriptions.jetpack-module div.module-image {
+	background-position: -1009px 5px;
+}
 
-	.jetpack-module .jetpack-module-actions {
-		position: absolute;
-		bottom: 20px;
-		left: 15px;
-		background: #fff;
-		display: block;
-	}
+#sharedaddy.jetpack-module div.module-image {
+	background-position: -710px 5px;
+}
 
-		.jetpack-module .jetpack-module-actions a {
-			position: relative;
-			font-weight: bold;
-			color: #888;
-			font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-		}
+#after-the-deadline.jetpack-module div.module-image {
+	background-position: -308px 5px;
+}
 
-	.jetpack-inactive {
-		border-color: #eee;
-		cursor: pointer;
-	}
-		.jetpack-inactive *, jetpack-inactive:hover * { -webkit-transition-duration: .4s; -moz-transition-duration: .4s }
+#vaultpress.jetpack-module div.module-image {
+	background-position: -910px 5px;
+}
+
+#gravatar-hovercards.jetpack-module div.module-image {
+	background-position: -410px 5px;
+}
+
+#contact-form.jetpack-module div.module-image {
+	background-position: -1107px 5px;
+}
+
+#shortlinks.jetpack-module div.module-image {
+	background-position: -108px 5px;
+}
+
+#shortcodes.jetpack-module div.module-image {
+	background-position: -608px 5px;
+}
+
+#latex.jetpack-module div.module-image {
+	background-position: -208px 5px;
+}
+
+#widgets.jetpack-module div.module-image {
+	background-position: -5px 5px;
+}
+
+#enhanced-distribution.jetpack-module div.module-image {
+	background-position: -808px 5px;
+}
+
+#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;
+}
+
+#debug.jetpack-module div.module-image {
+	background-position: -2550px 5px;
+}
+
+#omnisearch.jetpack-module div.module-image {
+	background-position: -2625px 5px;
+}
+
+.jetpack-module div.module-image p {
+	background-color: #b4d278;
+	color: #fff;
+	text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
+	text-align: center;
+	margin: 0;
+	padding: 0;
+	clear: both;
+	font-weight: bold;
+	-webkit-font-smoothing: antialiased;
+	border-bottom-left-radius: 2px;
+}
 
-		.jetpack-inactive h3, .jetpack-inactive p, .jetpack-inactive span {
-			color: #ccc;
-		}
+.jetpack-new-module div.module-image p {
+	background-color: #f5bd4d;
+}
 
-		.jetpack-inactive .jetpack-configure-button { display: none; }
-		.jetpack-inactive div.module-image {
-			opacity: 0.6;
-		}
+.jetpack-updated-module div.module-image p {
+	background-color: #6aafcf;
+}
 
-		.jetpack-inactive .jetpack-module-description p a {
-			color: #92b8d0;
-		}
-			.jetpack-inactive:hover .jetpack-module-description p a {
-				color: #5590b7;
-			}
+.jetpack-new-module:hover div.module-image p {
+	background-color: #b4d278;
+}
 
+.jetpack-updated-module:hover div.module-image p {
+	background-color: #b4d278;
+}
 
-		.jetpack-inactive:hover {
-			border-color: #ddd;
-		}
+.jetpack-new-module:hover div.module-image span.module-image-free,
+.jetpack-updated-module:hover div.module-image span.module-image-free {
+	display: inline !important;
+}
 
-		.jetpack-inactive:hover h3, .jetpack-inactive:hover p, .jetpack-inactive:hover span {
-			color: #aaa;
-		}
+.jetpack-new-module:hover div.module-image span.module-image-badge,
+.jetpack-updated-module:hover div.module-image span.module-image-badge {
+	display: none;
+}
 
-		.jetpack-inactive:hover div.module-image {
-			opacity: 0.75;
-		}
+.jetpack-toggle {
+	float: right;
+	padding: 2px 4px 4px;
+}
 
-	.placeholder {
-		border-color: #eee !important;
-		cursor: default !important;
+.jetpack-toggle a {
+	text-decoration: none;
+	font-weight: bold;
+	font-size: 180%;
+	color: #bbb;
+}
+
+.jetpack-active .jetpack-toggle-button:hover {
+	color: #b90000;
+}
+
+.jetpack-module h3 {
+	line-height: 1.1;
+	margin: 0;
+	padding: 0;
+	font-size: 17px;
+	font-weight: normal;
+	font-style: normal;
+	color: #000;
+}
+
+.jetpack-module-description p {
+	line-height: 150%;
+	font-size: 12px;
+	margin-bottom: 20px;
+	color: #666;
+}
+
+.jetpack-module .jetpack-module-actions {
+	position: absolute;
+	bottom: 20px;
+	left: 15px;
+	background: #fff;
+	display: block;
+}
+
+.jetpack-module .jetpack-module-actions a {
+	position: relative;
+	font-weight: bold;
+	color: #888;
+}
+
+.jetpack-inactive {
+	border-color: #eee;
+	cursor: pointer;
+}
+
+.jetpack-inactive *,
+jetpack-inactive:hover * {
+	-webkit-transition-duration: 0.4s;
+	transition-duration:         0.4s;
+}
+
+.jetpack-inactive h3, .jetpack-inactive p, .jetpack-inactive span {
+	color: #ccc;
+}
+
+.jetpack-inactive .jetpack-configure-button {
+	display: none;
+}
+
+.jetpack-inactive div.module-image {
+	opacity: 0.6;
+}
+
+.jetpack-inactive .jetpack-module-description p a {
+	color: #92b8d0;
+}
+
+.jetpack-inactive:hover .jetpack-module-description p a {
+	color: #5590b7;
+}
+
+.jetpack-inactive:hover {
+	border-color: #ddd;
+}
+
+.jetpack-inactive:hover h3,
+.jetpack-inactive:hover p,
+.jetpack-inactive:hover span {
+	color: #aaa;
+}
+
+.jetpack-inactive:hover div.module-image {
+	opacity: 0.75;
+}
+
+.placeholder {
+	border-color: #eee !important;
+	cursor: default !important;
+}
+
+.placeholder h3 {
+	color: #dadada;
+	margin-top: 55px;
+	text-align: center;
+	background: transparent url(images/icon-comingsoon.png) top center no-repeat;
+	padding: 40px 0 0 0;
+	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-image: url(images/icon-comingsoon-2x.png);
+		background-size: 32px 32px;
 	}
 
-		.placeholder h3 {
-			color: #dadada;
-			margin-top: 55px;
-			text-align: center;
-			background: transparent url(images/icon-comingsoon.png) top center no-repeat;
-			padding: 40px 0 0 0;
-			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;
-		    	background-size:32px 32px;
-		    }
-		}
+}
 
 #jp-settings-screen {
 	margin: 0 25px;
 }
-	#jp-settings-screen h3 {
-		font-size: 18px;
-		font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
-		color: #555;
-		padding-bottom: 20px;
-		border-bottom: 1px solid #eee;
-	}
+
+#jp-settings-screen h3 {
+	font-size: 18px;
+	color: #555;
+	padding-bottom: 20px;
+	border-bottom: 1px solid #eee;
+}
 
 p#news-sub {
 	text-align: center;
 }
 
 #jp-footer {
-	background: url( images/footer-clouds.png ) top center no-repeat;
+	background: url(images/footer-clouds.png) top center no-repeat;
 	margin: 30px 0;
 	padding-top: 60px;
 	text-align: center;
 }
 
-@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-footer  {
-    	background: url( images/footer-clouds-2x.png ) top center no-repeat;
-		background-size:700px 150px;
-    }
+@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-footer  {
+		background-image: url(images/footer-clouds-2x.png);
+		background-size: 700px 150px;
+	}
+
 }
 
+#jp-footer .automattic {
+	color: #999;
+	font-size: 10px;
+	line-height: 15px;
+	text-transform: uppercase;
+	letter-spacing: 3px;
+	padding-left: 3px;
+}
 
-	#jp-footer .automattic {
-		color: #999;
-		font-size: 10px;
-		line-height: 15px;
-		text-transform: uppercase;
-		letter-spacing: 3px;
-		padding-left: 3px;
-	}
+#jp-footer .automattic span {
+	text-indent: -999em;
+	overflow: hidden;
+	background: url(images/automattic.png) center top no-repeat;
+	display: inline-block;
+	width: 165px;
+	vertical-align: top;
+	margin: 0 5px 0 1px;
+	line-height: 14px;
+	height: 14px;
+	filter: alpha(opacity=40);
+	-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
+	opacity: 0.5;
+}
 
-		#jp-footer .automattic span {
-			text-indent: -999em;
-			overflow: hidden;
-			background: url( images/automattic.png ) center top no-repeat;
-			display: inline-block;
-			width: 165px;
-			vertical-align: top;
-			margin: 0 5px 0 1px;
-			line-height: 14px;
-			height: 14px;
-			filter: alpha(opacity=40);
-			-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
-			opacity: 0.5;
-		}
-		@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-footer .automattic span  {
-		    	background: url( images/automattic-2x.png ) center top no-repeat;
-				background-size:165px 14px;
-		    }
-		}
-
-	#jp-footer p.small {
-		font-size: 11px;
-		color: #ccc;
+@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-footer .automattic span  {
+		background-image: url(images/automattic-2x.png);
+		background-size: 165px 14px;
 	}
 
-		#jp-footer .small a {
-			text-decoration: none;
-		}
+}
 
-		#jp-footer .small a:hover {
-			text-decoration: underline;
-		}
+#jp-footer p.small {
+	font-size: 11px;
+	color: #ccc;
+}
+
+#jp-footer .small a {
+	text-decoration: none;
+}
+
+#jp-footer .small a:hover {
+	text-decoration: underline;
+}
 
 #jetpack-configuration code {
 	font-size: 14px;
@@ -864,7 +1038,11 @@ p#news-sub {
 	clear: both;
 }
 
-.error, .updated { position: relative; z-index: 100; }
+.error,
+.updated {
+	position: relative;
+	z-index: 100;
+}
 
 .toplevel_page_jetpack .wrap {
 	max-width: 983px;
@@ -880,29 +1058,24 @@ p#news-sub {
 	position: relative;
 	z-index: 100;
 	border: 1px solid #ccc !important;
-	-moz-border-radius: 3px;
-	-webkit-border-radius: 3px;
 	border-radius: 3px;
 	background-color: #efefef !important;
-	-webkit-box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
-	-moz-box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
-	box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
+	box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.04);
 	padding: 18px 90px 8px 15px !important;
 	overflow: hidden;
 	line-height: 180%;
 }
 
-#jetpack-settings > .jp-survey { margin: 10px 13px 40px 15px }
+#jetpack-settings > .jp-survey {
+	margin: 10px 13px 40px 15px;
+}
 
 .jp-survey h4 {
 	margin: 0;
 	font-size: 18px;
-	font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
 	font-weight: normal;
 	color: #333;
 	text-shadow: 0 1px 0 #fff;
-	-moz-border-radius: 5px;
-	-webkit-border-radius: 5px;
 	border-radius: 5px;
 	display: block;
 	float: left;
@@ -942,50 +1115,40 @@ p#news-sub {
 	width: 16px;
 	height: 16px;
 	text-indent: -9999px;
-	background: transparent url( images/alertbox-closeicon.png ) no-repeat center center;
+	background: transparent url(images/alertbox-closeicon.png) center center no-repeat;
 	border: 0 none;
-	-moz-border-radius: 0 0 0 5px;
-	-webkit-border-radius: 0 0 0 5px;
-	-o-border-radius: 0 0 0 5px;
-	-ms-border-radius: 0 0 0 5px;
 	border-radius: 0 0 0 5px;
-	-moz-box-shadow: none;
-	-webkit-box-shadow: none;
 	box-shadow: none;
-	-webkit-transition-duration: .3s;
-	-moz-transition-duration: .3s;
-	-o-transition-duration: .3s;
-	-ms-transition-duration: .3s;
-	transition-duration: .3s;
+	-webkit-transition-duration: 0.3s;
+	transition-duration:         0.3s;
 	cursor: pointer;
 }
 
-@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-close-button  {
-    	background: transparent url( images/alertbox-closeicon-2x.png ) no-repeat center center;
-		background-size:16px 16px;
-    }
+@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-close-button  {
+		background-image: url(images/alertbox-closeicon-2x.png);
+		background-size: 16px 16px;
+	}
+
 }
 
 .jetpack-close-button:hover {
 	background-color: #fff;
 	border: 0 none;
 	outline: none;
-	-webkit-transition-duration: .3s;
-	-moz-transition-duration: .3s;
-	-o-transition-duration: .3s;
-	-ms-transition-duration: .3s;
-	transition-duration: .3s;
+	-webkit-transition-duration: 0.3s;
+	transition-duration:         0.3s;
 }
 
 .jetpack-close-button:active {
 	background-color: #efefef;
 	border: 0 none;
-	-webkit-transition-duration: .3s;
-	-moz-transition-duration: .3s;
-	-o-transition-duration: .3s;
-	-ms-transition-duration: .3s;
-	transition-duration: .3s;
+	-webkit-transition-duration: 0.3s;
+	transition-duration:         0.3s;
 }
 
 .jetpack-wrap-container {
@@ -1002,17 +1165,13 @@ p#news-sub {
 	position: absolute;
 	bottom: 5px;
 	right: 15px;
-	font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
 	float: right;
 	display: inline-block;
 	background: #b4d278;
-	-moz-box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
-	-webkit-box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
-	box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
+	box-shadow: inset 0 0 2px #fff,
+	            0 1px 5px rgba(0, 0, 0, 0.3);
 	padding: 8px 15px;
 	border: 1px solid #2a8cba;
-	-moz-border-radius: 5px;
-	-webkit-border-radius: 5px;
 	border-radius: 5px;
 	line-height: 1.3;
 	color: #fff;
@@ -1020,26 +1179,23 @@ p#news-sub {
 	font-size: 16px;
 	font-weight: bold;
 	text-decoration: none;
-	text-shadow: 0px 1px 2px rgba( 0,0,0,0.5);
-	-webkit-transition-duration: .3s;
-	-moz-transition-duration: .3s;
+	text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
+	-webkit-transition-duration: 0.3s;
+	transition-duration:         0.3s;
 	cursor: pointer;
 }
 
-.jetpack-install-container p a.button-connector:hover, .jetpack-install-container p a.button-connector:active {
+.jetpack-install-container p a.button-connector:hover,
+.jetpack-install-container p a.button-connector:active {
 	background-color: #f0a000;
 	border-color: #c87800;
-	-webkit-transition-duration: .3s;
 	outline: none;
-	-moz-box-shadow: inset 0 0 2px #fff, 0 1px 7px rgba(240,160,0,0.5);
-	-webkit-box-shadow: inset 0 0 2px #fff, 0 1px 7px rgba(240,160,0,0.5);
-	box-shadow: inset 0 0 2px #fff, 0 1px 7spx rgba(240,160,0,0.5);
+	box-shadow: inset 0 0 2px #fff,
+	            0 1px 7px 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;
+	padding: 0.5em 1em 0.5em 1em;
 	border-radius: 3px;
 	border-width: 1px;
 	border-style: solid;

diff --git a/plugins/jetpack/_inc/jetpack.js b/plugins/jetpack/_inc/jetpack.js
index 6ef9de8..4d70053 100644
--- a/plugins/jetpack/_inc/jetpack.js
+++ b/plugins/jetpack/_inc/jetpack.js
@@ -80,6 +80,7 @@ jetpack = {
 			}
 		} );
 
+		jQuery( '#screen-meta, #screen-meta-links' ).wrapAll( '<div class="screen-meta-wrap" />' );
 	},
 
 	level_modules: function() {

diff --git a/plugins/jetpack/_inc/jquery.inview.js b/plugins/jetpack/_inc/jquery.inview.js
index 45f71c4..b581903 100644
--- a/plugins/jetpack/_inc/jquery.inview.js
+++ b/plugins/jetpack/_inc/jquery.inview.js
@@ -73,14 +73,14 @@
             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();
@@ -98,7 +98,7 @@
         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 &&
@@ -124,7 +124,7 @@
   $(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() {

diff --git a/plugins/jetpack/_inc/jquery.jetpack-resize.js b/plugins/jetpack/_inc/jquery.jetpack-resize.js
index e1adb22..1c3cc87 100644
--- a/plugins/jetpack/_inc/jquery.jetpack-resize.js
+++ b/plugins/jetpack/_inc/jquery.jetpack-resize.js
@@ -60,7 +60,7 @@
 	if ( 'undefined' === typeof $.fn.Jetpack ) {
 		/**
 		 * Dispatches calls to the correct namespace
-		 * 
+		 *
 		 * @param string namespace
 		 * @param ...
 		 * @return mixed|jQuery (chainable)
@@ -81,7 +81,7 @@
 			/**
 			 * Defines the Jetpack.resizeable() namespace.
 			 * See below for non-trivial definition for browsers with postMessage.
-			 */ 
+			 */
 			resizeable: function() {
 				$.error( 'Browser does not support window.postMessage' );
 			}
@@ -122,7 +122,7 @@
 
 			// Some browsers send structured data, some send JSON strings
 			if ( 'object' === typeof event.data ) {
-				data = event.data;
+				data = event.data.data;
 			} else {
 				try {
 					data = JSON.parse( event.data );
@@ -131,10 +131,13 @@
 				}
 			}
 
-			if ( !data ) {
+			if ( !data.data ) {
 				return;
 			}
 
+			// Un-nest
+			data = data.data;
+
 			// Is it a resize event?
 			if ( 'undefined' === typeof data.action || 'resize' !== data.action ) {
 				return;
@@ -242,6 +245,10 @@
 
 				if ( 0 !== value ) {
 					target[variable]( value );
+					var container = target.parent();
+					if ( container.hasClass( 'slim-likes-widget' ) ) {
+						container[variable]( value );
+					}
 				}
 			} );
 
@@ -269,7 +276,7 @@
 				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
index 4642af1..1e901ca 100644
--- a/plugins/jetpack/_inc/jquery.spin.js
+++ b/plugins/jetpack/_inc/jquery.spin.js
@@ -1,86 +1,104 @@
-/*
- * Matt Husby https://github.com/matthusby/spin.js
- * Based on the jquery plugin by Bradley Smith
- * https://gist.github.com/1290439
+/**
+ * Copyright (c) 2011-2013 Felix Gnass
+ * Licensed under the MIT license
  */
 
 /*
-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.
+
+Basic Usage:
+============
+
+$('#el').spin(); // Creates a default Spinner using the text color of #el.
+$('#el').spin({ ... }); // Creates a Spinner using the provided options.
+
+$('#el').spin(false); // Stops and removes the spinner.
+
+Using Presets:
+==============
+
+$('#el').spin('small'); // Creates a 'small' Spinner using the text color of #el.
+$('#el').spin('large', '#fff'); // Creates a 'large' white Spinner.
+
+Adding a custom preset:
+=======================
+
+$.fn.spin.presets.flower = {
+  lines: 9
+  length: 10
+  width: 20
+  radius: 0
+}
+
+$('#el').spin('flower', 'red');
+
 */
 
-( 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
+(function(factory) {
+
+  if (typeof exports == 'object') {
+    // CommonJS
+    factory(require('jquery'), require('spin'))
+  }
+  else if (typeof define == 'function' && define.amd) {
+    // AMD, register as anonymous module
+    define(['jquery', 'spin'], factory)
+  }
+  else {
+    // Browser globals
+    if (!window.Spinner) throw new Error('Spin.js not present')
+    factory(window.jQuery, window.Spinner)
+  }
+
+}(function($, Spinner) {
+
+  $.fn.spin = function(opts, color) {
+
+    return this.each(function() {
+      var $this = $(this),
+        data = $this.data();
+
+      if (data.spinner) {
+        data.spinner.stop();
+        delete data.spinner;
+      }
+      if (opts !== false) {
+        opts = $.extend(
+          { color: color || $this.css('color') },
+          $.fn.spin.presets[opts] || opts
+        )
+        // Begin WordPress Additions
+        // To use opts.right, you need to have specified a length, width, and radius.
+        if ( typeof opts.right !== 'undefined' && typeof opts.length !== 'undefined'
+          && typeof opts.width !== 'undefined' && typeof opts.radius !== 'undefined' ) {
+          var pad = $this.css( 'padding-left' );
+          pad = ( typeof pad === 'undefined' ) ? 0 : parseInt( pad, 10 );
+          opts.left = $this.outerWidth() - ( 2 * ( opts.length + opts.width + opts.radius ) ) - pad - opts.right;
+          delete opts.right;
+        }
+        // End WordPress Additions
+        data.spinner = new Spinner(opts).spin(this)
+      }
+    })
+  }
+
+  $.fn.spin.presets = {
+    tiny: { lines: 8, length: 2, width: 2, radius: 3 },
+    small: { lines: 8, length: 4, width: 3, radius: 5 },
+    large: { lines: 10, length: 8, width: 4, radius: 8 }
+  }
+
+}));
+
+// Jetpack Presets Overrides:
+(function($){
+	$.fn.spin.presets.wp = { trail: 60, speed: 1.3 };
+	$.fn.spin.presets.small  = $.extend( { lines:  8, length: 2, width: 2, radius: 3 }, $.fn.spin.presets.wp );
+	$.fn.spin.presets.medium = $.extend( { lines:  8, length: 4, width: 3, radius: 5 }, $.fn.spin.presets.wp );
+	$.fn.spin.presets.large  = $.extend( { lines: 10, length: 6, width: 4, radius: 7 }, $.fn.spin.presets.wp );
+	$.fn.spin.presets['small-left']   = $.extend( { left:  5 }, $.fn.spin.presets.small );
+	$.fn.spin.presets['small-right']  = $.extend( { right: 5 }, $.fn.spin.presets.small );
+	$.fn.spin.presets['medium-left']  = $.extend( { left:  5 }, $.fn.spin.presets.medium );
+	$.fn.spin.presets['medium-right'] = $.extend( { right: 5 }, $.fn.spin.presets.medium );
+	$.fn.spin.presets['large-left']   = $.extend( { left:  5 }, $.fn.spin.presets.large );
+	$.fn.spin.presets['large-right']  = $.extend( { right: 5 }, $.fn.spin.presets.large );
+})(jQuery);

diff --git a/plugins/jetpack/_inc/postmessage.js b/plugins/jetpack/_inc/postmessage.js
index e8933bc..51f8567 100644
--- a/plugins/jetpack/_inc/postmessage.js
+++ b/plugins/jetpack/_inc/postmessage.js
@@ -105,7 +105,7 @@ var NO_JQUERY = {};
          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();
@@ -243,7 +243,7 @@ var NO_JQUERY = {};
                            pm.send({target:e.source, data:data, type:msg.callback});
                        }
                      }
-                     
+
                      try {
                          if ( o.callback ) {
                            o.fn(msg.data, sendReply, e);
@@ -390,7 +390,7 @@ var NO_JQUERY = {};
                          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);

diff --git a/plugins/jetpack/_inc/spin.js b/plugins/jetpack/_inc/spin.js
index f506cd2..c66c607 100644
--- a/plugins/jetpack/_inc/spin.js
+++ b/plugins/jetpack/_inc/spin.js
@@ -1,301 +1,349 @@
-//fgnass.github.com/spin.js#v1.2.4
-(function(window, document, undefined) {
+//fgnass.github.com/spin.js#v1.3
 
 /**
- * Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de]
+ * Copyright (c) 2011-2013 Felix Gnass
  * 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
+(function(root, factory) {
+
+  /* CommonJS */
+  if (typeof exports == 'object')  module.exports = factory()
+
+  /* AMD module */
+  else if (typeof define == 'function' && define.amd) define(factory)
+
+  /* Browser global */
+  else root.Spinner = factory()
+}
+(this, function() {
+  "use strict";
+
+  var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
+    , animations = {} /* Animation rules keyed by their name */
+    , useCssAnimations /* Whether to use CSS animations or setTimeout */
+
+  /**
+   * 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')
+      , 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', {type : 'text/css'})
+    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('-')
+      , start = 0.01 + i/lines * 100
+      , z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
+      , prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
+      , 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 + '}' +
+        '}', sheet.cssRules.length)
+
+      animations[name] = 1
+    }
+
+    return name
+  }
+
+  /**
+   * Tries various vendor prefixes and returns the first supported property.
+   */
+  function vendor(el, prop) {
+    var s = el.style
+      , pp
+      , 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
+  }
+
+  // Built-in defaults
+
+  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
+    rotate: 0,            // Rotation offset
+    corners: 1,           // Roundness (0..1)
+    color: '#000',        // #rgb or #rrggbb
+    direction: 1,         // 1: clockwise, -1: counterclockwise
+    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
+    position: 'relative'  // element position
+  }
+
+  /** The constructor */
+  function Spinner(o) {
+    if (typeof this == 'undefined') return new Spinner(o)
+    this.opts = merge(o || {}, Spinner.defaults, defaults)
+  }
+
+  // Global defaults that override the built-ins:
+  Spinner.defaults = {}
+
+  merge(Spinner.prototype, {
+
+    /**
+     * Adds the spinner to the given target element. If this instance is already
+     * spinning, it is automatically removed from its previous target b calling
+     * stop() internally.
+     */
+    spin: function(target) {
+      this.stop()
+
+      var self = this
+        , o = self.opts
+        , el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex})
+        , mid = o.radius+o.length+o.width
+        , ep // element position
+        , 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) : parseInt(o.left, 10) + mid) + 'px',
+          top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid)  + 'px'
+        })
+      }
+
+      el.setAttribute('role', 'progressbar')
+      self.lines(el, self.opts)
+
+      if (!useCssAnimations) {
+        // No CSS animation support, use setTimeout() instead
+        var i = 0
+          , start = (o.lines - 1) * (1 - o.direction) / 2
+          , alpha
+          , fps = o.fps
+          , f = fps/o.speed
+          , ostep = (1-o.opacity) / (f*o.trail / 100)
+          , astep = f/o.lines
+
+        ;(function anim() {
+          i++;
+          for (var j = 0; j < o.lines; j++) {
+            alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)
+
+            self.opacity(el, j * o.direction + start, alpha, o)
+          }
+          self.timeout = self.el && setTimeout(anim, ~~(1000/fps))
+        })()
+      }
+      return self
+    },
+
+    /**
+     * Stops and removes the Spinner.
+     */
+    stop: function() {
+      var el = this.el
+      if (el) {
+        clearTimeout(this.timeout)
+        if (el.parentNode) el.parentNode.removeChild(el)
+        this.el = undefined
+      }
+      return this
+    },
+
+    /**
+     * Internal method that draws the individual lines. Will be overwritten
+     * in VML fallback mode below.
+     */
+    lines: function(el, o) {
+      var i = 0
+        , start = (o.lines - 1) * (1 - o.direction) / 2
+        , 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+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
+          borderRadius: (o.corners * 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, start + i * o.direction, 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
+    },
+
+    /**
+     * Internal method that adjusts the opacity of a single line.
+     * Will be overwritten in VML fallback mode below.
+     */
+    opacity: function(el, i, val) {
+      if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
+    }
+
+  })
+
+
+  function initVML() {
+
+    /* Utility function to create a VML tag */
+    function vml(tag, attr) {
+      return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
+    }
+
+    // No CSS transforms but VML support, add a CSS rule for VML elements:
+    sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')
+
+    Spinner.prototype.lines = function(el, o) {
+      var r = o.length+o.width
+        , s = 2*r
+
+      function grp() {
+        return css(
+          vml('group', {
+            coordsize: s + ' ' + s,
+            coordorigin: -r + ' ' + -r
+          }),
+          { width: s, height: s }
+        )
+      }
+
+      var margin = -(o.width+o.length)*2 + 'px'
+        , g = css(grp(), {position: 'absolute', top: margin, left: margin})
+        , i
+
+      function seg(i, dx, filter) {
+        ins(g,
+          ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
+            ins(css(vml('roundrect', {arcsize: o.corners}), {
+                width: r,
+                height: o.width,
+                left: o.radius,
+                top: -o.width>>1,
+                filter: filter
+              }),
+              vml('fill', {color: o.color, opacity: o.opacity}),
+              vml('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
+      }
+    }
+  }
+
+  var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})
+
+  if (!vendor(probe, 'transform') && probe.adj) initVML()
+  else useCssAnimations = vendor(probe, 'animation')
+
+  return Spinner
+
+}));

diff --git a/plugins/jetpack/class.jetpack-ixr-client.php b/plugins/jetpack/class.jetpack-ixr-client.php
index 8d6e52f..7eefee5 100644
--- a/plugins/jetpack/class.jetpack-ixr-client.php
+++ b/plugins/jetpack/class.jetpack-ixr-client.php
@@ -49,7 +49,7 @@ class Jetpack_IXR_Client extends IXR_Client {
 			$this->error = new IXR_Error( -32300, 'transport error - HTTP status code was not 200' );
 			return false;
 		}
-		
+
 		$content = wp_remote_retrieve_body( $response );
 
 		// Now parse what we've got back

diff --git a/plugins/jetpack/class.jetpack-post-images.php b/plugins/jetpack/class.jetpack-post-images.php
index afdcacf..5829fcc 100644
--- a/plugins/jetpack/class.jetpack-post-images.php
+++ b/plugins/jetpack/class.jetpack-post-images.php
@@ -15,15 +15,17 @@ 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 ) {
+		$images = array();
+
 		$post = get_post( $post_id );
+		if ( !empty( $post->post_password ) )
+			return $images;
 
 		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;
@@ -79,15 +81,17 @@ class Jetpack_PostImages {
 	 * If a gallery is detected, then get all the images from it.
 	 */
 	static function from_gallery( $post_id ) {
+		$images = array();
+
 		$post = get_post( $post_id );
+		if ( !empty( $post->post_password ) )
+			return $images;
 
 		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;
@@ -145,6 +149,11 @@ class Jetpack_PostImages {
 	 * their dimensions are at or above a required minimum.
 	 */
 	static function from_attachment( $post_id, $width = 200, $height = 200 ) {
+		$images = array();
+
+		$post = get_post( $post_id );
+		if ( !empty( $post->post_password ) )
+			return $images;
 
 		$post_images = get_posts( array(
 			'post_parent' => $post_id,   // Must be children of post
@@ -158,8 +167,6 @@ class Jetpack_PostImages {
 
 		$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
@@ -210,9 +217,12 @@ class Jetpack_PostImages {
 	static function from_thumbnail( $post_id, $width = 200, $height = 200 ) {
 		$images = array();
 
-		if ( !function_exists( 'get_post_thumbnail_id' ) ) {
+		$post = get_post( $post_id );
+		if ( !empty( $post->post_password ) )
+			return $images;
+
+		if ( !function_exists( 'get_post_thumbnail_id' ) )
 			return $images;
-		}
 
 		$thumb = get_post_thumbnail_id( $post_id );
 
@@ -251,10 +261,12 @@ class Jetpack_PostImages {
 
 		if ( is_numeric( $html_or_id ) ) {
 			$post = get_post( $html_or_id );
-
-			if ( !$post )
+			if ( empty( $post ) || !empty( $post->post_password ) )
 				return $images;
+
 			$html = $post->post_content; // DO NOT apply the_content filters here, it will cause loops
+		} else {
+			$html = $html_or_id;
 		}
 
 		if ( !$html )

diff --git a/plugins/jetpack/class.jetpack-signature.php b/plugins/jetpack/class.jetpack-signature.php
index 975375a..3f6c16f 100644
--- a/plugins/jetpack/class.jetpack-signature.php
+++ b/plugins/jetpack/class.jetpack-signature.php
@@ -56,7 +56,7 @@ class Jetpack_Signature {
 			}
 		}
 
-		$method = isset( $override['method'] ) ? $override['method'] : $_SERVER['REQUEST_METHOD']; 
+		$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 );
 	}
 
@@ -99,7 +99,7 @@ class Jetpack_Signature {
 				return new Jetpack_Error( 'invalid_body_hash', 'The body hash does not match.' );
 			}
 		} else {
-			if ( $verify_body_hash && jetpack_sha1_base64( $body ) != $body_hash ) {
+			if ( $verify_body_hash && jetpack_sha1_base64( $body ) !== $body_hash ) {
 				return new Jetpack_Error( 'invalid_body_hash', 'The body hash does not match.' );
 			}
 		}

diff --git a/plugins/jetpack/class.jetpack-user-agent.php b/plugins/jetpack/class.jetpack-user-agent.php
index 3ae1bb8..4c63a65 100644
--- a/plugins/jetpack/class.jetpack-user-agent.php
+++ b/plugins/jetpack/class.jetpack-user-agent.php
@@ -78,6 +78,7 @@ class Jetpack_User_Agent_Info {
 	const PLATFORM_J2ME_MIDP		= 'j2me_midp';
 	const PLATFORM_ANDROID 			= 'android';
 	const PLATFORM_ANDROID_TABLET	= 'android_tablet';
+	const PLATFORM_FIREFOX_OS		= 'firefoxOS';
 
 	var $dumb_agents = array(
 		'nokia', 'blackberry', 'philips', 'samsung', 'sanyo', 'sony', 'panasonic', 'webos',
@@ -139,6 +140,8 @@ class Jetpack_User_Agent_Info {
 	   		return 'webos';
 	   	elseif ( $this->is_S60_OSSBrowser() )
 	   		return 'series60';
+	   	elseif ( $this->is_firefox_os() )
+	   	   	return 'firefoxOS';
 	   	elseif ( $this->is_firefox_mobile() )
 	   		return 'firefox_mobile';
 	   	elseif ( $this->is_MaemoTablet() )
@@ -228,6 +231,9 @@ class Jetpack_User_Agent_Info {
     elseif ( $this->is_J2ME_platform() ) {
    		$this->_platform = self::PLATFORM_J2ME_MIDP;
    	}
+   	elseif ( $this->is_firefox_os() ) {
+   		$this->_platform = self::PLATFORM_FIREFOX_OS;
+   	}
    	else
    		$this->_platform = false;
 
@@ -297,6 +303,12 @@ class Jetpack_User_Agent_Info {
 			$this->isTierRichCss = false;
 			$this->isTierGenericMobile = false;
 		}
+		elseif ( $this->is_firefox_os() ) {
+			$this->matched_agent = 'firefoxOS';
+			$this->isTierIphone = true;
+			$this->isTierRichCss = false;
+			$this->isTierGenericMobile = false;
+		}
 		elseif ( $this->is_firefox_mobile() ) {
 			$this->matched_agent = 'fennec';
 			$this->isTierIphone = true;
@@ -377,7 +389,7 @@ class Jetpack_User_Agent_Info {
 
 	// Detects if the user is using a tablet.
 	// props Corey Gilmore, BGR.com
-	function is_tablet() {
+	static 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()
@@ -387,14 +399,14 @@ class Jetpack_User_Agent_Info {
 				||  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(){
+	static function is_iphoneOrIpod(){
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -421,7 +433,7 @@ class Jetpack_User_Agent_Info {
 	 *  Otherwise those browsers will be 'catched' by the iphone string.
 	 *
 	 */
-	function is_iphone_or_ipod( $type = 'iphone-any' ) {
+	static function is_iphone_or_ipod( $type = 'iphone-any' ) {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -438,61 +450,61 @@ class Jetpack_User_Agent_Info {
 			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( ) {
+	static 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( ) {
+	static 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( ) {
+	static 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 )
@@ -502,7 +514,7 @@ class Jetpack_User_Agent_Info {
 		else
 			return false;
 	}
-	
+
 
 	/*
 	 * Detects if the current UA is Facebook for iPhone
@@ -510,7 +522,7 @@ class Jetpack_User_Agent_Info {
 	 * - 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( ) {
+	static function is_facebook_for_iphone( ) {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -535,7 +547,7 @@ class Jetpack_User_Agent_Info {
 	 * - 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( ) {
+	static function is_facebook_for_ipad( ) {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -553,7 +565,7 @@ class Jetpack_User_Agent_Info {
 	/*
 	 *  Detects if the current UA is WordPress for iOS
 	 */
-	function is_wordpress_for_ios( ) {
+	static function is_wordpress_for_ios( ) {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -573,7 +585,7 @@ class Jetpack_User_Agent_Info {
 	 * Otherwise those browsers will be 'catched' by the ipad string.
 	 *
 	*/
-	function is_ipad( $type = 'ipad-any' ) {
+	static function is_ipad( $type = 'ipad-any' ) {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -598,7 +610,7 @@ class Jetpack_User_Agent_Info {
 	 * 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( ) {
+	static function is_firefox_mobile( ) {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -613,6 +625,26 @@ class Jetpack_User_Agent_Info {
 
 
 	/*
+	 * Detects if the current browser is FirefoxOS Native browser
+	*
+	* Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0
+	*
+	*/
+	static function is_firefox_os( ) {
+
+		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
+			return false;
+
+		$ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
+
+		if ( strpos( $ua, 'mozilla' ) !== false && strpos( $ua, 'mobile' ) !== false && strpos( $ua, 'gecko' ) !== false && strpos( $ua, 'firefox' ) !== false)
+			return true;
+		else
+			return false;
+	}
+
+
+	/*
 	 * Detects if the current browser is Opera Mobile
 	 *
 	 * What is the difference between Opera Mobile and Opera Mini?
@@ -623,7 +655,7 @@ class Jetpack_User_Agent_Info {
 	 *
 	 * Opera/9.80 (Windows NT 6.1; Opera Mobi/14316; U; en) Presto/2.7.81 Version/11.00"
 	 */
-	function is_opera_mobile( ) {
+	static function is_opera_mobile( ) {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -649,7 +681,7 @@ class Jetpack_User_Agent_Info {
 	 * Opera/9.80 (BlackBerry; Opera Mini/5.1.22303/22.387; U; en) Presto/2.5.25 Version/10.54
 	 *
 	 */
-	function is_opera_mini( ) {
+	static function is_opera_mini( ) {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -666,7 +698,7 @@ class Jetpack_User_Agent_Info {
 	 * 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( ) {
+	static function is_opera_mini_dumb( ) {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -690,7 +722,7 @@ class Jetpack_User_Agent_Info {
 	 * 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() {
+	static function is_OperaMobile() {
 		_deprecated_function( __FUNCTION__, 'always', 'is_opera_mini() or is_opera_mobile()' );
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
@@ -712,7 +744,7 @@ class Jetpack_User_Agent_Info {
 	 * 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() {
+	static function is_WindowsPhone7() {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -732,10 +764,10 @@ class Jetpack_User_Agent_Info {
 	 * 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() {
+	static 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;
@@ -743,8 +775,8 @@ class Jetpack_User_Agent_Info {
 			return true;
 		}
 	}
-	
-	
+
+
 	/*
 	 * Detects if the current browser is on a Palm device running the new WebOS. This EXCLUDES TouchPad.
 	 *
@@ -752,7 +784,7 @@ class Jetpack_User_Agent_Info {
 	 * 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() {
+	static function is_PalmWebOS() {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -775,7 +807,7 @@ class Jetpack_User_Agent_Info {
 	 * 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() {
+	static function is_TouchPad() {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 		return false;
 
@@ -801,7 +833,7 @@ class Jetpack_User_Agent_Info {
 	 * 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() {
+	static function is_S60_OSSBrowser() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 		return false;
@@ -831,7 +863,7 @@ class Jetpack_User_Agent_Info {
 	 * Detects if the device platform is the Symbian Series 60.
 	 *
 	 */
-	function is_symbian_platform() {
+	static function is_symbian_platform() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 		return false;
@@ -864,7 +896,7 @@ class Jetpack_User_Agent_Info {
 	 * This browser will report 'NokiaBrowser' in the header, however some older version will also report 'OviBrowser'.
 	 *
 	 */
-	function is_symbian_s40_platform() {
+	static function is_symbian_s40_platform() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 		return false;
@@ -879,7 +911,7 @@ class Jetpack_User_Agent_Info {
 	    return false;
 	}
 
-	function is_J2ME_platform() {
+	static function is_J2ME_platform() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -899,7 +931,7 @@ class Jetpack_User_Agent_Info {
 	/*
 	 * Detects if the current UA is on one of the Maemo-based Nokia Internet Tablets.
 	 */
-	function is_MaemoTablet() {
+	static function is_MaemoTablet() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 		return false;
@@ -922,7 +954,7 @@ class Jetpack_User_Agent_Info {
 	/*
 	 * Detects if the current UA is a MeeGo device (Nokia Smartphone).
 	 */
-	function is_MeeGo() {
+	static function is_MeeGo() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -943,7 +975,7 @@ class Jetpack_User_Agent_Info {
 	/*
 	 is_webkit() can be used to check the User Agent for an webkit generic browser
 	 */
-	function is_webkit() {
+	static function is_webkit() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 		return false;
@@ -962,7 +994,7 @@ class Jetpack_User_Agent_Info {
      * Detects if the current browser is the Native Android browser.
      * @return boolean true if the browser is Android otherwise false
      */
-	function is_android() {
+	static function is_android() {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -985,7 +1017,7 @@ class Jetpack_User_Agent_Info {
 	 *
 	 * @return boolean true if the browser is Android and not 'mobile' otherwise false
 	 */
-	function is_android_tablet( ) {
+	static function is_android_tablet( ) {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -1012,7 +1044,7 @@ class Jetpack_User_Agent_Info {
 	 *
 	 * @return boolean true if the browser is Kindle Fire Native browser otherwise false
 	 */
-	function is_kindle_fire( ) {
+	static function is_kindle_fire( ) {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -1033,7 +1065,7 @@ class Jetpack_User_Agent_Info {
  	*
  	* @return boolean true if the browser is Kindle monochrome Native browser otherwise false
  	*/
- 	function is_kindle_touch( ) {
+ 	static function is_kindle_touch( ) {
  		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
  			return false;
  		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
@@ -1046,7 +1078,7 @@ class Jetpack_User_Agent_Info {
 
 
 	// Detect if user agent is the WordPress.com Windows 8 app (used ONLY on the custom oauth stylesheet)
-	function is_windows8_auth( ) {
+	static function is_windows8_auth( ) {
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
 
@@ -1059,10 +1091,10 @@ class Jetpack_User_Agent_Info {
 	}
 
 	// Detect if user agent is the WordPress.com Windows 8 app.
-	function is_wordpress_for_win8( ) {
+	static 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 )
@@ -1070,15 +1102,15 @@ class Jetpack_User_Agent_Info {
 		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() {
+	static function is_blackberry_tablet() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;
@@ -1099,13 +1131,13 @@ class Jetpack_User_Agent_Info {
 	 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() {
+	static 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() )
@@ -1120,7 +1152,7 @@ class Jetpack_User_Agent_Info {
 	/*
 	 is_blackberry_10() can be used to check the User Agent for a BlackBerry 10 device.
 	*/
-	function is_blackberry_10() {
+	static function is_blackberry_10() {
 		$agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
 		return ( strpos( $agent, 'bb10' ) !== false ) && ( strpos( $agent, 'mobile' ) !== false );
 	}
@@ -1141,14 +1173,14 @@ class Jetpack_User_Agent_Info {
 	 * @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() {
+	static 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' );
@@ -1223,7 +1255,7 @@ class Jetpack_User_Agent_Info {
 	 * @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() {
+	static function detect_blackberry_browser_version() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 		return false;
@@ -1232,7 +1264,7 @@ class Jetpack_User_Agent_Info {
 
 		if ( self::is_blackberry_10() )
 			return 'blackberry-10';
-		
+
 		$pos_blackberry = strpos( $agent, 'blackberry' );
 		if ( $pos_blackberry === false ) {
 			//not a blackberry device
@@ -1270,7 +1302,7 @@ class Jetpack_User_Agent_Info {
 	}
 
 	//Checks if a visitor is coming from one of the WordPress mobile apps
-	function is_mobile_app() {
+	static function is_mobile_app() {
 
 		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
 			return false;

diff --git a/plugins/jetpack/class.jetpack-xmlrpc-server.php b/plugins/jetpack/class.jetpack-xmlrpc-server.php
index 3aa5adb..fd1b893 100644
--- a/plugins/jetpack/class.jetpack-xmlrpc-server.php
+++ b/plugins/jetpack/class.jetpack-xmlrpc-server.php
@@ -30,7 +30,7 @@ class Jetpack_XMLRPC_Server {
 				'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.getComment'        => array( $this, 'get_comment' ),
 				'jetpack.getComments'       => array( $this, 'get_comments' ),
 			) );
 
@@ -158,7 +158,7 @@ class Jetpack_XMLRPC_Server {
 	function test_connection() {
 		return JETPACK__VERSION;
 	}
-	
+
 	function test_api_user_code( $args ) {
 		$client_id = (int) $args[0];
 		$user_id   = (int) $args[1];
@@ -279,7 +279,7 @@ class Jetpack_XMLRPC_Server {
 
 		return $sync_data;
 	}
-	
+
 	function update_attachment_parent( $args ) {
 		$attachment_id = (int) $args[0];
 		$parent_id     = (int) $args[1];

diff --git a/plugins/jetpack/class.json-api-endpoints.php b/plugins/jetpack/class.json-api-endpoints.php
index 6189d40..91c1480 100644
--- a/plugins/jetpack/class.json-api-endpoints.php
+++ b/plugins/jetpack/class.json-api-endpoints.php
@@ -55,7 +55,7 @@ abstract class WPCOM_JSON_API_Endpoint {
 
 	// Is this endpoint still in testing phase?  If so, not available to the public.
 	var $in_testing = false;
-	
+
 	/**
 	 * @var string Version of the API
 	 */
@@ -161,15 +161,16 @@ abstract class WPCOM_JSON_API_Endpoint {
 	// 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; charset=utf-8' :
 		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 );
+			$return = json_decode( $input, true );
+
 			if ( function_exists( 'json_last_error' ) ) {
 				if ( JSON_ERROR_NONE !== json_last_error() ) {
 					return null;
@@ -180,9 +181,6 @@ abstract class WPCOM_JSON_API_Endpoint {
 				}
 			}
 
-			if ( is_object( $return ) ) {
-				$return = (array) $return;
-			}
 			break;
 		case 'multipart/form-data' :
 			$return = array_merge( stripslashes_deep( $_POST ), $_FILES );
@@ -202,6 +200,7 @@ abstract class WPCOM_JSON_API_Endpoint {
 	function cast_and_filter( $data, $documentation, $return_default_values = false, $for_output = false ) {
 		$return_as_object = false;
 		if ( is_object( $data ) ) {
+			// @todo this should probably be a deep copy if $data can ever have nested objects
 			$data = (array) $data;
 			$return_as_object = true;
 		} elseif ( !is_array( $data ) ) {
@@ -446,6 +445,16 @@ abstract class WPCOM_JSON_API_Endpoint {
 			);
 			$return[$key] = (object) $this->cast_and_filter( $value, apply_filters( 'wpcom_json_api_attachment_cast_and_filter', $docs ), false, $for_output );
 			break;
+		case 'metadata' :
+			$docs = array(
+				'id'       => '(int)',
+				'key'       => '(string)',
+				'value'     => '(string|false|float|int|array|object)',
+				'previous_value' => '(string)',
+				'operation'  => '(string)',
+			);
+			$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 );
 		}
@@ -517,7 +526,7 @@ abstract class WPCOM_JSON_API_Endpoint {
 			'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];
+			$doc_section = 'response' === $doc_section_key ? $doc['response']['body'] : $doc['request'][$doc_section_key];
 			if ( !$doc_section ) {
 				continue;
 			}
@@ -560,29 +569,26 @@ abstract class WPCOM_JSON_API_Endpoint {
 
 <?php
 		// If no example was hardcoded in the doc, try to get some
-		if ( empty( $this->example_response ) ) { 
+		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     = wp_cache_get( $response_key );
 
 			// Response doesn't exist, so run the request
-			if ( empty( $response ) ) {
+			if ( false === $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;
-				}
+				if ( 'GET' === $this->method ) {
+					$response      = wp_remote_get( $this->example_request );
+					$response_body = wp_remote_retrieve_body( $response );
 
-				// Only update the option if there's a result
-				if ( !empty( $response ) ) {
-					$response = $response['body'];
-					update_option( $response_key, $response );
+					// Only cache if there's a result
+					if ( strlen( $response_body ) ) {
+						wp_cache_set( $response_key, $response );
+					} else {
+						wp_cache_delete( $response_key );
+					}
 				}
 			}
 
@@ -771,7 +777,7 @@ EOPHP;
 						$type = '(string)';
 					}
 
-					if ( 'response_format' != $_property ) {
+					if ( 'response_format' !== $_property ) {
 						// hack - don't show "(default)" in response format
 						reset( $description );
 						$description_key = key( $description );
@@ -802,7 +808,7 @@ EOPHP;
 
 				$item = compact( 'type', 'description' );
 
-				if ( 'response_format' == $_property ) {
+				if ( 'response_format' === $_property ) {
 					$doc['response'][$doc_item][$key] = $item;
 				} else {
 					$doc['request'][$doc_item][$key] = $item;
@@ -819,7 +825,7 @@ EOPHP;
 			return false;
 		}
 
-		if ( 'inherit' == $post->post_status ) {
+		if ( 'inherit' === $post->post_status ) {
 			$parent_post = get_post( $post->post_parent );
 			$post_status_obj = get_post_status_object( $parent_post->post_status );
 		} else {
@@ -849,11 +855,11 @@ EOPHP;
 		}
 
 		if ( -1 == get_option( 'blog_public' ) && !current_user_can( 'read_post', $post->ID ) ) {
-			return new WP_Error( 'unauthorized', 'User cannot view post', 403 );
+			return new WP_Error( 'unauthorized', 'User cannot view post', array( 'status_code' => 403, 'error' => 'private_blog' ) );
 		}
 
 		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 new WP_Error( 'unauthorized', 'User cannot view password protected post', array( 'status_code' => 403, 'error' => 'password_protected' ) );
 		}
 
 		return true;
@@ -876,6 +882,9 @@ EOPHP;
 			$profile_URL = 'http://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
 		} else {
 			if ( isset( $author->post_author ) ) {
+				if ( 0 == $author->post_author )
+					return null;
+
 				$author = $author->post_author;
 			} elseif ( isset( $author->user_id ) && $author->user_id ) {
 				$author = $author->user_id;
@@ -944,7 +953,7 @@ EOPHP;
 		$response['description'] = (string) $taxonomy->description;
 		$response['post_count']  = (int) $taxonomy->count;
 
-		if ( 'category' == $taxonomy_type )
+		if ( 'category' === $taxonomy_type )
 			$response['parent'] = (int) $taxonomy->parent;
 
 		$response['meta'] = (object) array(
@@ -1009,11 +1018,11 @@ EOPHP;
 
 		$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 );
 	}
@@ -1038,7 +1047,7 @@ EOPHP;
 	}
 
 	function get_taxonomy_link( $blog_id, $taxonomy_id, $taxonomy_type, $path = '' ) {
-		if ( 'category' == $taxonomy_type )
+		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 );
@@ -1091,14 +1100,14 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 		),
 		'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.',
-		),
+		'type'     => "(string) The post's post_type. Post types besides post and page need to be whitelisted using the <code>rest_api_allowed_post_types</code> filter.",
 		'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.',
+		'i_like'         => '(bool) Does the current user like this post?',
+		'is_reblogged'   => '(bool) Did the current user reblog this post?',
+		'is_following'   => '(bool) Is the current user following this blog?',
 		'featured_image' => '(URL) The URL to the featured image for this post if it has one.',
 		'format'         => array(), // see constructor
 		'geo'            => '(object>geo|false)',
@@ -1106,7 +1115,8 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 		'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',
+		'metadata'	     => '(array) Array of post metadata keys and values. All unprotected meta keys are available by default for read requests. Both unprotected and protected meta keys are avaiable for authenticated requests with access. Protected meta keys can be made available with the <code>rest_api_allowed_public_metadata</code> filter.',
+		'meta'           => '(object) API result meta data',
 	);
 
 	// var $response_format =& $this->post_object_format;
@@ -1121,6 +1131,30 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 		parent::__construct( $args );
 	}
 
+	function is_post_type_allowed( $post_type ) {
+
+		// if the post type is empty, that's fine, WordPress will default to post
+		if ( empty( $post_type ) )
+			return true;
+
+		// whitelist of post types that can be accessed
+ 		if ( in_array( $post_type, apply_filters( 'rest_api_allowed_post_types', array( 'post', 'page', 'any' ) ) ) )
+			return true;
+
+ 		return false;
+ 	}
+
+	function is_metadata_public( $key ) {
+		if ( empty( $key ) )
+			return false;
+
+		// whitelist of metadata that can be accessed
+ 		if ( in_array( $key, apply_filters( 'rest_api_allowed_public_metadata', array() ) ) )
+			return true;
+
+ 		return false;
+ 	}
+
 	function the_password_form() {
 		return __( 'This post is password protected.', 'jetpack' );
 	}
@@ -1134,7 +1168,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 			$geo = false;
 		}
 
-		if ( 'display' == $context ) {
+		if ( 'display' === $context ) {
 			$args = $this->query_args();
 			if ( isset( $args['content_width'] ) && $args['content_width'] ) {
 				$GLOBALS['content_width'] = (int) $args['content_width'];
@@ -1173,8 +1207,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
 		}
 
-		$types = array( 'post', 'page' );
-		if ( !in_array( $post->post_type, $types ) ) {
+		if ( ! $this->is_post_type_allowed( $post->post_type ) ) {
 			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
 		}
 
@@ -1200,7 +1233,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 		$post            = get_post( $post->ID, OBJECT, $context );
 		$GLOBALS['post'] = $post;
 
-		if ( 'display' == $context ) {
+		if ( 'display' === $context ) {
 			setup_postdata( $post );
 		}
 
@@ -1221,7 +1254,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 				$response[$key] = (string) $this->format_date( $post->post_modified_gmt, $post->post_modified );
 				break;
 			case 'title' :
-				if ( 'display' == $context ) {
+				if ( 'display' === $context ) {
 					$response[$key] = (string) get_the_title( $post->ID );
 				} else {
 					$response[$key] = (string) $post->post_title;
@@ -1234,7 +1267,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 				$response[$key] = (string) esc_url_raw( wp_get_shortlink( $post->ID ) );
 				break;
 			case 'content' :
-				if ( 'display' == $context ) {
+				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' ) );
@@ -1243,7 +1276,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 				}
 				break;
 			case 'excerpt' :
-				if ( 'display' == $context ) {
+				if ( 'display' === $context ) {
 					add_filter( 'the_password_form', array( $this, 'the_password_form' ) );
 					ob_start();
 					the_excerpt();
@@ -1289,6 +1322,15 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 			case 'like_count' :
 				$response[$key] = (int) $this->api->post_like_count( $blog_id, $post->ID );
 				break;
+			case 'i_like'     :
+				$response[$key] = (int) $this->api->is_liked( $blog_id, $post->ID );
+				break;
+			case 'is_reblogged':
+				$response[$key] = (int) $this->api->is_reblogged( $blog_id, $post->ID );
+				break;
+			case 'is_following':
+				$response[$key] = (int) $this->api->is_following( $blog_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] ) )
@@ -1379,6 +1421,32 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 				}
 				$response[$key] = (object) $response[$key];
 				break;
+			case 'metadata' : // (array|false)
+				$metadata = array();
+				foreach ( (array) has_meta( $post_id ) as $meta ) {
+					// Don't expose protected fields.
+					$show = false;
+					if ( $this->is_metadata_public( $meta['meta_key'] ) )
+						$show = true;
+					if ( current_user_can( 'edit_post_meta', $post_id , $meta['meta_key'] ) )
+						$show = true;
+
+					if ( !$show )
+						continue;
+
+					$metadata[] = array(
+						'id'    => $meta['meta_id'],
+						'key'   => $meta['meta_key'],
+						'value' => maybe_unserialize( $meta['meta_value'] ),
+					);
+				}
+
+				if ( ! empty( $metadata ) ) {
+					$response[$key] = $metadata;
+				} else {
+					$response[$key] = false;
+				}
+				break;
 			case 'meta' :
 				$response[$key] = (object) array(
 					'links' => (object) array(
@@ -1462,7 +1530,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 		$size = 'win8app-column';
 
 		$id = intval( $id );
-		if ( 'RAND' == $order )
+		if ( 'RAND' === $order )
 			$orderby = 'none';
 
 		if ( !empty( $include ) ) {
@@ -1481,7 +1549,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 
 		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 );
+				$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
@@ -1509,8 +1577,8 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
 			'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'],
+			'width'		=> (int) isset( $metadata['width']  ) ? $metadata['width']  : 0,
+			'height'	=> (int) isset( $metadata['height'] ) ? $metadata['height'] : 0,
 		);
 
 		if ( isset( $metadata['duration'] ) ) {
@@ -1573,16 +1641,37 @@ class WPCOM_JSON_API_List_Posts_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
 			return new WP_Error( 'invalid_number',  'The NUMBER parameter must be less than or equal to 100.', 400 );
 		}
 
+		if ( ! $this->is_post_type_allowed( $args['type'] ) ) {
+			return new WP_Error( 'unknown_post_type', 'Unknown post type', 404 );
+		}
+
 		$query = array(
 			'posts_per_page' => $args['number'],
 			'order'          => $args['order'],
 			'orderby'        => $args['order_by'],
-			'post_type'      => $args['type'],
+			'post_type'      => ( 'any' == $args['type'] ) ? array( 'post', 'page' ) : $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['meta_key'] ) ) {
+			$show = false;
+			if ( $this->is_metadata_public( $args['meta_key'] ) )
+				$show = true;
+			if ( current_user_can( 'edit_post_meta', $query['post_type'], $args['meta_key'] ) )
+				$show = true;
+
+			if ( is_protected_meta( $args['meta_key'], 'post' ) && ! $show )
+				return new WP_Error( 'invalid_meta_key', 'Invalid meta key', 404 );
+
+			$meta = array( 'key' => $args['meta_key'] );
+			if ( isset( $args['meta_value'] ) )
+				$meta['value'] = $args['meta_value'];
+
+			$query['meta_query'] = array( $meta );
+		}
+
 		if (
 			isset( $args['sticky'] )
 		&&
@@ -1735,8 +1824,16 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
 				return new WP_Error( 'invalid_input', 'Invalid request input', 400 );
 			}
 
+			// default to post
+			if ( empty( $input['type'] ) )
+				$input['type'] = 'post';
+
 			$post_type = get_post_type_object( $input['type'] );
 
+			if ( ! $this->is_post_type_allowed( $input['type'] ) ) {
+				return new WP_Error( 'unknown_post_type', 'Unknown post type', 404 );
+			}
+
 			if ( 'publish' === $input['status'] ) {
 				if ( !current_user_can( $post_type->cap->publish_posts ) ) {
 					if ( current_user_can( $post_type->cap->edit_posts ) ) {
@@ -1782,12 +1879,21 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
 
 		if ( !empty( $input['categories'] )) {
 			if ( is_array( $input['categories'] ) ) {
-				$categories = $input['categories'];
+				$_categories = $input['categories'];
 			} else {
 				foreach ( explode( ',', $input['categories'] ) as $category ) {
-					$categories[] = $category;
+					$_categories[] = $category;
 				}
  			}
+			foreach ( $_categories as $category ) {
+				if ( !$category_info = term_exists( $category, 'category' ) ) {
+					if ( is_int( $category ) )
+						continue;
+					$category_info = wp_insert_term( $category, 'category' );
+				}
+				if ( !is_wp_error( $category_info ) )
+					$categories[] = (int) $category_info['term_id'];
+			}
 		}
 
 		if ( !empty( $input['tags'] ) ) {
@@ -1802,9 +1908,9 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
  		}
 
 		unset( $input['tags'], $input['categories'] );
-		
+
 		$insert = array();
-		
+
 		if ( !empty( $input['slug'] ) ) {
 			$insert['post_name'] = $input['slug'];
 			unset( $input['slug'] );
@@ -1814,22 +1920,30 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
 			$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'] );
-		
+
+		$metadata = $input['metadata'];
+		unset( $input['metadata'] );
+
 		foreach ( $input as $key => $value ) {
 			$insert["post_$key"] = $value;
 		}
-		
+
+		if ( !empty( $tags ) )
+			$insert["tax_input"]["post_tag"] = $tags;
+		if ( !empty( $categories ) )
+			$insert["tax_input"]["category"] = $categories;
+
 		$has_media = isset( $input['media'] ) && $input['media'] ? count( $input['media'] ) : false;
 
 		if ( $new ) {
@@ -1868,9 +1982,9 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
 		}
 
 		if ( !$post_id || is_wp_error( $post_id ) ) {
-			return null;
+			return $post_id;
 		}
-			
+
 		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 );
@@ -1882,17 +1996,80 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
 				}
 			}
 		}
-		
+
 		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' );
+			update_post_meta( $post_id, $GLOBALS['publicize_ui']->publicize->POST_MESS, trim( $publicize_custom_message ) );
 
 		set_post_format( $post_id, $insert['post_format'] );
 
+		if ( ! empty( $metadata ) ) {
+			foreach ( (array) $metadata as $meta ) {
+
+				$meta = (object) $meta;
+
+				$existing_meta_item = new stdClass;
+
+				if ( empty( $meta->operation ) )
+					$meta->operation = 'update';
+
+				if ( ! empty( $meta->value ) ) {
+					if ( 'true' == $meta->value )
+						$meta->value = true;
+					if ( 'false' == $meta->value )
+						$meta->value = false;
+				}
+
+				if ( ! empty( $meta->id ) ) {
+					$meta->id = absint( $meta->id );
+					$existing_meta_item = get_metadata_by_mid( 'post', $meta->id );
+				}
+
+				$unslashed_meta_key = wp_unslash( $meta->key ); // should match what the final key will be
+				$meta->key = wp_slash( $meta->key );
+				$unslashed_existing_meta_key = wp_unslash( $existing_meta_item->meta_key );
+				$existing_meta_item->meta_key = wp_slash( $existing_meta_item->meta_key );
+
+				switch ( $meta->operation ) {
+					case 'delete':
+
+						if ( ! empty( $meta->id ) && ! empty( $existing_meta_item->meta_key ) && current_user_can( 'delete_post_meta', $post_id, $unslashed_existing_meta_key ) ) {
+							delete_metadata_by_mid( 'post', $meta->id );
+						} elseif ( ! empty( $meta->key ) && ! empty( $meta->previous_value ) && current_user_can( 'delete_post_meta', $post_id, $unslashed_meta_key ) ) {
+							delete_post_meta( $post_id, $meta->key, $meta->previous_value );
+						} elseif ( ! empty( $meta->key ) && current_user_can( 'delete_post_meta', $post_id, $unslashed_meta_key ) ) {
+							delete_post_meta( $post_id, $meta->key );
+						}
+
+						break;
+					case 'add':
+
+						if ( ! empty( $meta->id ) || ! empty( $meta->previous_value ) ) {
+							continue;
+						} elseif ( ! empty( $meta->key ) && ! empty( $meta->value ) && current_user_can( 'add_post_meta', $post_id, $unslashed_meta_key ) ) {
+							add_post_meta( $post_id, $meta->key, $meta->value );
+						}
+
+						break;
+					case 'update':
+
+						if ( empty( $meta->value ) ) {
+							continue;
+						} elseif ( ! empty( $meta->id ) && ! empty( $existing_meta_item->meta_key ) && current_user_can( 'edit_post_meta', $post_id, $unslashed_existing_meta_key ) ) {
+							update_metadata_by_mid( 'post', $meta->id, $meta->value );
+						} elseif ( ! empty( $meta->key ) && ! empty( $meta->previous_value ) && current_user_can( 'edit_post_meta', $post_id, $unslashed_meta_key ) ) {
+							update_post_meta( $post_id, $meta->key,$meta->value, $meta->previous_value );
+						} elseif ( ! empty( $meta->key ) && current_user_can( 'edit_post_meta', $post_id, $unslashed_meta_key ) ) {
+							update_post_meta( $post_id, $meta->key, $meta->value );
+						}
+
+						break;
+				}
+
+			}
+		}
+
+		do_action( 'rest_api_inserted_post', $post_id, $insert, $new );
+
 		$return = $this->get_post_by( 'ID', $post_id, $args['context'] );
 		if ( !$return || is_wp_error( $return ) ) {
 			return $return;
@@ -1910,6 +2087,10 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
 			return new WP_Error( 'unknown_post', 'Unknown post', 404 );
 		}
 
+		if ( ! $this->is_post_type_allowed( $post->post_type ) ) {
+			return new WP_Error( 'unknown_post_type', 'Unknown post type', 404 );
+		}
+
 		if ( !current_user_can( 'delete_post', $post->ID ) ) {
 			return new WP_Error( 'unauthorized', 'User cannot delete posts', 403 );
 		}
@@ -2039,7 +2220,7 @@ class WPCOM_JSON_API_Update_Taxonomy_Endpoint extends WPCOM_JSON_API_Taxonomy_En
 			return new WP_Error( 'unknown_taxonomy', 'A taxonomy with that name already exists', 404 );
 		}
 
-		if ( 'category' != $taxonomy_type )
+		if ( 'category' !== $taxonomy_type )
 			$input['parent'] = 0;
 
 		$data = wp_insert_term( addslashes( $input['name'] ), $taxonomy_type,
@@ -2048,8 +2229,12 @@ class WPCOM_JSON_API_Update_Taxonomy_Endpoint extends WPCOM_JSON_API_Taxonomy_En
 		  		'parent'      => $input['parent']
 			)
 		);
-	
+
+		if ( is_wp_error( $data ) )
+			return $data;
+
 		$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;
@@ -2081,7 +2266,7 @@ class WPCOM_JSON_API_Update_Taxonomy_Endpoint extends WPCOM_JSON_API_Taxonomy_En
 		}
 
 		$update = array();
-		if ( 'category' == $taxonomy_type && !empty( $input['parent'] ) )
+		if ( 'category' === $taxonomy_type && !empty( $input['parent'] ) )
 			$update['parent'] = $input['parent'];
 
 		if ( !empty( $input['description'] ) )
@@ -2093,7 +2278,7 @@ class WPCOM_JSON_API_Update_Taxonomy_Endpoint extends WPCOM_JSON_API_Taxonomy_En
 
 		$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;
@@ -2266,7 +2451,7 @@ abstract class WPCOM_JSON_API_Comment_Endpoint extends WPCOM_JSON_API_Endpoint {
 				$response[$key] = (string) esc_url_raw( wp_get_shortlink( $post->ID ) . "%23comment-{$comment->comment_ID}" );
 				break;
 			case 'content' :
-				if ( 'display' == $context ) {
+				if ( 'display' === $context ) {
 					ob_start();
 					comment_text();
 					$response[$key] = (string) ob_get_clean();
@@ -2694,17 +2879,28 @@ class WPCOM_JSON_API_Update_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endp
 		}
 
 		if ( isset( $update['comment_status'] ) ) {
+			if ( count( $update ) === 1 ) {
+				// We are only here to update the comment status so let's respond ASAP
+				add_action( 'wp_set_comment_status', array( $this, 'output_comment' ), 0, 1 );
+			}
 			switch ( $update['comment_status'] ) {
+				case 'approved' :
+					if ( 'approve' !== $comment_status ) {
+						wp_set_comment_status( $comment->comment_ID, 'approve' );
+					}
+					break;
 				case 'unapproved' :
-					$update['comment_approved'] = 0;
+					if ( 'hold' !== $comment_status ) {
+						wp_set_comment_status( $comment->comment_ID, 'hold' );
+					}
 					break;
 				case 'spam' :
-					if ( 'spam' != $comment_status ) {
+					if ( 'spam' !== $comment_status ) {
 						wp_spam_comment( $comment->comment_ID );
 					}
 					break;
 				case 'unspam' :
-					if ( 'spam' == $comment_status ) {
+					if ( 'spam' === $comment_status ) {
 						wp_unspam_comment( $comment->comment_ID );
 					}
 					break;
@@ -2713,12 +2909,12 @@ class WPCOM_JSON_API_Update_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endp
 						return new WP_Error( 'trash_disabled', 'Cannot trash comment', 403 );
 					}
 
-					if ( 'trash' != $comment_status ) { 
+					if ( 'trash' !== $comment_status ) {
  						wp_trash_comment( $comment_id );
  					}
  					break;
 				case 'untrash' :
-					if ( 'trash' == $comment_status ) {
+					if ( 'trash' === $comment_status ) {
 						wp_untrash_comment( $comment->comment_ID );
 					}
 					break;
@@ -2729,9 +2925,10 @@ class WPCOM_JSON_API_Update_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endp
 			unset( $update['comment_status'] );
 		}
 
-		$update['comment_ID'] = $comment->comment_ID;
-
-		wp_update_comment( add_magic_quotes( $update ) );
+		if ( ! empty( $update ) ) {
+			$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 ) ) {
@@ -2770,6 +2967,12 @@ class WPCOM_JSON_API_Update_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endp
 
 		return $this->get_comment( $comment->comment_ID, $args['context'] );
 	}
+
+	function output_comment( $comment_id ) {
+		$args  = $this->query_args();
+		$output = $this->get_comment( $comment_id, $args['context'] );
+		$this->api->output_early( 200, $output );
+	}
 }
 
 class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint {
@@ -2838,16 +3041,20 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint {
 	}
 }
 
+
+
 /*
  * Set up endpoints
  */
 
+
+
 /*
  * Site endpoints
  */
 new WPCOM_JSON_API_GET_Site_Endpoint( array(
 	'description' => 'Information about a site ID/domain',
-	'group'	      => 'Sites',
+	'group'	      => 'sites',
 	'stat'        => 'sites:X',
 
 	'method'      => 'GET',
@@ -2880,7 +3087,7 @@ new WPCOM_JSON_API_GET_Site_Endpoint( array(
  */
 new WPCOM_JSON_API_List_Posts_Endpoint( array(
 	'description' => 'Return matching Posts',
-	'group'       => 'Posts',
+	'group'       => 'posts',
 	'stat'        => 'posts',
 
 	'method'      => 'GET',
@@ -2907,11 +3114,7 @@ new WPCOM_JSON_API_List_Posts_Endpoint( array(
 		'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.',
-		),
+		'type'     => "(string) Specify the post type. Defaults to 'post', use 'any' to query for both posts and pages. Post types besides post and page need to be whitelisted using the <code>rest_api_allowed_post_types</code> filter.",
 		'status'   => array(
 			'publish' => 'Return only published posts.',
 			'private' => 'Return only private posts.',
@@ -2924,6 +3127,8 @@ new WPCOM_JSON_API_List_Posts_Endpoint( array(
 		'sticky'   => '(bool) Specify the stickiness.',
 		'author'   => "(int) Author's user ID",
 		'search'   => '(string) Search query',
+		'meta_key'   => '(string) Metadata key that the post should contain',
+		'meta_value'   => '(string) Metadata value that the post should contain. Will only be applied if a `meta_key` is also given',
 	),
 
 	'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/posts/?number=5&pretty=1'
@@ -2931,7 +3136,7 @@ new WPCOM_JSON_API_List_Posts_Endpoint( array(
 
 new WPCOM_JSON_API_Get_Post_Endpoint( array(
 	'description' => 'Return a single Post (by ID)',
-	'group'       => 'Posts',
+	'group'       => 'posts',
 	'stat'        => 'posts:1',
 
 	'method'      => 'GET',
@@ -2961,7 +3166,7 @@ new WPCOM_JSON_API_Get_Post_Endpoint( array(
 
 new WPCOM_JSON_API_Get_Post_Endpoint( array(
 	'description' => 'Return a single Post (by slug)',
-	'group'       => 'Posts',
+	'group'       => 'posts',
 	'stat'        => 'posts:slug',
 
 	'method'      => 'GET',
@@ -2976,7 +3181,7 @@ new WPCOM_JSON_API_Get_Post_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Post_Endpoint( array(
 	'description' => 'Create a Post',
-	'group'       => 'Posts',
+	'group'       => 'posts',
 	'stat'        => 'posts:new',
 
 	'method'      => 'POST',
@@ -3002,15 +3207,13 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 		),
 		'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.',
-		),
+		'type'      => "(string) The post type. Defaults to 'post'. Post types besides post and page need to be whitelisted using the <code>rest_api_allowed_post_types</code> filter.",
 		'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>",
+		'metadata'      => "(array) Array of metadata objects containing the following properties: `key` (metadata key), `id` (meta ID), `previous_value` (if set, the action will only occur for the provided previous value), `value` (the new value to set the meta to), `operation` (the operation to perform: `update` or `add`; defaults to `update`). All unprotected meta keys are available by default for read requests. Both unprotected and protected meta keys are avaiable for authenticated requests with access. Protected meta keys can be made available with the <code>rest_api_allowed_public_metadata</code> filter.",
 		'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.",
 	),
@@ -3026,7 +3229,7 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 			'title'      => 'Hello World',
 			'content'    => 'Hello. I am a test post. I was created by the API',
 			'tags'       => 'tests',
-			'categories' => 'API'			
+			'categories' => 'API'
 		)
 	),
 
@@ -3056,11 +3259,14 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 	"pings_open": true,
 	"comment_count": 0,
 	"like_count": 0,
+	"i_like": false,
+	"is_reblogged": false,
+	"is_following": false,
 	"featured_image": "",
 	"format": "standard",
 	"geo": false,
 	"publicize_URLs": [
-		
+
 	],
 	"tags": {
 		"tests": {
@@ -3093,6 +3299,13 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 			}
 		}
 	},
+	"metadata {
+		{
+			"id" : 123,
+			"key" : "test_meta_key",
+			"value" : "test_value",
+		}
+	},
 	"meta": {
 		"links": {
 			"self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1270",
@@ -3107,7 +3320,7 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Post_Endpoint( array(
 	'description' => 'Edit a Post',
-	'group'       => 'Posts',
+	'group'       => 'posts',
 	'stat'        => 'posts:1:POST',
 
 	'method'      => 'POST',
@@ -3138,6 +3351,7 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 		'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?',
+		'metadata'      => "(array) Array of metadata objects containing the following properties: `key` (metadata key), `id` (meta ID), `previous_value` (if set, the action will only occur for the provided previous value), `value` (the new value to set the meta to), `operation` (the operation to perform: `update` or `add`; defaults to `update`). All unprotected meta keys are available by default for read requests. Both unprotected and protected meta keys are avaiable for authenticated requests with access. Protected meta keys can be made available with the <code>rest_api_allowed_public_metadata</code> filter.",
 	),
 
 	'example_request'      => 'https://public-api.wordpress.com/rest/v1/sites/30434183/posts/1222/',
@@ -3151,7 +3365,7 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 			'title'      => 'Hello World (Again)',
 			'content'    => 'Hello. I am an edited post. I was edited by the API',
 			'tags'       => 'tests',
-			'categories' => 'API'			
+			'categories' => 'API'
 		)
 	),
 
@@ -3181,11 +3395,14 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 	"pings_open": true,
 	"comment_count": 5,
 	"like_count": 0,
+	"i_like": false,
+	"is_reblogged": false,
+	"is_following": false,
 	"featured_image": "",
 	"format": "standard",
 	"geo": false,
 	"publicize_URLs": [
-		
+
 	],
 	"tags": {
 		"tests": {
@@ -3218,6 +3435,13 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 			}
 		}
 	},
+	"metadata {
+		{
+			"id" : 123,
+			"key" : "test_meta_key",
+			"value" : "test_value",
+		}
+	},
 	"meta": {
 		"links": {
 			"self": "https:\/\/public-api.wordpress.com\/rest\/v1\/sites\/30434183\/posts\/1222",
@@ -3232,8 +3456,8 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 ) );
 
 new WPCOM_JSON_API_Update_Post_Endpoint( array(
-	'description' => 'Delete a Post',
-	'group'       => 'Posts',
+	'description' => 'Delete a Post. Note: If the post object is of type post or page and the trash is enabled, this request will send the post to the trash. A second request will permanently delete the post.',
+	'group'       => 'posts',
 	'stat'        => 'posts:1:delete',
 
 	'method'      => 'POST',
@@ -3277,11 +3501,14 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 	"pings_open": true,
 	"comment_count": 5,
 	"like_count": 0,
+	"i_like": false,
+	"is_reblogged": false,
+	"is_following": false,
 	"featured_image": "",
 	"format": "standard",
 	"geo": false,
 	"publicize_URLs": [
-		
+
 	],
 	"tags": {
 		"tests": {
@@ -3298,6 +3525,13 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
 			}
 		}
 	},
+	"metadata {
+		{
+			"id" : 123,
+			"key" : "test_meta_key",
+			"value" : "test_value",
+		}
+	},
 	"categories": {
 		"API": {
 			"name": "API",
@@ -3332,7 +3566,7 @@ new WPCOM_JSON_API_Update_Post_Endpoint( array(
  */
 new WPCOM_JSON_API_List_Comments_Endpoint( array(
 	'description' => 'Return recent Comments',
-	'group'       => 'Comments',
+	'group'       => 'comments',
 	'stat'        => 'comments',
 
 	'method'      => 'GET',
@@ -3346,7 +3580,7 @@ new WPCOM_JSON_API_List_Comments_Endpoint( array(
 
 new WPCOM_JSON_API_List_Comments_Endpoint( array(
 	'description' => 'Return recent Comments for a Post',
-	'group'       => 'Comments',
+	'group'       => 'comments',
 	'stat'        => 'posts:1:replies',
 
 	'method'      => 'GET',
@@ -3361,7 +3595,7 @@ new WPCOM_JSON_API_List_Comments_Endpoint( array(
 
 new WPCOM_JSON_API_Get_Comment_Endpoint( array(
 	'description' => 'Return a single Comment',
-	'group'       => 'Comments',
+	'group'       => 'comments',
 	'stat'        => 'comments:1',
 
 	'method'      => 'GET',
@@ -3376,7 +3610,7 @@ new WPCOM_JSON_API_Get_Comment_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Comment_Endpoint( array(
 	'description' => 'Create a Comment on a Post',
-	'group'       => 'Comments',
+	'group'       => 'comments',
 	'stat'        => 'posts:1:replies:new',
 
 	'method'      => 'POST',
@@ -3447,7 +3681,7 @@ new WPCOM_JSON_API_Update_Comment_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Comment_Endpoint( array(
 	'description' => 'Create a Comment as a reply to another Comment',
-	'group'       => 'Comments',
+	'group'       => 'comments',
 	'stat'        => 'comments:1:replies:new',
 
 	'method'      => 'POST',
@@ -3517,7 +3751,7 @@ new WPCOM_JSON_API_Update_Comment_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Comment_Endpoint( array(
 	'description' => 'Edit a Comment',
-	'group'       => 'Comments',
+	'group'       => 'comments',
 	'stat'        => 'comments:1:POST',
 
 	'method'      => 'POST',
@@ -3592,7 +3826,7 @@ new WPCOM_JSON_API_Update_Comment_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Comment_Endpoint( array(
 	'description' => 'Delete a Comment',
-	'group'       => 'Comments',
+	'group'       => 'comments',
 	'stat'        => 'comments:1:delete',
 
 	'method'      => 'POST',
@@ -3654,7 +3888,7 @@ new WPCOM_JSON_API_Update_Comment_Endpoint( array(
  */
 new WPCOM_JSON_API_Get_Taxonomy_Endpoint( array(
 	'description' => 'Returns information on a single Category',
-	'group'       => 'Taxonomy',
+	'group'       => 'taxonomy',
 	'stat'        => 'categories:1',
 
 	'method'      => 'GET',
@@ -3669,7 +3903,7 @@ new WPCOM_JSON_API_Get_Taxonomy_Endpoint( array(
 
 new WPCOM_JSON_API_Get_Taxonomy_Endpoint( array(
 	'description' => 'Returns information on a single Tag',
-	'group'       => 'Taxonomy',
+	'group'       => 'taxonomy',
 	'stat'        => 'tags:1',
 
 	'method'      => 'GET',
@@ -3684,7 +3918,7 @@ new WPCOM_JSON_API_Get_Taxonomy_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 	'description' => 'Create a new Category',
-	'group'       => 'Taxonomy',
+	'group'       => 'taxonomy',
 	'stat'        => 'categories:new',
 
 	'method'      => 'POST',
@@ -3727,7 +3961,7 @@ new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 	'description' => 'Create a new Tag',
-	'group'       => 'Taxonomy',
+	'group'       => 'taxonomy',
 	'stat'        => 'tags:new',
 
 	'method'      => 'POST',
@@ -3769,7 +4003,7 @@ new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 	'description' => 'Edit a Tag',
-	'group'       => 'Taxonomy',
+	'group'       => 'taxonomy',
 	'stat'        => 'tags:1:POST',
 
 	'method'      => 'POST',
@@ -3812,7 +4046,7 @@ new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 	'description' => 'Edit a Category',
-	'group'       => 'Taxonomy',
+	'group'       => 'taxonomy',
 	'stat'        => 'categories:1:POST',
 
 	'method'      => 'POST',
@@ -3857,7 +4091,7 @@ new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 	'description' => 'Delete a Category',
-	'group'       => 'Taxonomy',
+	'group'       => 'taxonomy',
 	'stat'        => 'categories:1:delete',
 
 	'method'      => 'POST',
@@ -3885,7 +4119,7 @@ new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 
 new WPCOM_JSON_API_Update_Taxonomy_Endpoint( array(
 	'description' => 'Delete a Tag',
-	'group'       => 'Taxonomy',
+	'group'       => 'taxonomy',
 	'stat'        => 'tags:1:delete',
 
 	'method'      => 'POST',

diff --git a/plugins/jetpack/class.json-api.php b/plugins/jetpack/class.json-api.php
index 5a322eb..b94ce59 100644
--- a/plugins/jetpack/class.json-api.php
+++ b/plugins/jetpack/class.json-api.php
@@ -12,6 +12,7 @@ class WPCOM_JSON_API {
 	var $method = '';
 	var $url = '';
 	var $path = '';
+	var $version = null;
 	var $query = array();
 	var $post_body = null;
 	var $files = null;
@@ -23,6 +24,7 @@ class WPCOM_JSON_API {
 	var $public_api_scheme = 'https';
 
 	var $trapped_error = null;
+	var $did_output = false;
 
 	static function init( $method = null, $url = null, $post_body = null ) {
 		if ( !self::$self ) {
@@ -78,7 +80,7 @@ class WPCOM_JSON_API {
 			$this->accept = $_SERVER['HTTP_ACCEPT'];
 		}
 
-		if ( 'POST' == $this->method ) {
+		if ( 'POST' === $this->method ) {
 			if ( is_null( $post_body ) ) {
 				$this->post_body = file_get_contents( 'php://input' );
 
@@ -122,11 +124,17 @@ class WPCOM_JSON_API {
 
 		add_filter( 'comment_edit_pre', array( $this, 'comment_edit_pre' ) );
 
-		$this->initialize();
+		$initialization = $this->initialize();
+		if ( is_wp_error( $initialization ) ) {
+			$this->output_error( $initialization );
+			return;
+		}
 
-		// Normalize path
+		// Normalize path and extract API version
 		$this->path = untrailingslashit( $this->path );
-		$this->path = preg_replace( '#^/rest/v1#', '', $this->path );
+		preg_match( '#^/rest/v1(\.\d+)*#', $this->path, $matches );
+		$this->path = substr( $this->path, strlen( $matches[0] ) );
+		$this->version = $matches[1];
 
 		$allowed_methods = array( 'GET', 'POST' );
 		$four_oh_five = false;
@@ -156,7 +164,7 @@ class WPCOM_JSON_API {
 				$methods = $allowed_methods;
 				$find_all_matching_endpoints = true;
 				$four_oh_five = true;
-			} 
+			}
 		}
 
 		// Find which endpoint to serve
@@ -238,25 +246,37 @@ class WPCOM_JSON_API {
 		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_error( $response );
 		}
 
 		return $this->output( 200, $response );
 	}
 
 	function process_request( WPCOM_JSON_API_Endpoint $endpoint, $path_pieces ) {
+		$this->endpoint = $endpoint;
 		return call_user_func_array( array( $endpoint, 'callback' ), $path_pieces );
 	}
 
+	function output_early( $status_code, $response = null, $content_type = 'application/json' ) {
+		$exit = $this->exit;
+		$this->exit = false;
+		if ( is_wp_error( $response ) )
+			$this->output_error( $response );
+		else
+			$this->output( $status_code, $response, $content_type );
+		$this->exit = $exit;
+		$this->finish_request();
+	}
+
 	function output( $status_code, $response = null, $content_type = 'application/json' ) {
+		// In case output() was called before the callback returned
+		if ( $this->did_output ) {
+			if ( $this->exit )
+				exit;
+			return $content_type;
+		}
+		$this->did_output = true;
+
 		if ( is_null( $response ) ) {
 			$response = new stdClass;
 		}
@@ -310,6 +330,22 @@ class WPCOM_JSON_API {
 		return $content_type;
 	}
 
+	function output_error( $error ) {
+		$status_code = $error->get_error_data();
+
+		if ( is_array( $status_code ) )
+			$status_code = $status_code['status_code'];
+
+		if ( !$status_code ) {
+			$status_code = 400;
+		}
+		$response = array(
+			'error'   => $error->get_error_code(),
+			'message' => $error->get_error_message(),
+		);
+		return $this->output( $status_code, $response );
+	}
+
 	function ensure_http_scheme_of_home_url( $url, $path, $original_scheme ) {
 		if ( $original_scheme ) {
 			return $url;
@@ -352,6 +388,18 @@ class WPCOM_JSON_API {
 		return 0;
 	}
 
+	function is_liked( $blog_id, $post_id ) {
+		return false;
+	}
+
+	function is_reblogged( $blog_id, $post_id ) {
+		return false;
+	}
+
+	function is_following( $blog_id ) {
+		return false;
+	}
+
 	function get_avatar_url( $email ) {
 		add_filter( 'pre_option_show_avatars', '__return_true', 999 );
 		$_SERVER['HTTPS'] = 'off';
@@ -440,4 +488,9 @@ class WPCOM_JSON_API {
 			'message' => $this->trapped_error['message'],
 		) );
 	}
+
+	function finish_request() {
+		if ( function_exists( 'fastcgi_finish_request' ) )
+			return fastcgi_finish_request();
+	}
 }

diff --git a/plugins/jetpack/class.photon.php b/plugins/jetpack/class.photon.php
index c045688..b7e2ddf 100644
--- a/plugins/jetpack/class.photon.php
+++ b/plugins/jetpack/class.photon.php
@@ -135,7 +135,7 @@ class Jetpack_Photon {
 		$images = Jetpack_Photon::parse_images_from_html( $content );
 
 		if ( ! empty( $images ) ) {
-			global $content_width;
+			$content_width = Jetpack::get_content_width();
 
 			$image_sizes = self::image_sizes();
 			$upload_dir = wp_upload_dir();
@@ -309,6 +309,10 @@ class Jetpack_Photon {
 						// Replace original tag with modified version
 						$content = str_replace( $tag, $new_tag, $content );
 					}
+				} elseif ( preg_match( '#^http(s)?://i[\d]{1}.wp.com#', $src ) && ! 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', $tag, 1 );
+
+					$content = str_replace( $tag, $new_tag, $content );
 				}
 			}
 		}

diff --git a/plugins/jetpack/functions.gallery.php b/plugins/jetpack/functions.gallery.php
index 9a9e71b..fd9319e 100644
--- a/plugins/jetpack/functions.gallery.php
+++ b/plugins/jetpack/functions.gallery.php
@@ -9,10 +9,10 @@ class Jetpack_Gallery_Settings {
 	}
 
 	function admin_init() {
-		$this->gallery_types = apply_filters( 'jetpack_gallery_types', array() );
+		$this->gallery_types = apply_filters( 'jetpack_gallery_types', array( 'default' => __( 'Thumbnail Grid', 'jetpack' ) ) );
 
 		// Enqueue the media UI only if needed.
-		if ( ! empty( $this->gallery_types ) ) {
+		if ( count( $this->gallery_types ) > 1 ) {
 			add_action( 'wp_enqueue_media', array( $this, 'wp_enqueue_media' ) );
 			add_action( 'print_media_templates', array( $this, 'print_media_templates' ) );
 		}
@@ -32,14 +32,15 @@ class Jetpack_Gallery_Settings {
 	 * Outputs a view template which can be used with wp.media.template
 	 */
 	function print_media_templates() {
+		$default_gallery_type = apply_filters( 'jetpack_default_gallery_type', 'default' );
+
 		?>
 		<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>
+						<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value, $default_gallery_type ); ?>><?php echo esc_html( $caption ); ?></option>
 					<?php endforeach; ?>
 				</select>
 			</label>

diff --git a/plugins/jetpack/functions.opengraph.php b/plugins/jetpack/functions.opengraph.php
index 542d01f..ef610af 100644
--- a/plugins/jetpack/functions.opengraph.php
+++ b/plugins/jetpack/functions.opengraph.php
@@ -22,14 +22,14 @@ function jetpack_og_tags() {
 	$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 ) );
+	$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' );
+		$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' );
@@ -44,13 +44,15 @@ function jetpack_og_tags() {
 			$tags['fb:admins'] = $facebook_admins;
 
 	} else if ( is_author() ) {
-		$tags['og:type'] = 'author';
+		$tags['og:type'] = 'profile';
 
 		$author = get_queried_object();
 
-		$tags['og:title'] = $author->display_name;
-		$tags['og:url'] = get_author_posts_url( $author->ID );
-		$tags['og:description'] = $author->description;
+		$tags['og:title']           = $author->display_name;
+		$tags['og:url']             = get_author_posts_url( $author->ID );
+		$tags['og:description']     = $author->description;
+		$tags['profile:first_name'] = get_the_author_meta( 'first_name', $author->ID );
+		$tags['profile:last_name']  = get_the_author_meta( 'last_name', $author->ID );
 
 	} else if ( is_singular() ) {
 		global $post;
@@ -72,7 +74,7 @@ function jetpack_og_tags() {
 		return;
 
 	$tags['og:site_name'] = get_bloginfo( 'name' );
-	$tags['og:image'] = jetpack_og_get_image( $image_width, $image_height );
+	$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'] ) )
@@ -101,7 +103,7 @@ function jetpack_og_tags() {
 	echo $og_output;
 }
 
-function jetpack_og_get_image( $width = 50, $height = 50, $max_images = 4 ) { // Facebook requires thumbnails to be a minimum of 50x50
+function jetpack_og_get_image( $width = 200, $height = 200, $max_images = 4 ) { // Facebook requires thumbnails to be a minimum of 200x200
 	$image = '';
 
 	if ( is_singular() && !is_home() && !is_front_page() ) {

diff --git a/plugins/jetpack/functions.photon.php b/plugins/jetpack/functions.photon.php
index fc276b3..bce3b91 100644
--- a/plugins/jetpack/functions.photon.php
+++ b/plugins/jetpack/functions.photon.php
@@ -80,7 +80,7 @@ function jetpack_photon_url( $image_url, $args = array(), $scheme = null ) {
 
 	return jetpack_photon_url_scheme( $photon_url, $scheme );
 }
-
+add_filter( 'jetpack_photon_url', 'jetpack_photon_url', 10, 3 );
 
 /**
  * WordPress.com
@@ -157,4 +157,4 @@ function jetpack_photon_allow_facebook_graph_domain( $allow = false, $domain ) {
 	}
 
 	return $allow;
-}
\ No newline at end of file
+}

diff --git a/plugins/jetpack/jetpack.php b/plugins/jetpack/jetpack.php
index 80b6a3c..7c0fa02 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: 2.2
+ * Version: 2.3.3
  * Author URI: http://jetpack.me
  * License: GPL2+
  * Text Domain: jetpack
@@ -17,4469 +17,51 @@ define( 'JETPACK__API_VERSION', 1 );
 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', '2.2' );
+define( 'JETPACK__VERSION', '2.3.3' );
 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)
-	An array of options.
-	@see Jetpack::get_option_names()
-
-jetpack_register (string)
-	Temporary verification secrets.
-
-jetpack_activated (int)
-	1: the plugin was activated normally
-	2: the plugin was activated on this site because of a network-wide activation
-	3: the plugin was auto-installed
-	4: the plugin was manually disconnected (but is still installed)
-
-jetpack_active_modules (array)
-	Array of active module slugs.
-
-jetpack_do_activate (bool)
-	Flag for "activating" the plugin on sites where the activation hook never fired (auto-installs)
-*/
-
-class Jetpack {
-	var $xmlrpc_server = null;
-
-	var $HTTP_RAW_POST_DATA = null; // copy of $GLOBALS['HTTP_RAW_POST_DATA']
-
-	var $plugins_to_deactivate = array(
-		'stats' => array( 'stats/stats.php', 'WordPress.com Stats' ),
-		'shortlinks' => array( 'stats/stats.php', 'WordPress.com Stats' ),
-		'sharedaddy' => array( 'sharedaddy/sharedaddy.php', 'Sharedaddy' ),
-		'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',
-		'subscriber' => 'read',
-	);
-
-	/**
-	 * Message to display in admin_notice
-	 * @var string
-	 */
-	var $message = '';
-
-	/**
-	 * Error to display in admin_notice
-	 * @var string
-	 */
-	var $error = '';
-
-	/**
-	 * Modules that need more privacy description.
-	 * @var string
-	 */
-	var $privacy_checks = '';
-
-	/**
-	 * Stats to record once the page loads
-	 *
-	 * @var array
-	 */
-	var $stats = array();
-
-	/**
-	 * Jetpack_Sync object
-	 */
-	var $sync;
-
-	/**
-	 * Verified data for JSON authorization request
-	 */
-	var $json_api_authorization_request = array();
-
-	/**
-	 * Singleton
-	 * @static
-	 */
-	public static function init() {
-		static $instance = false;
-
-		if ( !$instance ) {
-			load_plugin_textdomain( 'jetpack', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
-			$instance = new Jetpack;
-
-			$instance->plugin_upgrade();
-		}
-
-		return $instance;
-	}
-
-	/**
-	 * Must never be called statically
-	 */
-	function plugin_upgrade() {
-		// Upgrade: 1.1 -> 1.2
-		if ( get_option( 'jetpack_id' ) ) {
-			// Move individual jetpack options to single array of options
-			$options = array();
-			foreach ( Jetpack::get_option_names() as $option ) {
-				if ( false !== $value = get_option( "jetpack_$option" ) ) {
-					$options[$option] = $value;
-				}
-			}
-
-			if ( $options ) {
-				Jetpack::update_options( $options );
-
-				foreach ( array_keys( $options ) as $option ) {
-					delete_option( "jetpack_$option" );
-				}
-			}
-
-			// Add missing version and old_version options
-			if ( !$version = Jetpack::get_option( 'version' ) ) {
-				$version = $old_version = '1.1:' . time();
-				Jetpack::update_options( compact( '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 );
-				}
-			}
-		}
-	}
-
-	/**
-	 * Constructor.  Initializes WordPress hooks
-	 */
-	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();
-
-			$this->require_jetpack_authentication();
-
-			if ( Jetpack::is_active() ) {
-				// Hack to preserve $HTTP_RAW_POST_DATA
-				add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
-
-				// The actual API methods.
-				add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'xmlrpc_methods' ) );
-			} else {
-				// The bootstrap API methods.
-				add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'bootstrap_xmlrpc_methods' ) );
-			}
-
-			// 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_filter( 'xmlrpc_blog_options', array( $this, 'xmlrpc_options' ) );
-
-		add_action( 'admin_menu', array( $this, 'admin_menu' ) );
-		add_action( 'admin_init', array( $this, 'admin_init' ) );
-		add_action( 'admin_init', array( $this, 'dismiss_jetpack_notice' ) );
-
-		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' );
-	}
-
-	/**
-	 * Device Pixels support
-	 * This improves the resolution of gravatars and wordpress.com uploads on hi-res and zoomed browsers.
-	 */
-	function devicepx() {
-		wp_enqueue_script( 'devicepx', ( is_ssl() ? 'https' : 'http' ) . '://s0.wp.com/wp-content/js/devicepx-jetpack.js', array(), gmdate('oW'), true );
-	}
-
-	/**
-	 * Is Jetpack active?
-	 */
-	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( 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.
-	 */
-	public static function load_modules() {
-		if ( !Jetpack::is_active() ) {
-			return;
-		}
-
-		$version = Jetpack::get_option( 'version' );
-		if ( !$version ) {
-			$version = $old_version = JETPACK__VERSION . ':' . time();
-			Jetpack::update_options( compact( 'version', 'old_version' ) );
-		}
-		list( $version ) = explode( ':', $version );
-
-		$modules = array_filter( Jetpack::get_active_modules(), array( 'Jetpack', 'is_module' ) );
-
-		// Don't load modules that have had "Major" changes since the stored version until they have been deactivated/reactivated through the lint check.
-		if ( version_compare( $version, JETPACK__VERSION, '<' ) ) {
-			$updated_modules = array();
-			foreach ( $modules as $module ) {
-				$module_data = Jetpack::get_module( $module );
-				if ( !isset( $module_data['changed'] ) ) {
-					continue;
-				}
-
-				if ( version_compare( $module_data['changed'], $version, '<=' ) ) {
-					continue;
-				}
-
-				$updated_modules[] = $module;
-			}
-
-			$modules = array_diff( $modules, $updated_modules );
-		}
-
-		foreach ( $modules as $module ) {
-			if ( did_action( 'jetpack_module_loaded_' . $module ) ) {
-				continue;
-			}
-			require Jetpack::get_module_path( $module );
-			do_action( 'jetpack_module_loaded_' . $module );
-		}
-
-		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 */
-
-	public static function get_option_names( $type = 'compact' ) {
-		switch ( $type ) {
-		case 'non-compact' :
-		case 'non_compact' :
-			return array(
-				'register',
-				'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. (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.
-		);
-	}
-
-	/**
-	 * Returns the requested option.  Looks in jetpack_options or jetpack_$name as appropriate.
- 	 *
-	 * @param string $name    Option name
-	 * @param mixed  $default (optional)
-	 */
-	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() ) ) {
-			trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
-			return false;
-		}
-
-		$options = get_option( 'jetpack_options' );
-		if ( is_array( $options ) && isset( $options[$name] ) ) {
-			return $options[$name];
-		}
-
-		return $default;
-	}
-
-	/**
-	* 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' );
-
-		return array(
-			'secret_1' => $secret_1,
-			'secret_2' => $secret_2,
-			'eol'      => $eol,
-		);
-	}
-
-	/**
-	 * Updates the single given option.  Updates jetpack_options or jetpack_$name as appropriate.
- 	 *
-	 * @param string $name  Option name
-	 * @param mixed  $value Option 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() ) ) {
-			trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
-			return false;
-		}
-
-		$options = get_option( 'jetpack_options' );
-		if ( !is_array( $options ) ) {
-			$options = array();
-		}
-
-		$options[$name] = $value;
-
-		return update_option( 'jetpack_options', $options );
-	}
-
-	/**
-	 * Updates the multiple given options.  Updates jetpack_options and/or jetpack_$name as appropriate.
- 	 *
-	 * @param array $array array( option name => option value, ... )
-	 */
-	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 ) {
-			trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
-			unset( $array[$unknown_name] );
-		}
-
-		foreach ( array_intersect( $names, Jetpack::get_option_names( 'non_compact' ) ) as $name ) {
-			update_option( "jetpack_$name", $array[$name] );
-			unset( $array[$name] );
-		}
-
-		$options = get_option( 'jetpack_options' );
-		if ( !is_array( $options ) ) {
-			$options = array();
-		}
-
-		return update_option( 'jetpack_options', array_merge( $options, $array ) );
-	}
-
-	/**
-	 * Deletes the given option.  May be passed multiple option names as an array.
-	 * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
- 	 *
-	 * @param string|array $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 ) {
-			trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
-		}
-
-		foreach ( array_intersect( $names, Jetpack::get_option_names( 'non_compact' ) ) as $name ) {
-			delete_option( "jetpack_$name" );
-		}
-
-		$options = get_option( 'jetpack_options' );
-		if ( !is_array( $options ) ) {
-			$options = array();
-		}
-
-		$to_delete = array_intersect( $names, Jetpack::get_option_names(), array_keys( $options ) );
-		if ( $to_delete ) {
-			foreach ( $to_delete as $name ) {
-				unset( $options[$name] );
-			}
-
-			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.
-	 */
-	public static function glob_php( $absolute_path ) {
-		$absolute_path = untrailingslashit( $absolute_path );
-		$files = array();
-		if ( !$dir = @opendir( $absolute_path ) ) {
-			return $files;
-		}
-
-		while ( false !== $file = readdir( $dir ) ) {
-			if ( '.' == substr( $file, 0, 1 ) || '.php' != substr( $file, -4 ) ) {
-				continue;
-			}
-
-			$file = "$absolute_path/$file";
-
-			if ( !is_file( $file ) ) {
-				continue;
-			}
-
-			$files[] = $file;
-		}
-
-		closedir( $dir );
-
-		return $files;
-	}
-
-	public function activate_new_modules() {
-		if ( ! Jetpack::is_active() ) {
-			return;
-		}
-
-		$jetpack_old_version = Jetpack::get_option( 'version' ); // [sic]
-		if ( !$jetpack_old_version ) {
-			$jetpack_old_version = $version = $old_version = '1.1:' . time();
-			Jetpack::update_options( compact( 'version', 'old_version' ) );
-		}
-
-		list( $jetpack_version ) = explode( ':', $jetpack_old_version ); // [sic]
-
-		if ( version_compare( JETPACK__VERSION, $jetpack_version, '<=' ) ) {
-			return;
-		}
-
-		$active_modules = Jetpack::get_active_modules();
-		$reactivate_modules = array();
-		foreach ( $active_modules as $active_module ) {
-			$module = Jetpack::get_module( $active_module );
-			if ( !isset( $module['changed'] ) ) {
-				continue;
-			}
-
-			if ( version_compare( $module['changed'], $jetpack_version, '<=' ) ) {
-				continue;
-			}
-
-			$reactivate_modules[] = $active_module;
-			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,
-		) );
-
-		Jetpack::state( 'message', 'modules_activated' );
-		Jetpack::activate_default_modules( $jetpack_version, JETPACK__VERSION, $reactivate_modules );
-		wp_safe_redirect( Jetpack::admin_url() );
-		exit;
-	}
-
-	/**
-	 * List available Jetpack modules. Simply lists .php files in /modules/.
-	 * Make sure to tuck away module "library" files in a sub-directory.
-	 */
-	public static function get_available_modules( $min_version = false, $max_version = false ) {
-		static $modules = null;
-
-		if ( !isset( $modules ) ) {
-			$files = Jetpack::glob_php( dirname( __FILE__ ) . '/modules' );
-
-			$modules = array();
-
-			foreach ( $files as $file ) {
-				if ( !$headers = Jetpack::get_module( $file ) ) {
-					continue;
-				}
-
-				$modules[ Jetpack::get_module_slug( $file ) ] = $headers['introduced'];
-			}
-		}
-
-		if ( !$min_version && !$max_version ) {
-			return array_keys( $modules );
-		}
-
-		$r = array();
-		foreach ( $modules as $slug => $introduced ) {
-			if ( $min_version && version_compare( $min_version, $introduced, '>=' ) ) {
-				continue;
-			}
-
-			if ( $max_version && version_compare( $max_version, $introduced, '<' ) ) {
-				continue;
-			}
-
-			$r[] = $slug;
-		}
-
-		return $r;
-	}
-
-	/**
-	 * Default modules loaded on activation.
-	 */
-	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' :
-			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;
-			}
-		}
-
-		return $return;
-	}
-
-	/**
-	 * Extract a module's slug from its full path.
-	 */
-	public static function get_module_slug( $file ) {
-		return str_replace( '.php', '', basename( $file ) );
-	}
-
-	/**
-	 * Generate a module's path from its slug.
-	 */
-	public static function get_module_path( $slug ) {
-		return dirname( __FILE__ ) . "/modules/$slug.php";
-	}
-
-	/**
-	 * Load module data from module file. Headers differ from WordPress
-	 * plugin headers to avoid them being identified as standalone
-	 * plugins on the WordPress plugins page.
-	 */
-	public static function get_module( $module ) {
-		$headers = array(
-			'name'        => 'Module Name',
-			'description' => 'Module Description',
-			'sort'        => 'Sort Order',
-			'introduced'  => 'First Introduced',
-			'changed'     => 'Major Changes In',
-			'deactivate'  => 'Deactivate',
-			'free'        => 'Free',
-		);
-
-		$file = Jetpack::get_module_path( Jetpack::get_module_slug( $module ) );
-		if ( !file_exists( $file ) )
-			return false;
-
-		$mod = get_file_data( $file, $headers );
-		if ( empty( $mod['name'] ) )
-			return false;
-
-		$mod['name'] = translate( $mod['name'], 'jetpack' );
-		$mod['description'] = translate( $mod['description'], 'jetpack' );
-		if ( empty( $mod['sort'] ) )
-			$mod['sort'] = 10;
-		$mod['deactivate'] = empty( $mod['deactivate'] );
-		$mod['free'] = empty( $mod['free'] );
-		return $mod;
-	}
-
-	/**
-	 * Get a list of activated modules as an array of module slugs.
-	 */
-	public static function get_active_modules() {
-		$active = Jetpack::get_option( 'active_modules' );
-		if ( !is_array( $active ) )
-			$active = array();
-		if ( is_admin() ) {
-			$active[] = 'vaultpress';
-		} else {
-			$active = array_diff( $active, array( 'vaultpress' ) );
-		}
-		return array_unique( $active );
-	}
-
-	public static function is_module( $module ) {
-		return !empty( $module ) && !validate_file( $module, Jetpack::get_available_modules() );
-	}
-
-	/**
-	 * Catches PHP errors.  Must be used in conjunction with output buffering.
-	 *
-	 * @param bool $catch True to start catching, False to stop.
-	 *
-	 * @static
-	 */
-	public static function catch_errors( $catch ) {
-		static $display_errors, $error_reporting;
-
-		if ( $catch ) {
-			$display_errors = @ini_set( 'display_errors', 1 );
-			$error_reporting = @error_reporting( E_ALL );
-			add_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 0 );
-		} else {
-			@ini_set( 'display_errors', $display_errors );
-			@error_reporting( $error_reporting );
-			remove_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 1 );
-		}
-	}
-
-	/**
-	 * Saves any generated PHP errors in ::state( 'php_errors', {errors} )
-	 */
-	public static function catch_errors_on_shutdown() {
-		Jetpack::state( 'php_errors', ob_get_clean() );
-	}
-
-	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 );
-		$modules = array_merge( $other_modules, $modules );
-
-		// Look for standalone plugins and disable if active.
-
-		$to_deactivate = array();
-		foreach ( $modules as $module ) {
-			if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) {
-				$to_deactivate[$module] = $jetpack->plugins_to_deactivate[$module];
-			}
-		}
-
-		$deactivated = array();
-		foreach ( $to_deactivate as $module => $deactivate_me ) {
-			list( $probable_file, $probable_title ) = $deactivate_me;
-			if ( Jetpack_Client_Server::deactivate_plugin( $probable_file, $probable_title ) ) {
-				$deactivated[] = $module;
-			}
-		}
-
-		if ( $deactivated ) {
-			Jetpack::state( 'deactivated_plugins', join( ',', $deactivated ) );
-
-			$url = add_query_arg( array(
-				'action' => 'activate_default_modules',
-				'_wpnonce' => wp_create_nonce( 'activate_default_modules' ),
-			), add_query_arg( compact( 'min_version', 'max_version', 'other_modules' ), Jetpack::admin_url() ) );
-			wp_safe_redirect( $url );
-			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();
-		Jetpack::catch_errors( true );
-		foreach ( $modules as $module ) {
-			$active = Jetpack::get_active_modules();
-			if ( in_array( $module, $active ) ) {
-				$module_info = Jetpack::get_module( $module );
-				if ( !$module_info['deactivate'] ) {
-					$state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules';
-					if ( $active_state = Jetpack::state( $state ) ) {
-						$active_state = explode( ',', $active_state );
-					} else {
-						$active_state = array();
-					}
-					$active_state[] = $module;
-					Jetpack::state( $state, implode( ',', $active_state ) );
-				}
-				continue;
-			}
-
-			$file = Jetpack::get_module_path( $module );
-			if ( !file_exists( $file ) ) {
-				continue;
-			}
-
-			// we'll override this later if the plugin can be included without fatal error
-			wp_safe_redirect( Jetpack::admin_url() );
-			Jetpack::state( 'error', 'module_activation_failed' );
-			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 ) ) {
-				$active_state = explode( ',', $active_state );
-			} else {
-				$active_state = array();
-			}
-			$active_state[] = $module;
-			Jetpack::state( $state, implode( ',', $active_state ) );
-			Jetpack::update_option( 'active_modules', array_unique( $active ) );
-			ob_end_clean();
-		}
-		Jetpack::state( 'error', false );
-		Jetpack::state( 'module', false );
-		Jetpack::catch_errors( false );
-		do_action( 'jetpack_activate_default_modules', $min_version, $max_version, $other_modules );
-	}
-
-	public static function activate_module( $module ) {
-		$jetpack = Jetpack::init();
-
-		if ( !Jetpack::is_active() )
-			return false;
-
-		if ( !strlen( $module ) )
-			return false;
-
-		if ( !Jetpack::is_module( $module ) )
-			return false;
-
-		// If it's already active, then don't do it again
-		$active = Jetpack::get_active_modules();
-		foreach ( $active as $act ) {
-			if ( $act == $module )
-				return true;
-		}
-
-		// Check and see if the old plugin is active
-		if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) {
-			// Deactivate the old plugin
-			if ( Jetpack_Client_Server::deactivate_plugin( $jetpack->plugins_to_deactivate[$module][0], $jetpack->plugins_to_deactivate[$module][1] ) ) {
-				// If we deactivated the old plugin, remembere that with ::state() and redirect back to this page to activate the module
-				// We can't activate the module on this page load since the newly deactivated old plugin is still loaded on this page load.
-				Jetpack::state( 'deactivated_plugins', $module );
-				wp_safe_redirect( add_query_arg( 'jetpack_restate', 1 ) );
-				exit;
-			}
-		}
-
-		// Check the file for fatal errors, a la wp-admin/plugins.php::activate
-		Jetpack::state( 'module', $module );
-		Jetpack::state( 'error', 'module_activation_failed' ); // we'll override this later if the plugin can be included without fatal error
-		wp_safe_redirect( Jetpack::admin_url() );
-
-		Jetpack::catch_errors( true );
-		ob_start();
-		require Jetpack::get_module_path( $module );
-		do_action( 'jetpack_activate_module', $module );
-		$active[] = $module;
-		Jetpack::update_option( 'active_modules', array_unique( $active ) );
-		Jetpack::state( 'error', false ); // the override
-		Jetpack::state( 'message', 'module_activated' );
-		Jetpack::state( 'module', $module );
-		ob_end_clean();
-		Jetpack::catch_errors( false );
-		exit;
-	}
-
-	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 ) {
-			if ( !empty( $check ) && $module != $check )
-				$new[] = $check;
-		}
-
-		do_action( "jetpack_deactivate_module_$module" );
-		return Jetpack::update_option( 'active_modules', array_unique( $new ) );
-	}
-
-	public static function enable_module_configurable( $module ) {
-		$module = Jetpack::get_module_slug( $module );
-		add_filter( 'jetpack_module_configurable_' . $module, '__return_true' );
-	}
-
-	public static function module_configuration_url( $module ) {
-		$module = Jetpack::get_module_slug( $module );
-		return Jetpack::admin_url( array( 'configure' => $module ) );
-	}
-
-	public static function module_configuration_load( $module, $method ) {
-		$module = Jetpack::get_module_slug( $module );
-		add_action( 'jetpack_module_configuration_load_' . $module, $method );
-	}
-
-	public static function module_configuration_head( $module, $method ) {
-		$module = Jetpack::get_module_slug( $module );
-		add_action( 'jetpack_module_configuration_head_' . $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 */
-
-	public static function bail_on_activation( $message, $deactivate = true ) {
-?>
-<!doctype html>
-<html>
-<head>
-<meta charset="<?php bloginfo( 'charset' ); ?>">
-<style>
-* {
-	text-align: center;
-	margin: 0;
-	padding: 0;
-	font-family: "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif;
-}
-p {
-	margin-top: 1em;
-	font-size: 18px;
-}
-</style>
-<body>
-<p><?php echo esc_html( $message ); ?></p>
-</body>
-</html>
-<?php
-		if ( $deactivate ) {
-			$plugins = get_option( 'active_plugins' );
-			$jetpack = plugin_basename( __FILE__ );
-			$update = false;
-			foreach ( $plugins as $i => $plugin ) {
-				if ( $plugin === $jetpack ) {
-					$plugins[$i] = false;
-					$update = true;
-				}
-			}
-
-			if ( $update ) {
-				update_option( 'active_plugins', array_filter( $plugins ) );
-			}
-		}
-		exit;
-	}
-
-	/**
-	 * Attached to activate_{ plugin_basename( __FILES__ ) } by register_activation_hook()
-	 * @static
-	 */
-	public static function plugin_activation( $network_wide ) {
-		Jetpack::update_option( 'activated', 1 );
-
-		if ( version_compare( $GLOBALS['wp_version'], JETPACK__MINIMUM_WP_VERSION, '<' ) ) {
-			Jetpack::bail_on_activation( sprintf( __( 'Jetpack requires WordPress version %s or later.', 'jetpack' ), JETPACK__MINIMUM_WP_VERSION ) );
-		}
-
-		if ( $network_wide )
-			Jetpack::state( 'network_nag', true );
-
-		Jetpack::plugin_initialize();
-	}
-
-	/**
-	 * Sets the internal version number and activation state.
-	 * @static
-	 */
-	public static function plugin_initialize() {
-		if ( !Jetpack::get_option( 'activated' ) ) {
-			Jetpack::update_option( 'activated', 2 );
-		}
-
-		if ( !Jetpack::get_option( 'version' ) ) {
-			$version = $old_version = JETPACK__VERSION . ':' . time();
-			Jetpack::update_options( compact( 'version', 'old_version' ) );
-		}
-
-		Jetpack::load_modules();
-
-		Jetpack::delete_option( 'do_activate' );
-	}
-
-	/**
-	 * Removes all connection options
-	 * @static
-	 */
-	public static function plugin_deactivation( $network_wide ) {
-		Jetpack::disconnect( false );
-	}
-
-	/**
-	 * Disconnects from the Jetpack servers.
-	 * Forgets all connection details and tells the Jetpack servers to do the same.
-	 * @static
-	 */
-	public static function disconnect( $update_activated_state = true ) {
-		wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
-		Jetpack::clean_nonces( true );
-
-		Jetpack::load_xml_rpc_client();
-		$xml = new Jetpack_IXR_Client();
-		$xml->query( 'jetpack.deregister' );
-
-		Jetpack::delete_option( array(
-			'register',
-			'blog_token',
-			'user_token',
-			'user_tokens',
-			'master_user',
-			'time_diff',
-			'fallback_no_verify_ssl_certs',
-		) );
-
-		if ( $update_activated_state ) {
-			Jetpack::update_option( 'activated', 4 );
-		}
-	}
-
-	/**
-	 * 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()
-	 */
-	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.
-		if ( !$result || is_wp_error( $result ) ) {
-			return $result;
-		} else {
-			return true;
-		}
-	}
-
-/* Admin Pages */
-
-	function admin_init() {
-		// If the plugin is not connected, display a connect message.
-		if (
-			// the plugin was auto-activated and needs its candy
-			Jetpack::get_option( 'do_activate' )
-		||
-			// the plugin is active, but was never activated.  Probably came from a site-wide network activation
-			!Jetpack::get_option( 'activated' )
-		) {
-			Jetpack::plugin_initialize();
-		}
-
-		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' ) );
-				add_action( 'load-plugins.php', array( $this, 'prepare_connect_notice' ) );
-			}
-		} elseif ( false === Jetpack::get_option( 'fallback_no_verify_ssl_certs' ) ) {
-			// Upgrade: 1.1 -> 1.1.1
-			// Check and see if host can verify the Jetpack servers' SSL certificate
-			$args = array();
-			Jetpack_Client::_wp_remote_request(
-				Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'test' ), $args ),
-				$args,
-				true
-			);
-		}
-
-		add_action( 'load-plugins.php', array( $this, 'intercept_plugin_error_scrape_init' ) );
-		add_action( 'admin_head', array( $this, 'admin_menu_css' ) );
-		add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
-
-		add_action( 'wp_ajax_jetpack_debug', array( $this, 'ajax_debug' ) );
-
-		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  ) {
-				// WP 3.4.x
-				// TODO will need to add && $wp_db_version < xxxxx when 3.5 comes out.
-				add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_retina_scripts' ) );
-				// /wp-admin/customize.php omits the action above.
-				add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_retina_scripts' ) );
-			}
-		}
-	}
-
-	function prepare_connect_notice() {
-		add_action( 'admin_print_styles', array( $this, 'admin_styles' ) );
-
-		add_action( 'admin_notices', array( $this, 'admin_connect_notice' ) );
-
-		if ( Jetpack::state( 'network_nag' ) )
-			add_action( 'network_admin_notices', array( $this, 'network_connect_notice' ) );
-	}
-
-	/**
-	 * Sometimes a plugin can activate without causing errors, but it will cause errors on the next page load.
-	 * This function artificially throws errors for such cases (whitelisted).
-	 *
-	 * @param string $plugin The activated plugin.
-	 */
-	function throw_error_on_activate_plugin( $plugin ) {
-		$active_modules = Jetpack::get_active_modules();
-
-		// The Shortlinks module and the Stats plugin conflict, but won't cause errors on activation because of some function_exists() checks.
-		if ( function_exists( 'stats_get_api_key' ) && in_array( 'shortlinks', $active_modules ) ) {
-			$throw = false;
-
-			// Try and make sure it really was the stats plugin
-			if ( !class_exists( 'ReflectionFunction' ) ) {
-				if ( 'stats.php' == basename( $plugin ) ) {
-					$throw = true;
-				}
-			} else {
-				$reflection = new ReflectionFunction( 'stats_get_api_key' );
-				if ( basename( $plugin ) == basename( $reflection->getFileName() ) ) {
-					$throw = true;
-				}
-			}
-
-			if ( $throw ) {
-				trigger_error( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), 'WordPress.com Stats' ), E_USER_ERROR );
-			}
-		}
-	}
-
-	function intercept_plugin_error_scrape_init() {
-		add_action( 'check_admin_referer', array( $this, 'intercept_plugin_error_scrape' ), 10, 2 );
-	}
-
-	function intercept_plugin_error_scrape( $action, $result ) {
-		if ( !$result ) {
-			return;
-		}
-
-		foreach ( $this->plugins_to_deactivate as $module => $deactivate_me ) {
-			if ( "plugin-activation-error_{$deactivate_me[0]}" == $action ) {
-				Jetpack::bail_on_activation( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), $deactivate_me[1] ), false );
-			}
-		}
-	}
-
-	function admin_menu() {
-		list( $jetpack_version ) = explode( ':', Jetpack::get_option( 'version' ) );
-		if (
-			$jetpack_version
-		&&
-			$jetpack_version != JETPACK__VERSION
-		&&
-			( $new_modules = Jetpack::get_default_modules( $jetpack_version, JETPACK__VERSION ) )
-		&&
-			is_array( $new_modules )
-		&&
-			( $new_modules_count = count( $new_modules ) )
-		&&
-			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 ) );
-			$title = sprintf( 'Jetpack %s', "<span class='update-plugins count-{$new_modules_count}' title='$span_title'><span class='update-count'>$new_modules_count_i18n</span></span>" );
-		} else {
-			$title = __( 'Jetpack', 'jetpack' );
-		}
-
-		$hook = add_menu_page( 'Jetpack', $title, 'read', 'jetpack', array( $this, 'admin_page' ), 'div' );
-
-		add_action( "load-$hook", array( $this, 'admin_page_load' ) );
-
-		if ( version_compare( $GLOBALS['wp_version'], '3.3', '<' ) ) {
-			if ( isset( $_GET['page'] ) && 'jetpack' == $_GET['page'] ) {
-				add_contextual_help( $hook, $this->jetpack_help() );
-			}
-		} else {
-			add_action( "load-$hook", array( $this, 'admin_help' ) );
-		}
-		add_action( "admin_head-$hook", array( $this, 'admin_head' ) );
-		add_filter( 'custom_menu_order', array( $this, 'admin_menu_order' ) );
-		add_filter( 'menu_order', array( $this, 'jetpack_menu_order' ) );
-
-		add_action( "admin_print_styles-$hook", array( $this, 'admin_styles' ) );
-
-		add_action( "admin_print_scripts-$hook", array( $this, 'admin_scripts' ) );
-
-		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
-	 *
-	 * Deprecated.  Remove when Jetpack requires WP 3.3+
-	 */
-	function jetpack_help() {
-		return
-			'<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
-			'<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' .
-			'<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>' .
-			'<p><strong>' . __( 'Jetpack Module Options', 'jetpack' ) . '</strong></p>' .
-			'<p>' . __( '<strong>To Activate/Deactivate a Module</strong> - Click on Learn More. An Activate or Deactivate button will now appear next to the Learn More button. Click the Activate/Deactivate button.', 'jetpack' ) . '</p>' .
-			'<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' .
-			'<p><a href="http://jetpack.me/faq/" target="_blank">'     . __( 'Jetpack FAQ',     'jetpack' ) . '</a></p>' .
-			'<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></p>';
-	}
-
-	/**
-	 * Add help to the Jetpack page
-	 *
-	 * @since Jetpack (1.2.3)
-	 * @return false if not the Jetpack page
-	 */
-	function admin_help() {
-		$current_screen = get_current_screen();
-
-		// Overview
-		$current_screen->add_help_tab( array(
-			'id'		=> 'overview',
-			'title'		=> __( 'Overview', 'jetpack' ),
-			'content'	=>
-				'<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
-				'<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' .
-				'<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>'
-		) );
-
-		// Screen Content
-		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(
-			'<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' .
-			'<p><a href="http://jetpack.me/faq/" target="_blank">'     . __( 'Jetpack FAQ',     'jetpack' ) . '</a></p>' .
-			'<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></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;
-			}
-			/* 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 {
-					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;
-			}
-		</style><?php
-	}
-
-	function admin_menu_order() {
-		return true;
-	}
-
-	function jetpack_menu_order( $menu_order ) {
-		$jp_menu_order = array();
-
-		foreach ( $menu_order as $index => $item ) {
-			if ( $item != 'jetpack' )
-				$jp_menu_order[] = $item;
-
-			if ( $index == 0 )
-				$jp_menu_order[] = 'jetpack';
-		}
-
-		return $jp_menu_order;
-	}
-
-	function admin_head() {
-		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 . '-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 . '-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' ) );
-	}
-
-	function enqueue_retina_scripts() {
-		wp_enqueue_style( 'jetpack-retina', plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/jetpack-retina.css' ), false, JETPACK__VERSION . '-20120730' );
-	}
-
-	function plugin_action_links( $actions ) {
-		return array_merge(
-			array( 'settings' => sprintf( '<a href="%s">%s</a>', Jetpack::admin_url(), __( 'Settings', 'jetpack' ) ) ),
-			$actions
-		);
-		return $actions;
-	}
-
-	function admin_connect_notice() {
-		// Don't show the connect notice on the jetpack settings page. @todo: must be a better way?
-		if ( false !== strpos( $_SERVER['QUERY_STRING'], 'page=jetpack' ) )
-			return;
-
-		if ( !current_user_can( 'manage_options' ) )
-			return;
-		?>
-
-		<div id="message" class="updated jetpack-message jp-connect">
-			<div id="jp-dismiss" class="jetpack-close-button-container">
-				<a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?></a>
-			</div>
-			<div class="jetpack-wrap-container">
-				<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 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; ?>
-					</h4>
-				</div>
-				<div class="jetpack-install-container">
-					<?php if ( 1 == Jetpack::get_option( 'activated' ) ) : ?>
-						<p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
-					<?php else : ?>
-						<p class="submit"><a href="<?php echo Jetpack::admin_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Learn More', 'jetpack' ); ?></a></p>
-					<?php endif; ?>
-				</div>
-			</div>
-		</div>
-
-		<?php
-	}
-
-	function network_connect_notice() {
-		?>
-		<div id="message" class="updated jetpack-message">
-			<div class="squeezer">
-				<h4><?php _e( '<strong>Jetpack is activated!</strong> Each site on your network must be connected individually by an admin on that site.', 'jetpack' ) ?></h4>
-			</div>
-		</div>
-		<?php
-	}
-
-	public static function jetpack_comment_notice() {
-		if ( in_array( 'comments', Jetpack::get_active_modules() ) ) {
-			return '';
-		}
-
-		$jetpack_old_version = explode( ':', Jetpack::get_option( 'old_version' ) );
-		$jetpack_new_version = explode( ':', Jetpack::get_option( 'version' ) );
-
-		if ( $jetpack_old_version ) {
-			if ( version_compare( $jetpack_old_version[0], '1.4', '>=' ) ) {
-				return '';
-			}
-		}
-
-		if ( $jetpack_new_version ) {
-			if ( version_compare( $jetpack_new_version[0], '1.4-something', '<' ) ) {
-				return '';
-			}
-		}
-
-		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(
-					'action' => 'activate',
-					'module' => 'comments',
-				) ),
-				"jetpack_activate-comments"
-			),
-			__( 'click here', 'jetpack' )
-		);
-	}
-
-	/*
-	 * Registration flow:
-	 * 1 - ::admin_page_load() action=register
-	 * 2 - ::try_registration()
-	 * 3 - ::register()
-	 *     - Creates jetpack_register option containing two secrets and a timestamp
-	 *     - Calls https://jetpack.wordpress.com/jetpack.register/1/ with
-	 *       siteurl, home, gmt_offset, timezone_string, site_name, secret_1, secret_2, site_lang, timeout, stats_id
-	 *     - That request to jetpack.wordpress.com does not immediately respond.  It first makes a request BACK to this site's
-	 *       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_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
-	 * 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, 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
-	 * 13- Jetpack::activate_default_modules()
-	 *     Deactivates deprecated plugins
-	 *     Activates all default modules
-	 *     Catches errors: redirects to wp-admin/index.php?page=jetpack state:error=something
-	 * 14- redirect to this site's wp-admin/index.php?page=jetpack with state:message=authorized
-	 *     Done!
-	 */
-
-	/**
-	 * Handles the page load events for the Jetpack admin page
-	 */
-	function admin_page_load() {
-		$error = false;
-
-		if ( !empty( $_GET['jetpack_restate'] ) ) {
-			// Should only be used in intermediate redirects to preserve state across redirects
-			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() && Jetpack::is_user_connected() ) {
-					Jetpack::state( 'message', 'already_authorized' );
-					wp_safe_redirect( Jetpack::admin_url() );
-					exit;
-				}
-				$client_server = new Jetpack_Client_Server;
-				$client_server->authorize();
-				exit;
-			case 'register' :
-				check_admin_referer( 'jetpack-register' );
-				$registered = Jetpack::try_registration();
-				if ( is_wp_error( $registered ) ) {
-					$error = $registered->get_error_code();
-					Jetpack::state( 'error_description', $registered->get_error_message() );
-					break;
-				}
-
-				wp_redirect( $this->build_connect_url( true ) );
-				exit;
-			case 'activate' :
-				$module = stripslashes( $_GET['module'] );
-				check_admin_referer( "jetpack_activate-$module" );
-				Jetpack::activate_module( $module );
-				wp_safe_redirect( Jetpack::admin_url() );
-				exit;
-			case 'activate_default_modules' :
-				check_admin_referer( 'activate_default_modules' );
-				Jetpack::restate();
-				$min_version = isset( $_GET['min_version'] ) ? $_GET['min_version'] : false;
-				$max_version = isset( $_GET['max_version'] ) ? $_GET['max_version'] : false;
-				$other_modules = isset( $_GET['other_modules'] ) && is_array( $_GET['other_modules'] ) ? $_GET['other_modules'] : array();
-				Jetpack::activate_default_modules( $min_version, $max_version, $other_modules );
-				wp_safe_redirect( Jetpack::admin_url() );
-				exit;
-			case 'disconnect' :
-				check_admin_referer( 'jetpack-disconnect' );
-				Jetpack::disconnect();
-				wp_safe_redirect( Jetpack::admin_url() );
-				exit;
-			case 'deactivate' :
-				$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' ) ) {
-			$this->activate_new_modules();
-		}
-
-		switch ( $error ) {
-		case 'access_denied' :
-			$this->error = __( 'You need to authorize the Jetpack connection between your site and WordPress.com to enable the awesome features.', 'jetpack' );
-			break;
-		case 'wrong_state' :
-			$this->error =  __( "Don&#8217;t cross the streams!  You need to stay logged in to your WordPress blog while you authorize Jetpack.", 'jetpack' );
-			break;
-		case 'invalid_client' :
-			// @todo re-register instead of deactivate/reactivate
-			$this->error = __( 'Return to sender.  Whoops! It looks like you got the wrong Jetpack in the mail; deactivate then reactivate the Jetpack plugin to get a new one.', 'jetpack' );
-			break;
-		case 'invalid_grant' :
-			$this->error = __( "Wrong size.  Hm&#8230; it seems your Jetpack doesn&#8217;t quite fit.  Have you lost weight? Click &#8220;Connect to WordPress.com&#8221; again to get your Jetpack adjusted.", 'jetpack' );
-			break;
-		case 'site_inaccessible' :
-		case 'site_requires_authorization' :
-			$this->error = sprintf( __( 'Your website needs to be publicly accessible to use Jetpack: %s', 'jetpack' ), "<code>$error</code>" );
-			break;
-		case 'module_activation_failed' :
-			$module = Jetpack::state( 'module' );
-			if ( !empty( $module ) && $mod = Jetpack::get_module( $module ) ) {
-				$this->error = sprintf( __( '%s could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' ), $mod['name'] );
-				if ( isset( $this->plugins_to_deactivate[$module] ) ) {
-					$this->error .= ' ' . sprintf( __( 'Do you still have the %s plugin installed?', 'jetpack' ), $this->plugins_to_deactivate[$module][1] );
-				}
-			} else {
-				$this->error  = __( 'Module could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' );
-			}
-			if ( $php_errors = Jetpack::state( 'php_errors' ) ) {
-				$this->error .= "<br />\n";
-				$this->error .= $php_errors;
-			}
-			break;
-		case 'not_public' :
-			$this->error = __( "<strong>Your Jetpack has a glitch.</strong> Connecting this site with WordPress.com is not possible. This usually means your site is not publicly accessible (localhost).", 'jetpack' );
-			break;
-		case 'wpcom_408' :
-		case 'wpcom_5??' :
-		case 'wpcom_bad_response' :
-		case 'wpcom_outage' :
-			$this->error = __( 'WordPress.com is currently having problems and is unable to fuel up your Jetpack.  Please try again later.', 'jetpack' );
-			break;
-		case 'register_http_request_failed' :
-		case 'token_http_request_failed' :
-			$this->error = sprintf( __( 'Jetpack could not contact WordPress.com: %s.  This usually means something is incorrectly configured on your web host.', 'jetpack' ), "<code>$error</code>" );
-			break;
-		default :
-			if ( empty( $error ) ) {
-				break;
-			}
-			$error = trim( substr( strip_tags( $error ), 0, 20 ) );
-			// no break: fall through
-		case 'no_role' :
-		case 'no_cap' :
-		case 'no_code' :
-		case 'no_state' :
-		case 'invalid_state' :
-		case 'invalid_request' :
-		case 'invalid_scope' :
-		case 'unsupported_response_type' :
-		case 'invalid_token' :
-		case 'no_token' :
-		case 'missing_secrets' :
-		case 'home_missing' :
-		case 'siteurl_missing' :
-		case 'gmt_offset_missing' :
-		case 'site_name_missing' :
-		case 'secret_1_missing' :
-		case 'secret_2_missing' :
-		case 'site_lang_missing' :
-		case 'home_malformed' :
-		case 'siteurl_malformed' :
-		case 'gmt_offset_malformed' :
-		case 'timezone_string_malformed' :
-		case 'site_name_malformed' :
-		case 'secret_1_malformed' :
-		case 'secret_2_malformed' :
-		case 'site_lang_malformed' :
-		case 'secrets_mismatch' :
-		case 'verify_secret_1_missing' :
-		case 'verify_secret_1_malformed' :
-		case 'verify_secrets_missing' :
-		case 'verify_secrets_mismatch' :
-			$error = esc_html( $error );
-			$this->error = sprintf( __( "<strong>Your Jetpack has a glitch.</strong>  Something went wrong that&#8217;s never supposed to happen.  Guess you&#8217;re just lucky: %s", 'jetpack' ), "<code>$error</code>" );
-			if ( !Jetpack::is_active() ) {
-				$this->error .= '<br />';
-				$this->error .= sprintf( __( 'Try connecting again.', 'jetpack' ) );
-			}
-			break;
-		}
-
-		$message_code = Jetpack::state( 'message' );
-
-		$active_state = Jetpack::state( 'activated_modules' );
-		if ( !empty( $active_state ) ) {
-			$available = Jetpack::get_available_modules();
-			$active_state = explode( ',', $active_state );
-			$active_state = array_intersect( $active_state, $available );
-			if ( count( $active_state ) ) {
-				foreach ( $active_state as $mod ) {
-					$this->stat( 'module-activated', $mod );
-				}
-			} else {
-				$active_state = false;
-			}
-		}
-
-		switch ( $message_code ) {
-		case 'modules_activated' :
-			$this->message = sprintf(
-				__( 'Welcome to <strong>Jetpack %s</strong>!', 'jetpack' ),
-				JETPACK__VERSION
-			);
-
-			if ( $active_state ) {
-				$titles = array();
-				foreach ( $active_state as $mod ) {
-					if ( $mod_headers = Jetpack::get_module( $mod ) ) {
-						$titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', '&nbsp;', $mod_headers['name'] ) . '</strong>';
-					}
-				}
-				if ( $titles ) {
-					$this->message .= '<br /><br />' . wp_sprintf( __( 'The following new modules have been activated: %l.', 'jetpack' ), $titles );
-				}
-			}
-
-			if ( $reactive_state = Jetpack::state( 'reactivated_modules' ) ) {
-				$titles = array();
-				foreach ( explode( ',',  $reactive_state ) as $mod ) {
-					if ( $mod_headers = Jetpack::get_module( $mod ) ) {
-						$titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', '&nbsp;', $mod_headers['name'] ) . '</strong>';
-					}
-				}
-				if ( $titles ) {
-					$this->message .= '<br /><br />' . wp_sprintf( __( 'The following modules have been updated: %l.', 'jetpack' ), $titles );
-				}
-			}
-
-			$this->message .= Jetpack::jetpack_comment_notice();
-			break;
-
-		case 'module_activated' :
-			if ( $module = Jetpack::get_module( Jetpack::state( 'module' ) ) ) {
-				$this->message = sprintf( __( '<strong>%s Activated!</strong> You can deactivate at any time by clicking Learn More and then Deactivate on the module card.', 'jetpack' ), $module['name'] );
-				$this->stat( 'module-activated', Jetpack::state( 'module' ) );
-			}
-			break;
-
-		case 'module_deactivated' :
-			$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' :
-			$this->message = __( '<strong>Module settings were saved.</strong> ', 'jetpack' );
-			break;
-
-		case 'already_authorized' :
-			$this->message = __( '<strong>Your Jetpack is already connected.</strong> ', 'jetpack' );
-			break;
-
-		case 'authorized' :
-			$this->message  = __( "<strong>You&#8217;re fueled up and ready to go.</strong> ", 'jetpack' );
-			$this->message .= "<br />\n";
-			$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' );
-
-		if ( !empty( $deactivated_plugins ) ) {
-			$deactivated_plugins = explode( ',', $deactivated_plugins );
-			$deactivated_titles = array();
-			foreach ( $deactivated_plugins as $deactivated_plugin ) {
-				if ( !isset( $this->plugins_to_deactivate[$deactivated_plugin] ) ) {
-					continue;
-				}
-
-				$deactivated_titles[] = '<strong>' . str_replace( ' ', '&nbsp;', $this->plugins_to_deactivate[$deactivated_plugin][1] ) . '</strong>';
-			}
-
-			if ( $deactivated_titles ) {
-				if ( $this->message ) {
-					$this->message .= "<br /><br />\n";
-				}
-
-				$this->message .= wp_sprintf( _n(
-					'Jetpack contains the most recent version of the old %l plugin.',
-					'Jetpack contains the most recent versions of the old %l plugins.',
-					count( $deactivated_titles ),
-					'jetpack'
-				), $deactivated_titles );
-
-				$this->message .= "<br />\n";
-
-				$this->message .= _n(
-					'The old version has been deactivated and can be removed from your site.',
-					'The old versions have been deactivated and can be removed from your site.',
-					count( $deactivated_titles ),
-					'jetpack'
-				);
-			}
-		}
-
-		$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'] ) && current_user_can( 'manage_options' ) ) {
-			do_action( 'jetpack_module_configuration_load_' . $_GET['configure'] );
-		}
-
-		add_filter( 'jetpack_short_module_description', 'wptexturize' );
-	}
-
-	function admin_notices() {
-
-		if ( $this->error ) {
-?>
-<div id="message" class="jetpack-message jetpack-err">
-	<div class="squeezer">
-		<h4><?php echo wp_kses( $this->error, array( 'code' => true, 'strong' => true, 'br' => true, 'b' => true ) ); ?></h4>
-<?php	if ( $desc = Jetpack::state( 'error_description' ) ) : ?>
-		<p><?php echo esc_html( stripslashes( $desc ) ); ?></p>
-<?php	endif; ?>
-	</div>
-</div>
-<?php
-		}
-
-		if ( $this->message ) {
-?>
-<div id="message" class="jetpack-message">
-	<div class="squeezer">
-		<h4><?php echo wp_kses( $this->message, array( 'strong' => array(), 'a' => array( 'href' => true ), 'br' => true ) ); ?></h4>
-	</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;
-	}
-
-	/**
-	 * Record a stat for later output
-	 */
-	function stat( $group, $detail ) {
-		if ( !isset( $this->stats[ $group ] ) )
-			$this->stats[ $group ] = array();
-		$this->stats[ $group ][] = $detail;
-	}
-
-	/**
-	 * Load stats pixels. $group is auto-prefixed with "jetpack-"
-	 */
-	function do_stats() {
-		if ( is_array( $this->stats ) && count( $this->stats ) ) {
-			foreach ( $this->stats as $group => $stats ) {
-				if ( is_array( $stats ) && count( $stats ) )
-					echo '<img src="' . ( is_ssl() ? 'https' : 'http' ) . '://stats.wordpress.com/g.gif?v=wpcom2&x_jetpack-' . esc_attr( $group ) . '=' . esc_attr( implode( ',', $stats ) ) . '&rand=' . md5( mt_rand( 0, 999 ) . time() ) . '" width="1" height="1" style="display:none;" />';
-			}
-		}
-	}
-
-	function translate_current_user_to_role() {
-		foreach ( $this->capability_translations as $role => $cap ) {
-			if ( current_user_can( $role ) || current_user_can( $cap ) ) {
-				return $role;
-			}
-		}
-
-		return false;
-	}
-
-	function translate_role_to_cap( $role ) {
-		if ( !isset( $this->capability_translations[$role] ) ) {
-			return false;
-		}
-
-		return $this->capability_translations[$role];
-	}
-
-	function sign_role( $role ) {
-		if ( !$user_id = (int) get_current_user_id() ) {
-			return false;
-		}
-
-		$token = Jetpack_Data::get_access_token();
-		if ( !$token || is_wp_error( $token ) ) {
-			return false;
-		}
-
-		return $role . ':' . hash_hmac( 'md5', "{$role}|{$user_id}", $token->secret );
-	}
-
-	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 {
-			$role = $this->translate_current_user_to_role();
-			$signed_role = $this->sign_role( $role );
-
-			$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}_{$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' ) );
-		}
-
-		return $raw ? $url : esc_url( $url );
-	}
-
-	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;
-	}
-
-	function dismiss_jetpack_notice() {
-		if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] && ! is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
-			require_once ABSPATH . 'wp-admin/includes/plugin.php';
-
-			deactivate_plugins( plugin_basename( __FILE__ ), false, false );
-
-			wp_safe_redirect( admin_url() . 'plugins.php?deactivate=true&plugin_status=all&paged=1&s=' );
-			exit;
-		}
-	}
-
-	function admin_page() {
-		global $current_user;
-
-		$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">
-
-			<h2 style="display: none"></h2> <!-- For WP JS message relocation -->
-
-			<div id="jp-header"<?php if ( $is_connected ) : ?> class="small"<?php endif; ?>>
-				<div id="jp-clouds">
-					<?php if ( $is_connected ) : ?>
-					<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>
-					<?php if ( !$is_connected ) : ?>
-					<div id="jp-notice">
-						<p><?php _e( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ); ?></p>
-					</div>
-					<?php endif; ?>
-				</div>
-			</div>
-
-			<?php if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] ) : ?>
-				<div id="message" class="error">
-					<p><?php _e( 'Jetpack is network activated and notices can not be dismissed.', 'jetpack' ); ?></p>
-				</div>
-			<?php endif; ?>
-
-			<?php do_action( 'jetpack_notices' ) ?>
-
-			<?php // If the connection has not been made then show the marketing text. ?>
-			<?php if ( ! $is_connected ) : ?>
-
-				<div id="message" class="updated jetpack-message jp-connect">
-					<div id="jp-dismiss" class="jetpack-close-button-container">
-						<a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice.', 'jetpack' ); ?></a>
-					</div>
-					<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 connect your website to WordPress.com using the button to the right. Once you&#8217;ve made the connection you&#8217;ll activate all the delightful features below.", 'jetpack' ) ?></p>
-							</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( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
-						</div>
-					</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'] ) && current_user_can( 'manage_options' ) ) :
-				$this->admin_screen_configure_module( $_GET['configure'] );
-
-			// List all the available modules.
-			else :
-				$this->admin_screen_list_modules();
-				?>
-
-				<div id="survey" class="jp-survey">
-					<div class="jp-survey-container">
-						<div class="jp-survey-text">
-							<h4><?php _e( 'Have feedback on Jetpack?', 'jetpack' ); ?></h4>
-							<br />
-							<?php _e( 'Answer a short survey to let us know how we&#8217;re doing and what to add in the future.', 'jetpack' ); ?>
-						</div>
-						<div class="jp-survey-button-container">
-							<p class="submit"><?php printf( '<a id="jp-survey-button" class="button-primary" target="_blank" href="%1$s">%2$s</a>', 'http://jetpack.me/survey/?rel=' . JETPACK__VERSION, __( 'Take Survey', 'jetpack' ) ); ?></p>
-						</div>
-					</div>
-				</div>
-
-				<?php if ( $is_connected && $this->current_user_is_connection_owner() ) : ?>
-					<p id="news-sub"><?php _e( 'Checking email updates status&hellip;', 'jetpack' ); ?></p>
-					<script type="text/javascript">
-					jQuery(document).ready(function($){
-						$.get( ajaxurl, { action: 'jetpack-check-news-subscription', rand: jQuery.now().toString() + Math.random().toString() }, function( data ) {
-							if ( 'subscribed' == data ) {
-								$( '#news-sub' ).html( '<?php printf(
-															esc_js( _x( 'You are currently subscribed to email updates. %s', '%s = Unsubscribe link', 'jetpack' ) ),
-															'<a href="#" class="jp-news-link button">' . esc_js( __( 'Unsubscribe', 'jetpack' ) ) . '</a>'
-														); ?>' );
-							} else {
-								$( '#news-sub' ).html( '<?php printf(
-															esc_js( _x( 'Want to receive updates about Jetpack by email? %s', '%s = Subscribe link', 'jetpack' ) ),
-															'<a href="#" class="jp-news-link button-primary">' . esc_js( __( 'Subscribe', 'jetpack' ) ) . '</a>'
-														); ?>' );
-							}
-							$( '.jp-news-link' ).click( function() {
-								$( '#news-sub' ).append( ' <img src="<?php echo esc_js( esc_url( admin_url( 'images/loading.gif' ) ) ); ?>" align="absmiddle" id="jp-news-loading" />' );
-								$.get( ajaxurl, { action: 'jetpack-subscribe-to-news', rand: jQuery.now().toString() + Math.random().toString() }, function( data ) {
-									if ( 'subscribed' == data ) {
-										$( '#news-sub' ).text( '<?php echo esc_js( __( 'You have been subscribed to receive email updates.', 'jetpack' ) ); ?>' );
-									} else {
-										$( '#news-sub' ).text( '<?php echo esc_js( __( 'You will no longer receive email updates about Jetpack.', 'jetpack' ) ); ?>' );
-									}
-									$( '#jp-news-loading' ).remove();
-								} );
-								return false;
-							} );
-						} );
-					} );
-					</script>
-				<?php endif; ?>
-			<?php endif; ?>
-
-			<div id="jp-footer">
-				<p class="automattic"><?php _e( 'An <span>Automattic</span> Airline', 'jetpack' ) ?></p>
-				<p class="small">
-					<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 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' ) ) {
-			die( '-1' );
-		}
-?>
-		<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',
-			'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>
-<?php
-		exit;
-	}
-
-	function admin_screen_configure_module( $module_id ) {
-		if ( !in_array( $module_id, Jetpack::get_active_modules() ) || !current_user_can( 'manage_options' ) )
-			return false; ?>
-
-		<div id="jp-settings-screen" style="position: relative">
-			<h3>
-			<?php
-				$module = Jetpack::get_module( $module_id );
-				echo '<a href="' . menu_page_url( 'jetpack', false ) . '">' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</a> &rarr; ';
-				printf( __( 'Configure %s', 'jetpack' ), $module['name'] );
-			?>
-			</h3>
-
-			<?php do_action( 'jetpack_module_configuration_screen_' . $module_id ); ?>
-		</div><?php
-	}
-
-	public static function sort_modules( $a, $b ) {
-		if ( $a['sort'] == $b['sort'] )
-			return 0;
-
-		return ( $a['sort'] < $b['sort'] ) ? -1 : 1;
-	}
-
-	function admin_screen_list_modules() {
-		require_once dirname( __FILE__ ) . '/modules/module-info.php';
-		$jetpack_connected = true;
-		if ( !Jetpack::is_active() )
-			$jetpack_connected = false;
-
-		?>
-		<div class="module-container">
-		<?php
-
-		$avail_raw = Jetpack::get_available_modules();
-		$available = array();
-		$active    = Jetpack::get_active_modules();
-		$counter   = 0;
-
-		foreach ( (array) $avail_raw as $module ) {
-			if ( $plugin = Jetpack::get_module( $module ) ) {
-				$plugin['module'] = $module;
-				$available[] = $plugin;
-			}
-		}
-		unset( $avail_raw );
-		usort( $available, array( 'Jetpack', 'sort_modules' ) );
-		$jetpack_version = Jetpack::get_option( 'version' );
-		if ( $jetpack_version ) {
-			list( $jetpack_version, $jetpack_version_time ) = explode( ':', $jetpack_version );
-		} else {
-			$jetpack_version = 0;
-			$jetpack_version_time = 0;
-		}
-
-		$jetpack_old_version = Jetpack::get_option( 'old_version' );
-		if ( $jetpack_old_version ) {
-			list( $jetpack_old_version ) = explode( ':', $jetpack_old_version );
-		} else {
-			$jetpack_old_version = 0;
-		}
-		$now = time();
-
-		foreach ( (array) $available as $module_data ) {
-			$module = $module_data['module'];
-			$activated = in_array( $module, $active );
-			if ( $activated ) {
-				$css        = 'active';
-				$toggle     = __( 'Deactivate', 'jetpack' );
-				$toggle_url = wp_nonce_url(
-					Jetpack::admin_url( array(
-						'action' => 'deactivate',
-						'module' => $module
-					) ),
-					"jetpack_deactivate-$module"
-				);
-			} else {
-				$css        = 'inactive';
-				$toggle     = __( 'Activate', 'jetpack' );
-				$toggle_url = wp_nonce_url(
-					Jetpack::admin_url( array(
-						'action' => 'activate',
-						'module' => $module
-					) ),
-					"jetpack_activate-$module"
-				);
-			}
-
-			if ( $counter % 4 == 0 ) {
-				$classes = $css . ' jetpack-newline';
-				$counter = 0;
-			} else {
-				$classes = $css;
-			}
-
-			$free_text = esc_html( $module_data['free'] ?  __( 'Free', 'jetpack' ) : __( 'Purchase', 'jetpack' ) );
-			$free_text = apply_filters( 'jetpack_module_free_text_' . $module, $free_text );
-			$badge_text = $free_text;
-
-			if ( !$jetpack_connected ) {
-				$classes = 'x disabled';
-			} else if ( $jetpack_version_time + 604800 > $now ) { // 1 week
-				if ( version_compare( $module_data['introduced'], $jetpack_old_version, '>' ) ) {
-					$badge_text = esc_html__( 'New', 'jetpack' );
-					$classes .= ' jetpack-new-module';
-				} elseif ( isset( $module_data['changed'] ) && version_compare( $module_data['changed'], $jetpack_old_version, '>' ) ) {
-					$badge_text = esc_html__( 'Updated', 'jetpack' );
-					$classes .= ' jetpack-updated-module';
-				} else {
-					$badge_text = $free_text;
-				}
-			}
-
-			?>
-			<div class="jetpack-module jetpack-<?php echo $classes; ?>" id="<?php echo $module ?>">
-				<h3><?php echo $module_data['name']; ?></h3>
-				<div class="jetpack-module-description">
-						<div class="module-image">
-							<p><span class="module-image-badge"><?php echo $badge_text; ?></span><span class="module-image-free" style="display: none"><?php echo $free_text; ?></span></p>
-						</div>
-
-						<p><?php echo apply_filters( 'jetpack_short_module_description', $module_data['description'], $module ); ?></p>
-				</div>
-
-				<div class="jetpack-module-actions">
-				<?php if ( $jetpack_connected ) : ?>
-					<?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 ( 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'] && 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 ) ?>
-				<?php endif; ?>
-				</div>
-			</div>
-			<?php if ( 'inactive' == $css && $jetpack_connected ) : ?>
-			<script type="text/javascript">
-			jQuery( '#<?php echo esc_js( $module ); ?>' ).bind( 'click', function(e){
-				if ( !jQuery(e.target).hasClass('more-info-link') )
-					document.location.href = '<?php echo str_replace( '&amp;', '&', esc_js( esc_url( $toggle_url ) ) ); ?>';
-			} );
-			</script>
-			<?php endif; ?>
-
-			<div id="jp-more-info-<?php echo esc_attr( $module ); ?>" style="display:none;">
-				<?php
-				if ( $jetpack_connected && has_action( 'jetpack_module_more_info_connected_' . $module ) )
-					do_action( 'jetpack_module_more_info_connected_' . $module );
-				else
-					do_action( 'jetpack_module_more_info_' . $module );
-				?>
-			</div>
-
-			<?php
-			$counter++;
-		}
-
-		// Add in some "Coming soon..." placeholders to fill up the current row and one more
-		for ( $i = 0; $i < 4; $i++ ) { ?>
-			<div class="jetpack-module placeholder"<?php if ( $i > 8 - $counter ) echo ' style="display: none;"'; ?>>
-				<h3><?php _e( 'Coming soon&#8230;', 'jetpack' ) ?></h3>
-			</div>
-		<?php
-		}
-
-		echo '</div><!-- .module-container -->';
-	}
-
-	function check_news_subscription() {
-		if ( !$this->current_user_is_connection_owner() ) {
-			exit;
-		}
-
-		Jetpack::load_xml_rpc_client();
-		$xml = new Jetpack_IXR_Client( array(
-			'user_id' => JETPACK_MASTER_USER,
-		) );
-		$xml->query( 'jetpack.checkNewsSubscription' );
-		if ( $xml->isError() ) {
-			printf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() );
-		} else {
-			print_r( $xml->getResponse() );
-		}
-		exit;
-	}
-
-	function subscribe_to_news() {
-		if ( !$this->current_user_is_connection_owner() ) {
-			exit;
-		}
-
-		Jetpack::load_xml_rpc_client();
-		$xml = new Jetpack_IXR_Client( array(
-			'user_id' => JETPACK_MASTER_USER,
-		) );
-		$xml->query( 'jetpack.subscribeToNews' );
-		if ( $xml->isError() ) {
-			printf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() );
-		} else {
-			print_r( $xml->getResponse() );
-		}
-		exit;
-	}
-
-/* Client API */
-
-	/**
-	 * Returns the requested Jetpack API URL
-	 *
-	 * @return string
-	 */
-	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
-	 */
-	public static function fix_url_for_bad_hosts( $url, &$args ) {
-		if ( 0 !== strpos( $url, 'https://' ) ) {
-			return $url;
-		}
-
-		switch ( JETPACK_CLIENT__HTTPS ) {
-		case 'ALWAYS' :
-			return $url;
-		case 'NEVER' :
-			return substr_replace( $url, '', 4, 1 );
-		// default : case 'AUTO' :
-		}
-
-		$jetpack = Jetpack::init();
-
-		// Yay! Your host is good!
-		if ( wp_http_supports( array( 'ssl' => true ) ) ) {
-			return $url;
-		}
-
-		// Boo! Your host is bad and makes Jetpack cry!
-		return substr_replace( $url, '', 4, 1 );
-	}
-
-	/**
-	 * Returns the Jetpack XML-RPC API
-	 *
-	 * @return string
-	 */
-	public static function xmlrpc_api_url() {
-		$base = preg_replace( '#(https?://[^?/]+)(/?.*)?$#', '\\1', JETPACK__API_BASE );
-		return untrailingslashit( $base ) . '/xmlrpc.php';
-	}
-
-	/**
-	 * @return bool|WP_Error
-	 */
-	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' ) );
-		if ( empty( $secret_1 ) || empty( $secret_2 ) || empty( $secret_eol ) || $secret_eol < time() )
-			return new Jetpack_Error( 'missing_secrets' );
-
-		$timeout = (int) ini_get( 'max_execution_time' );
-		if ( !$timeout )
-			$timeout = 30;
-		$timeout = intval( $timeout / 2 );
-
-		$gmt_offset = get_option( 'gmt_offset' );
-		if ( !$gmt_offset ) {
-			$gmt_offset = 0;
-		}
-
-		$stats_options = get_option( 'stats_options' );
-		$stats_id = isset($stats_options['blog_id']) ? $stats_options['blog_id'] : null;
-
-		$args = array(
-			'method' => 'POST',
-			'body' => array(
-				'siteurl'         => site_url(),
-				'home'            => home_url(),
-				'gmt_offset'      => $gmt_offset,
-				'timezone_string' => (string) get_option( 'timezone_string' ),
-				'site_name'       => (string) get_option( 'blogname' ),
-				'secret_1'        => $secret_1,
-				'secret_2'        => $secret_2,
-				'site_lang'       => get_locale(),
-				'timeout'         => $timeout,
-				'stats_id'        => $stats_id,
-			),
-			'headers' => array(
-				'Accept' => 'application/json',
-			),
-			'timeout' => $timeout,
-		);
-		$response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'register' ), $args ), $args, true );
-
-		if ( is_wp_error( $response ) ) {
-			return new Jetpack_Error( 'register_http_request_failed', $response->get_error_message() );
-		}
-
-		$code = wp_remote_retrieve_response_code( $response );
-		$entity = wp_remote_retrieve_body( $response );
-
-		if ( $entity )
-			$json = json_decode( $entity );
-		else
-			$json = false;
-
-		$code_type = intval( $code / 100 );
-		if ( 5 == $code_type ) {
-			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 );
-		} 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 );
-		}
-
-		// 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_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;
-	}
-
-
-/* Client Server API */
-
-	/**
-	 * Loads the Jetpack 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 and other requests from the Jetpack Server
-	 */
-	function authenticate_jetpack( $user, $username, $password ) {
-		if ( is_a( $user, 'WP_User' ) ) {
-			return $user;
-		}
-
-		// It's not for us
-		if ( !isset( $_GET['token'] ) || empty( $_GET['signature'] ) ) {
-			return $user;
-		}
-
-		@list( $token_key, $version, $user_id ) = explode( ':', $_GET['token'] );
-		if (
-			empty( $token_key )
-		||
-			empty( $version ) || strval( JETPACK__API_VERSION ) !== $version
-		||
-			empty( $user_id ) || !ctype_digit( $user_id ) || !get_userdata( $user_id ) // only handle user_tokens for now, not blog_tokens
-		) {
-			return $user;
-		}
-
-		$token = Jetpack_Data::get_access_token( $user_id );
-		if ( !$token ) {
-			return $user;
-		}
-
-		if ( 0 !== strpos( $token->secret, "$token_key." ) ) {
-			return $user;
-		}
-
-		require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
-
-		$jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
-		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 ) ) {
-			return $signature;
-		} else if ( $signature !== $_GET['signature'] ) {
-			return $user;
-		}
-
-		$timestamp = (int) $_GET['timestamp'];
-		$nonce     = stripslashes( (string) $_GET['nonce'] );
-
-		if ( !$this->add_nonce( $timestamp, $nonce ) ) {
-			return $user;
-		}
-
-		nocache_headers();
-
-		return new WP_User( $token->external_user_id );
-	}
-
-	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 );
-		$return = $wpdb->query( $wpdb->prepare(
-			"INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s)",
-			"jetpack_nonce_{$timestamp}_{$nonce}",
-			time(),
-			'no'
-		) );
-		$wpdb->show_errors( $show_errors );
-
-		$nonces_used_this_request["$timestamp:$nonce"] = $return;
-
-		return $return;
-	}
-
-	/**
-	 * In some setups, $HTTP_RAW_POST_DATA can be emptied during some IXR_Server paths since it is passed by reference to various methods.
-	 * Capture it here so we can verify the signature later.
-	 */
-	function xmlrpc_methods( $methods ) {
-		$this->HTTP_RAW_POST_DATA = $GLOBALS['HTTP_RAW_POST_DATA'];
-		return $methods;
-	}
-
-	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";
-		$sql_args = array( like_escape( 'jetpack_nonce_' ) . '%' );
-
-		if ( true !== $all ) {
-			$sql .= ' AND CAST( `option_value` AS UNSIGNED ) < %d';
-			$sql_args[] = time() - 3600;
-		}
-
-		$sql .= ' LIMIT 100';
-
-		$sql = $wpdb->prepare( $sql, $sql_args );
-
-		for ( $i = 0; $i < 1000; $i++ ) {
-			if ( !$wpdb->query( $sql ) ) {
-				break;
-			}
-		}
-	}
-
-	/**
-	 * State is passed via cookies from one request to the next, but never to subsequent requests.
-	 * SET: state( $key, $value );
-	 * GET: $value = state( $key );
-	 *
-	 * @param string $key
-	 * @param string $value
-	 * @param bool $restate private
-	 */
-	public static function state( $key = null, $value = null, $restate = false ) {
-		static $state = array();
-		static $path, $domain;
-		if ( !isset( $path ) ) {
-			require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
-			$admin_url = Jetpack::admin_url();
-			$bits = parse_url( $admin_url );
-
-			if ( is_array( $bits ) ) {
-				$path = ( isset( $bits['path'] ) ) ? dirname( $bits['path'] ) : null;
-				$domain = ( isset( $bits['host'] ) ) ? $bits['host'] : null;
-			} else {
-				$path = $domain = null;
-			}
-		}
-
-		// Extract state from cookies and delete cookies
-		if ( isset( $_COOKIE[ 'jetpackState' ] ) && is_array( $_COOKIE[ 'jetpackState' ] ) ) {
-			$yum = $_COOKIE[ 'jetpackState' ];
-			unset( $_COOKIE[ 'jetpackState' ] );
-			foreach ( $yum as $k => $v ) {
-				if ( strlen( $v ) )
-					$state[ $k ] = $v;
-				setcookie( "jetpackState[$k]", false, 0, $path, $domain );
-			}
-		}
-
-		if ( $restate ) {
-			foreach ( $state as $k => $v ) {
-				setcookie( "jetpackState[$k]", $v, 0, $path, $domain );
-			}
-			return;
-		}
-
-		// Get a state variable
-		if ( isset( $key ) && !isset( $value ) ) {
-			if ( array_key_exists( $key, $state ) )
-				return $state[ $key ];
-			return null;
-		}
-
-		// Set a state variable
-		if ( isset ( $key ) && isset( $value ) ) {
-			$state[ $key ] = $value;
-			setcookie( "jetpackState[$key]", $value, 0, $path, $domain );
-		}
-	}
-
-	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.
-	 */
-	public static function xmlrpc_async_call() {
-		global $blog_id;
-		static $clients = array();
-
-		$client_blog_id = is_multisite() ? $blog_id : 0;
-
-		if ( !isset( $clients[$client_blog_id] ) ) {
-			Jetpack::load_xml_rpc_client();
-			$clients[$client_blog_id] = new Jetpack_IXR_ClientMulticall( array(
-				'user_id' => JETPACK_MASTER_USER,
-			) );
-			ignore_user_abort( true );
-			add_action( 'shutdown', array( 'Jetpack', 'xmlrpc_async_call' ) );
-		}
-
-		$args = func_get_args();
-
-		if ( !empty( $args[0] ) ) {
-			call_user_func_array( array( $clients[$client_blog_id], 'addCall' ), $args );
-		} elseif ( is_multisite() ) {
-			foreach ( $clients as $client_blog_id => $client ) {
-				if ( !$client_blog_id || empty( $client->calls ) ) {
-					continue;
-				}
-
-				$switch_success = switch_to_blog( $client_blog_id, true );
-				if ( !$switch_success ) {
-					continue;
-				}
-
-				flush();
-				$client->query();
-
-				restore_current_blog();
-			}
-		} else {
-			if ( isset( $clients[0] ) && !empty( $clients[0]->calls ) ) {
-				flush();
-				$clients[0]->query();
-			}
-		}
-	}
-
-	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 );
-		}
-
-	       	srand( crc32( basename( $url ) ) );
-		$static_counter = rand( 0, 2 );
-		srand(); // this resets everything that relies on this, like array_rand() and shuffle()
-
-		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
-	 *
-	 * @return array|WP_Error WP HTTP response on success
-	 */
-	public static function remote_request( $args, $body = null ) {
-		$defaults = array(
-			'url' => '',
-			'user_id' => 0,
-			'blog_id' => 0,
-			'auth_location' => JETPACK_CLIENT__AUTH_LOCATION,
-			'method' => 'POST',
-			'timeout' => 10,
-			'redirection' => 0,
-		);
-
-		$args = wp_parse_args( $args, $defaults );
-
-		$args['blog_id'] = (int) $args['blog_id'];
-
-		if ( 'header' != $args['auth_location'] ) {
-			$args['auth_location'] = 'query_string';
-		}
-
-		$token = Jetpack_Data::get_access_token( $args['user_id'] );
-		if ( !$token ) {
-			return new Jetpack_Error( 'missing_token' );
-		}
-
-		$method = strtoupper( $args['method'] );
-
-		$timeout = intval( $args['timeout'] );
-
-		$redirection = $args['redirection'];
-
-		$request = compact( 'method', 'body', 'timeout', 'redirection' );
-
-		@list( $token_key, $secret ) = explode( '.', $token->secret );
-		if ( empty( $token ) || empty( $secret ) ) {
-			return new Jetpack_Error( 'malformed_token' );
-		}
-
-		$token_key = sprintf( '%s:%d:%d', $token_key, JETPACK__API_VERSION, $token->external_user_id );
-
-		require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
-
-		$time_diff = (int) Jetpack::get_option( 'time_diff' );
-		$jetpack_signature = new Jetpack_Signature( $token->secret, $time_diff );
-
-		$timestamp = time() + $time_diff;
-		$nonce = wp_generate_password( 10, false );
-
-		// Kind of annoying.  Maybe refactor Jetpack_Signature to handle body-hashing
-		if ( is_null( $body ) ) {
-			$body_hash = '';
-		} else {
-			if ( !is_string( $body ) ) {
-				return new Jetpack_Error( 'invalid_body', 'Body is malformed.' );
-			}
-			$body_hash = jetpack_sha1_base64( $body );
-		}
-
-		$auth = array(
-			'token' => $token_key,
-			'timestamp' => $timestamp,
-			'nonce' => $nonce,
-			'body-hash' => $body_hash,
-		);
-
-		if ( false !== strpos( $args['url'], 'xmlrpc.php' ) ) {
-			$url_args = array( 'for' => 'jetpack' );
-		} else {
-			$url_args = array();
-		}
-
-		if ( 'header' != $args['auth_location'] ) {
-			$url_args += $auth;
-		}
-
-		$url = add_query_arg( urlencode_deep( $url_args ), $args['url'] );
-		$url = Jetpack::fix_url_for_bad_hosts( $url, $request );
-
-		$signature = $jetpack_signature->sign_request( $token_key, $timestamp, $nonce, $body_hash, $method, $url, $body, false );
-
-		if ( !$signature || is_wp_error( $signature ) ) {
-			return $signature;
-		}
-
-		// Send an Authorization header so various caches/proxies do the right thing
-		$auth['signature'] = $signature;
-		$auth['version'] = JETPACK__VERSION;
-		$header_pieces = array();
-		foreach ( $auth as $key => $value ) {
-			$header_pieces[] = sprintf( '%s="%s"', $key, $value );
-		}
-		$request['headers'] = array(
-			'Authorization' => "X_JETPACK " . join( ' ', $header_pieces ),
-		);
-
-		if ( 'header' != $args['auth_location'] ) {
-			$url = add_query_arg( 'signature', urlencode( $signature ), $url );
-		}
-
-		return Jetpack_Client::_wp_remote_request( $url, $request );
-	}
-
-	/**
-	 * Wrapper for wp_remote_request().  Turns off SSL verification for certain SSL errors.
-	 * This is lame, but many, many, many hosts have misconfigured SSL.
-	 *
-	 * When Jetpack is registered, the jetpack_fallback_no_verify_ssl_certs option is set to the current time if:
-	 * 1. a certificate error is found AND
-	 * 2. not verifying the certificate works around the problem.
-	 *
-	 * The option is checked on each request.
-	 *
-	 * @internal
-	 * @todo: Better fallbacks (bundled certs?), feedback, UI, ....
-	 * @see Jetpack::fix_url_for_bad_hosts()
-	 *
-	 * @return array|WP_Error WP HTTP response on success
-	 */
-	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 );
-		}
-
-		if ( (int) $fallback ) {
-			// We're flagged to fallback
-			$args['sslverify'] = false;
-		}
-
-		$response = wp_remote_request( $url, $args );
-
-		if (
-			!$set_fallback                                     // We're not allowed to set the flag on this request, so whatever happens happens
-		||
-			isset( $args['sslverify'] ) && !$args['sslverify'] // No verification - no point in doing it again
-		||
-			!is_wp_error( $response )                          // Let it ride
-		) {
-			Jetpack_Client::set_time_diff( $response, $set_fallback );
-			return $response;
-		}
-
-		// At this point, we're not flagged to fallback and we are allowed to set the flag on this request.
-
-		$message = $response->get_error_message();
-
-		// Is it an SSL Certificate verification error?
-		if (
-			false === strpos( $message, '14090086' ) // OpenSSL SSL3 certificate error
-		&&
-			false === strpos( $message, '1407E086' ) // OpenSSL SSL2 certificate error
-		&&
-			false === strpos( $message, 'error setting certificate verify locations' ) // cURL CA bundle not found
-		&&
-			false === strpos( $message, 'Peer certificate cannot be authenticated with' ) // cURL CURLE_SSL_CACERT: CA bundle found, but not helpful
-			                                                                              // different versions of curl have different error messages
-			                                                                              // this string should catch them all
-		&&
-			false === strpos( $message, 'Problem with the SSL CA cert' ) // cURL CURLE_SSL_CACERT_BADFILE: probably access rights
-		) {
-			// No, it is not.
-			return $response;
-		}
-
-		// Redo the request without SSL certificate verification.
-		$args['sslverify'] = false;
-		$response = wp_remote_request( $url, $args );
-
-		if ( !is_wp_error( $response ) ) {
-			// The request went through this time, flag for future fallbacks
-			Jetpack::update_option( 'fallback_no_verify_ssl_certs', time() );
-			Jetpack_Client::set_time_diff( $response, $set_fallback );
-		}
-
-		return $response;
-	}
-
-	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
-		if ( 200 != $code && 304 != $code && 400 != $code && 401 != $code ) {
-			return;
-		}
-
-		if ( !$date = wp_remote_retrieve_header( $response, 'date' ) ) {
-			return;
-		}
-
-		if ( 0 >= $time = (int) strtotime( $date ) ) {
-			return;
-		}
-
-		$time_diff = $time - time();
-
-		if ( $force_set ) { // during register
-			Jetpack::update_option( 'time_diff', $time_diff );
-		} else { // otherwise
-			$old_diff = Jetpack::get_option( 'time_diff' );
-			if ( false === $old_diff || abs( $time_diff - (int) $old_diff ) > 10 ) {
-				Jetpack::update_option( 'time_diff', $time_diff );
-			}
-		}
-	}
-}
-
-class Jetpack_Data {
-	/**
-	 * Gets locally stored token
-	 *
-	 * @return object|false
-	 */
-	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;
-			}
-			if ( $user_id != $token_chunks[2] ) {
-				return false;
-			}
-			$token = "{$token_chunks[0]}.{$token_chunks[1]}";
-		} else {
-			$token = Jetpack::get_option( 'blog_token' );
-			if ( empty( $token ) ) {
-				return false;
-			}
-		}
-
-		return (object) array(
-			'secret' => $token,
-			'external_user_id' => (int) $user_id,
-		);
-	}
-}
-
-/**
- * Client = Plugin
- * Client Server = API Methods the Plugin must respond to
- *
- * @todo Roll this into Jetpack?  There's only one 'public' method now: ::authorize().
- */
-class Jetpack_Client_Server {
-	function authorize() {
-		$data = stripslashes_deep( $_GET );
-
-		$args = array();
-
-		$redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
-
-		do {
-			$jetpack = Jetpack::init();
-			$role = $jetpack->translate_current_user_to_role();
-			if ( !$role ) {
-				Jetpack::state( 'error', 'no_role' );
-				break;
-			}
-
-			$cap = $jetpack->translate_role_to_cap( $role );
-			if ( !$cap ) {
-				Jetpack::state( 'error', 'no_cap' );
-				break;
-			}
-
-			check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
-
-			if ( !empty( $data['error'] ) ) {
-				Jetpack::state( 'error', $data['error'] );
-				break;
-			}
-
-			if ( empty( $data['state'] ) ) {
-				Jetpack::state( 'error', 'no_state' );
-				break;
-			}
-
-			if ( !ctype_digit( $data['state'] ) ) {
-				Jetpack::state( 'error', 'invalid_state' );
-				break;
-			}
-
-			$current_user_id = get_current_user_id();
-			if ( $current_user_id != $data['state'] ) {
-				Jetpack::state( 'error', 'wrong_state' );
-				break;
-			}
-
-			if ( empty( $data['code'] ) ) {
-				Jetpack::state( 'error', 'no_code' );
-				break;
-			}
-
-			$token = $this->get_token( $data );
-
-			if ( is_wp_error( $token ) ) {
-				if ( $error = $token->get_error_code() )
-					Jetpack::state( 'error', $error );
-				else
-					Jetpack::state( 'error', 'invalid_token' );
-
-				Jetpack::state( 'error_description', $token->get_error_message() );
-
-				break;
-			}
-
-			if ( !$token ) {
-				Jetpack::state( 'error', 'no_token' );
-				break;
-			}
-
-			$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' );
-
-				Jetpack::activate_default_modules( 999, 1, $active_modules );
-			} else {
-				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 );
-
-		if ( wp_validate_redirect( $redirect ) ) {
-			wp_safe_redirect( $redirect );
-		} else {
-			wp_safe_redirect( Jetpack::admin_url() );
-		}
-
-		exit;
-	}
-
-	public static function deactivate_plugin( $probable_file, $probable_title ) {
-		if ( is_plugin_active( $probable_file ) ) {
-			deactivate_plugins( $probable_file );
-			return 1;
-		} else {
-			// If the plugin is not in the usual place, try looking through all active plugins.
-			$active_plugins = get_option( 'active_plugins', array() );
-			foreach ( $active_plugins as $plugin ) {
-				$data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
-				if ( $data['Name'] == $probable_title ) {
-					deactivate_plugins( $plugin );
-					return 1;
-				}
-			}
-		}
-
-		return 0;
-	}
-
-	/**
-	 * @return object|WP_Error
-	 */
-	function get_token( $data ) {
-		$jetpack = Jetpack::init();
-		$role = $jetpack->translate_current_user_to_role();
-
-		if ( !$role ) {
-			return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
-		}
-
-		$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,
-			'grant_type' => 'authorization_code',
-			'code' => $data['code'],
-			'redirect_uri' => add_query_arg( array(
-				'action' => 'authorize',
-				'_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
-				'redirect' => $redirect ? urlencode( $redirect ) : false,
-			), menu_page_url( 'jetpack', false ) ),
-		);
-
-		$args = array(
-			'method' => 'POST',
-			'body' => $body,
-			'headers' => array(
-				'Accept' => 'application/json',
-			),
-		);
-		$response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'token' ), $args ), $args );
-
-		if ( is_wp_error( $response ) ) {
-			return new Jetpack_Error( 'token_http_request_failed', $response->get_error_message() );
-		}
-
-		$code = wp_remote_retrieve_response_code( $response );
-		$entity = wp_remote_retrieve_body( $response );
-
-		if ( $entity )
-			$json = json_decode( $entity );
-		else
-			$json = false;
-
-		if ( 200 != $code || !empty( $json->error ) ) {
-			if ( empty( $json->error ) )
-				return new Jetpack_Error( 'unknown', '', $code );
-
-			$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 );
-		}
-
-		if ( empty( $json->access_token ) || !is_scalar( $json->access_token ) ) {
-			return new Jetpack_Error( 'access_token', '', $code );
-		}
-
-		if ( empty( $json->token_type ) || 'X_JETPACK' != strtoupper( $json->token_type ) ) {
-			return new Jetpack_Error( 'token_type', '', $code );
-		}
-
-		if ( empty( $json->scope ) ) {
-			return new Jetpack_Error( 'scope', 'No Scope', $code );
-		}
-		@list( $role, $hmac ) = explode( ':', $json->scope );
-		if ( empty( $role ) || empty( $hmac ) ) {
-			return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
-		}
-		if ( $jetpack->sign_role( $role ) !== $json->scope ) {
-			return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
-		}
-
-		if ( !$cap = $jetpack->translate_role_to_cap( $role ) )
-			return new Jetpack_Error( 'scope', 'No Cap', $code );
-		if ( !current_user_can( $cap ) )
-			return new Jetpack_Error( 'scope', 'current_user_cannot', $code );
-
-		return (string) $json->access_token;
-	}
-}
-
-
-/**
- * Request that a piece of data on this WordPress install be synced back to the
- * Jetpack server for remote processing/notifications/etc
- */
-class Jetpack_Sync {
-	// 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 __construct() {
-		// WP Cron action.  Only used on upgrade
-		add_action( 'jetpack_sync_all_registered_options', array( $this, 'sync_all_registered_options' ) );
-	}
-
-/* Static Methods for Modules */
-
-	/**
-	 * @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 );
-	}
-
-	/**
-	 * @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 | option ]
-	 * @param int $id Unique identifier
-	 * @param array $settings
-	 */
-	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
-		}
-
-		$defaults = array(
-			'on_behalf_of' => array(), // What modules want this data
-		);
-		$settings = wp_parse_args( $settings, $defaults );
-
-		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 {
-			// 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'] ) );
-		}
-
-		$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();
-		foreach ( $available_modules as $available_module ) {
-			$modules[$available_module] = in_array( $available_module, $active_modules );
-		}
-		$modules['vaultpress'] = class_exists( 'VaultPress' ) || function_exists( 'vaultpress_contact_service' );
-
-		$sync_data = array(
-			'modules' => $modules,
-			'version' => JETPACK__VERSION,
-		);
-
-		return $sync_data;
-	}
-
-	/**
-	 * Set up all the data and queue it for the outgoing XML-RPC request
-	 */
-	function sync() {
-		if ( !$this->sync ) {
-			return false;
-		}
-
-		$sync_data = $this->get_common_sync_data();
-
-		$wp_importing = defined( 'WP_IMPORTING' ) && WP_IMPORTING;
-
-		foreach ( $this->sync as $sync_operation_type => $sync_operations ) {
-			switch ( $sync_operation_type ) {
-			case 'post':
-				if ( $wp_importing ) {
-					break;
-				}
-
-				$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;
-				}
-
-				$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 );
-					}
-					$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;
-
-			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 );
-	}
-
-	/**
-	 * 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 ( 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;
-	}
-
-	/**
-	 * Helper method for registering a post for sync
-	 *
-	 * @param int $id wp_posts.ID
-	 * @param array $settings Sync data
-	 */
-	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 registering a comment for sync
-	 *
-	 * @param int $id wp_comments.comment_ID
-	 * @param array $settings Sync data
-	 */
-	function register_comment( $id, array $settings = null ) {
-		$id = (int) $id;
-		if ( !$id ) {
-			return false;
-		}
-
-		$comment = get_comment( $id );
-		if ( !$comment || empty( $comment->comment_post_ID ) ) {
-			return false;
-		}
-
-		$post = get_post( $comment->comment_post_ID );
-		if ( !$post ) {
-			return false;
-		}
-
-		$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;
-		}
-
-		// 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;
-	}
-
-	/**
-	 * Get a post and associated data in the standard JP format.
-	 * Cannot be called statically
-	 *
-	 * @param int $id Post ID
-	 * @return Array containing full post details
-	 */
-	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;
-	}
-
-	/**
-	 * 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 ) ) {
-			$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 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;
-		}
-
-		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 ( '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;
-		}
-
-		$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;
-	}
-
-	/**
-	 * Get a comment and associated data in the standard JP format.
-	 * Cannot be called statically
-	 *
-	 * @param int $id Comment ID
-	 * @return Array containing full comment details
-	 */
-	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 {}
+// Constants for expressing human-readable intervals
+// in their respective number of seconds.
+// Introduced in WordPress 3.5, specified here for backward compatability.
+defined( 'MINUTE_IN_SECONDS' ) or define( 'MINUTE_IN_SECONDS', 60 );
+defined( 'HOUR_IN_SECONDS' )   or define( 'HOUR_IN_SECONDS',   60 * MINUTE_IN_SECONDS );
+defined( 'DAY_IN_SECONDS' )    or define( 'DAY_IN_SECONDS',    24 * HOUR_IN_SECONDS   );
+defined( 'WEEK_IN_SECONDS' )   or define( 'WEEK_IN_SECONDS',    7 * DAY_IN_SECONDS    );
+defined( 'YEAR_IN_SECONDS' )   or define( 'YEAR_IN_SECONDS',  365 * DAY_IN_SECONDS    );
+
+// @todo: Abstract out the admin functions, and only include them if is_admin()
+// @todo: Only include things like class.jetpack-sync.php if we're connected.
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack.php'               );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-client.php'        );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-data.php'          );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-client-server.php' );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-sync.php'          );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-options.php'       );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-user-agent.php'    );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-post-images.php'   );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-error.php'         );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-debugger.php'      );
+require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-heartbeat.php'     );
+require_once( JETPACK__PLUGIN_DIR . 'class.photon.php'                );
+require_once( JETPACK__PLUGIN_DIR . 'functions.photon.php'            );
+require_once( JETPACK__PLUGIN_DIR . 'functions.compat.php'            );
+require_once( JETPACK__PLUGIN_DIR . 'functions.gallery.php'           );
 
 register_activation_hook( __FILE__, array( 'Jetpack', 'plugin_activation' ) );
 register_deactivation_hook( __FILE__, array( 'Jetpack', 'plugin_deactivation' ) );
 
 add_action( 'init', array( 'Jetpack', 'init' ) );
+add_action( 'init', array( 'Jetpack_Heartbeat', 'init' ), 100 );
 add_action( 'plugins_loaded', array( 'Jetpack', 'load_modules' ), 100 );
 add_filter( 'jetpack_static_url', array( 'Jetpack', 'staticize_subdomain' ) );
 
+/*
+if ( is_admin() && ! Jetpack::check_identity_crisis() ) {
+	Jetpack_Sync::sync_options( __FILE__, 'db_version', 'jetpack_active_modules', 'active_plugins' );
+}
+*/
+
 Jetpack_Sync::sync_options( __FILE__, 'widget_twitter' );

diff --git a/plugins/jetpack/languages/jetpack-ar.mo b/plugins/jetpack/languages/jetpack-ar.mo
index 254be8e..e057c91 100644
Binary files a/plugins/jetpack/languages/jetpack-ar.mo and b/plugins/jetpack/languages/jetpack-ar.mo differ

diff --git a/plugins/jetpack/languages/jetpack-az.mo b/plugins/jetpack/languages/jetpack-az.mo
index 033f859..1a17b7b 100644
Binary files a/plugins/jetpack/languages/jetpack-az.mo and b/plugins/jetpack/languages/jetpack-az.mo differ

diff --git a/plugins/jetpack/languages/jetpack-bs_BA.mo b/plugins/jetpack/languages/jetpack-bs_BA.mo
index 67cd446..40cc45b 100644
Binary files a/plugins/jetpack/languages/jetpack-bs_BA.mo and b/plugins/jetpack/languages/jetpack-bs_BA.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ca.mo b/plugins/jetpack/languages/jetpack-ca.mo
index 2daa9e1..68167b2 100644
Binary files a/plugins/jetpack/languages/jetpack-ca.mo and b/plugins/jetpack/languages/jetpack-ca.mo differ

diff --git a/plugins/jetpack/languages/jetpack-cs_CZ.mo b/plugins/jetpack/languages/jetpack-cs_CZ.mo
index 5e08877..220421d 100644
Binary files a/plugins/jetpack/languages/jetpack-cs_CZ.mo and b/plugins/jetpack/languages/jetpack-cs_CZ.mo differ

diff --git a/plugins/jetpack/languages/jetpack-da_DK.mo b/plugins/jetpack/languages/jetpack-da_DK.mo
index 773e5b5..c5af6d8 100644
Binary files a/plugins/jetpack/languages/jetpack-da_DK.mo and b/plugins/jetpack/languages/jetpack-da_DK.mo differ

diff --git a/plugins/jetpack/languages/jetpack-de_DE.mo b/plugins/jetpack/languages/jetpack-de_DE.mo
index a93c1c7..c9b11ee 100644
Binary files a/plugins/jetpack/languages/jetpack-de_DE.mo and b/plugins/jetpack/languages/jetpack-de_DE.mo differ

diff --git a/plugins/jetpack/languages/jetpack-el.mo b/plugins/jetpack/languages/jetpack-el.mo
index 8538e68..6487268 100644
Binary files a/plugins/jetpack/languages/jetpack-el.mo and b/plugins/jetpack/languages/jetpack-el.mo differ

diff --git a/plugins/jetpack/languages/jetpack-es_ES.mo b/plugins/jetpack/languages/jetpack-es_ES.mo
index 3cc9243..4f8be59 100644
Binary files a/plugins/jetpack/languages/jetpack-es_ES.mo and b/plugins/jetpack/languages/jetpack-es_ES.mo differ

diff --git a/plugins/jetpack/languages/jetpack-fa_IR.mo b/plugins/jetpack/languages/jetpack-fa_IR.mo
index f34c74e..096ac42 100644
Binary files a/plugins/jetpack/languages/jetpack-fa_IR.mo and b/plugins/jetpack/languages/jetpack-fa_IR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-fi.mo b/plugins/jetpack/languages/jetpack-fi.mo
index 591c047..913b15a 100644
Binary files a/plugins/jetpack/languages/jetpack-fi.mo and b/plugins/jetpack/languages/jetpack-fi.mo differ

diff --git a/plugins/jetpack/languages/jetpack-fr_FR.mo b/plugins/jetpack/languages/jetpack-fr_FR.mo
index 165c2b9..5fa71ad 100644
Binary files a/plugins/jetpack/languages/jetpack-fr_FR.mo and b/plugins/jetpack/languages/jetpack-fr_FR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-gl_ES.mo b/plugins/jetpack/languages/jetpack-gl_ES.mo
index e5f4c09..2e88f28 100644
Binary files a/plugins/jetpack/languages/jetpack-gl_ES.mo and b/plugins/jetpack/languages/jetpack-gl_ES.mo differ

diff --git a/plugins/jetpack/languages/jetpack-he_IL.mo b/plugins/jetpack/languages/jetpack-he_IL.mo
index 90d820c..cf18acd 100644
Binary files a/plugins/jetpack/languages/jetpack-he_IL.mo and b/plugins/jetpack/languages/jetpack-he_IL.mo differ

diff --git a/plugins/jetpack/languages/jetpack-hr.mo b/plugins/jetpack/languages/jetpack-hr.mo
index 8765f20..d1608ba 100644
Binary files a/plugins/jetpack/languages/jetpack-hr.mo and b/plugins/jetpack/languages/jetpack-hr.mo differ

diff --git a/plugins/jetpack/languages/jetpack-hu_HU.mo b/plugins/jetpack/languages/jetpack-hu_HU.mo
index 1171565..27fbc98 100644
Binary files a/plugins/jetpack/languages/jetpack-hu_HU.mo and b/plugins/jetpack/languages/jetpack-hu_HU.mo differ

diff --git a/plugins/jetpack/languages/jetpack-id_ID.mo b/plugins/jetpack/languages/jetpack-id_ID.mo
index 8d3427d..c0cddc0 100644
Binary files a/plugins/jetpack/languages/jetpack-id_ID.mo and b/plugins/jetpack/languages/jetpack-id_ID.mo differ

diff --git a/plugins/jetpack/languages/jetpack-it_IT.mo b/plugins/jetpack/languages/jetpack-it_IT.mo
index 7165de1..fc6d8f4 100644
Binary files a/plugins/jetpack/languages/jetpack-it_IT.mo and b/plugins/jetpack/languages/jetpack-it_IT.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ja.mo b/plugins/jetpack/languages/jetpack-ja.mo
index f715cc9..698be13 100644
Binary files a/plugins/jetpack/languages/jetpack-ja.mo and b/plugins/jetpack/languages/jetpack-ja.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ko_KR.mo b/plugins/jetpack/languages/jetpack-ko_KR.mo
index 3a7a529..46a7b08 100644
Binary files a/plugins/jetpack/languages/jetpack-ko_KR.mo and b/plugins/jetpack/languages/jetpack-ko_KR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-lt_LT.mo b/plugins/jetpack/languages/jetpack-lt_LT.mo
index 55f190a..3917f2f 100644
Binary files a/plugins/jetpack/languages/jetpack-lt_LT.mo and b/plugins/jetpack/languages/jetpack-lt_LT.mo differ

diff --git a/plugins/jetpack/languages/jetpack-mk_MK.mo b/plugins/jetpack/languages/jetpack-mk_MK.mo
index 804e8a3..4fc204d 100644
Binary files a/plugins/jetpack/languages/jetpack-mk_MK.mo and b/plugins/jetpack/languages/jetpack-mk_MK.mo differ

diff --git a/plugins/jetpack/languages/jetpack-my_MM.mo b/plugins/jetpack/languages/jetpack-my_MM.mo
index 1d1604b..02d9ab3 100644
Binary files a/plugins/jetpack/languages/jetpack-my_MM.mo and b/plugins/jetpack/languages/jetpack-my_MM.mo differ

diff --git a/plugins/jetpack/languages/jetpack-nb_NO.mo b/plugins/jetpack/languages/jetpack-nb_NO.mo
index 5600cf1..ba9a07e 100644
Binary files a/plugins/jetpack/languages/jetpack-nb_NO.mo and b/plugins/jetpack/languages/jetpack-nb_NO.mo differ

diff --git a/plugins/jetpack/languages/jetpack-nl_NL.mo b/plugins/jetpack/languages/jetpack-nl_NL.mo
index a125514..3e5b323 100644
Binary files a/plugins/jetpack/languages/jetpack-nl_NL.mo and b/plugins/jetpack/languages/jetpack-nl_NL.mo differ

diff --git a/plugins/jetpack/languages/jetpack-nn_NO.mo b/plugins/jetpack/languages/jetpack-nn_NO.mo
index 1157c95..e97633a 100644
Binary files a/plugins/jetpack/languages/jetpack-nn_NO.mo and b/plugins/jetpack/languages/jetpack-nn_NO.mo differ

diff --git a/plugins/jetpack/languages/jetpack-pl_PL.mo b/plugins/jetpack/languages/jetpack-pl_PL.mo
index 3a5df93..3e68660 100644
Binary files a/plugins/jetpack/languages/jetpack-pl_PL.mo and b/plugins/jetpack/languages/jetpack-pl_PL.mo differ

diff --git a/plugins/jetpack/languages/jetpack-pt_BR.mo b/plugins/jetpack/languages/jetpack-pt_BR.mo
index da51355..a4aa227 100644
Binary files a/plugins/jetpack/languages/jetpack-pt_BR.mo and b/plugins/jetpack/languages/jetpack-pt_BR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-pt_PT.mo b/plugins/jetpack/languages/jetpack-pt_PT.mo
index 62d6331..8afc9be 100644
Binary files a/plugins/jetpack/languages/jetpack-pt_PT.mo and b/plugins/jetpack/languages/jetpack-pt_PT.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ro_RO.mo b/plugins/jetpack/languages/jetpack-ro_RO.mo
index 6a76116..6b6b6e3 100644
Binary files a/plugins/jetpack/languages/jetpack-ro_RO.mo and b/plugins/jetpack/languages/jetpack-ro_RO.mo differ

diff --git a/plugins/jetpack/languages/jetpack-ru_RU.mo b/plugins/jetpack/languages/jetpack-ru_RU.mo
index 392de6d..12ab452 100644
Binary files a/plugins/jetpack/languages/jetpack-ru_RU.mo and b/plugins/jetpack/languages/jetpack-ru_RU.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sa_IN.mo b/plugins/jetpack/languages/jetpack-sa_IN.mo
index f7bfee6..6e87f22 100644
Binary files a/plugins/jetpack/languages/jetpack-sa_IN.mo and b/plugins/jetpack/languages/jetpack-sa_IN.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sk_SK.mo b/plugins/jetpack/languages/jetpack-sk_SK.mo
index 0f6a8ea..8cb3074 100644
Binary files a/plugins/jetpack/languages/jetpack-sk_SK.mo and b/plugins/jetpack/languages/jetpack-sk_SK.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sq.mo b/plugins/jetpack/languages/jetpack-sq.mo
index 795f5ab..8785650 100644
Binary files a/plugins/jetpack/languages/jetpack-sq.mo and b/plugins/jetpack/languages/jetpack-sq.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sr_RS.mo b/plugins/jetpack/languages/jetpack-sr_RS.mo
index 62d2959..c6d753d 100644
Binary files a/plugins/jetpack/languages/jetpack-sr_RS.mo and b/plugins/jetpack/languages/jetpack-sr_RS.mo differ

diff --git a/plugins/jetpack/languages/jetpack-sv_SE.mo b/plugins/jetpack/languages/jetpack-sv_SE.mo
index 382cbc3..60b01b1 100644
Binary files a/plugins/jetpack/languages/jetpack-sv_SE.mo and b/plugins/jetpack/languages/jetpack-sv_SE.mo differ

diff --git a/plugins/jetpack/languages/jetpack-th.mo b/plugins/jetpack/languages/jetpack-th.mo
index 1349918..f747b31 100644
Binary files a/plugins/jetpack/languages/jetpack-th.mo and b/plugins/jetpack/languages/jetpack-th.mo differ

diff --git a/plugins/jetpack/languages/jetpack-tr_TR.mo b/plugins/jetpack/languages/jetpack-tr_TR.mo
index 24eecce..09c0415 100644
Binary files a/plugins/jetpack/languages/jetpack-tr_TR.mo and b/plugins/jetpack/languages/jetpack-tr_TR.mo differ

diff --git a/plugins/jetpack/languages/jetpack-zh_CN.mo b/plugins/jetpack/languages/jetpack-zh_CN.mo
index 17900fb..d4fa8db 100644
Binary files a/plugins/jetpack/languages/jetpack-zh_CN.mo and b/plugins/jetpack/languages/jetpack-zh_CN.mo differ

diff --git a/plugins/jetpack/languages/jetpack-zh_TW.mo b/plugins/jetpack/languages/jetpack-zh_TW.mo
index 3866213..fda55d2 100644
Binary files a/plugins/jetpack/languages/jetpack-zh_TW.mo and b/plugins/jetpack/languages/jetpack-zh_TW.mo differ

diff --git a/plugins/jetpack/locales.php b/plugins/jetpack/locales.php
index e910fbf..5c306d4 100644
--- a/plugins/jetpack/locales.php
+++ b/plugins/jetpack/locales.php
@@ -1773,28 +1773,28 @@ class GP_Locales {
 		}
 	}
 
-	function &instance() {
+	static function instance() {
 		if ( !isset( $GLOBALS['gp_locales'] ) )
 			$GLOBALS['gp_locales'] = new GP_Locales;
 		return $GLOBALS['gp_locales'];
 	}
 
-	function locales() {
+	static function locales() {
 		$instance = GP_Locales::instance();
 		return $instance->locales;
 	}
 
-	function exists( $slug ) {
+	static function exists( $slug ) {
 		$instance = GP_Locales::instance();
 		return isset( $instance->locales[$slug] );
 	}
 
-	function by_slug( $slug ) {
+	static function by_slug( $slug ) {
 		$instance = GP_Locales::instance();
 		return isset( $instance->locales[$slug] )? $instance->locales[$slug] : null;
 	}
 
-	function by_field( $field_name, $field_value ) {
+	static function by_field( $field_name, $field_value ) {
 		$instance = GP_Locales::instance();
 		$result = false;
 		foreach( $instance->locales() as $locale ) {

diff --git a/plugins/jetpack/modules/after-the-deadline.php b/plugins/jetpack/modules/after-the-deadline.php
index 606f648..cf98ec0 100644
--- a/plugins/jetpack/modules/after-the-deadline.php
+++ b/plugins/jetpack/modules/after-the-deadline.php
@@ -4,21 +4,22 @@
  * Module Description: Improve your spelling, style, and grammar with the <a href="http://www.afterthedeadline.com/">After&nbsp;the&nbsp;Deadline</a> Proofreading service.
  * Sort Order: 6
  * First Introduced: 1.1
+ * Requires Connection: Yes
  */
- 
+
 add_action( 'jetpack_modules_loaded', 'AtD_load' );
 
 function AtD_load() {
-	Jetpack::enable_module_configurable( __FILE__ ); 
-	Jetpack::module_configuration_load( __FILE__, 'AtD_configuration_load' );	
+	Jetpack::enable_module_configurable( __FILE__ );
+	Jetpack::module_configuration_load( __FILE__, 'AtD_configuration_load' );
 }
 
 function AtD_configuration_load() {
 	wp_safe_redirect( get_edit_profile_url( get_current_user_id() ) . '#atd' );
-	exit;	
+	exit;
 }
 
-/*  
+/*
  *  Load necessary include files
  */
 include( 'after-the-deadline/config-options.php' );
@@ -56,7 +57,7 @@ function AtD_addbuttons() {
 	/* Don't bother doing this stuff if the current user lacks permissions */
 	if ( ! AtD_is_allowed() )
 		return;
-   
+
 	/* Add only in Rich Editor mode */
 	if ( get_user_option( 'rich_editing' ) == 'true' ) {
 		add_filter( 'mce_external_plugins', 'add_AtD_tinymce_plugin' );
@@ -85,16 +86,16 @@ function register_AtD_button( $buttons ) {
 	array_push( $buttons, '|', 'AtD' );
 	return $buttons;
 }
- 
+
 /*
- * Load the TinyMCE plugin : editor_plugin.js (wp2.5) 
+ * Load the TinyMCE plugin : editor_plugin.js (wp2.5)
  */
 function add_AtD_tinymce_plugin( $plugin_array ) {
 	$plugin_array['AtD'] = plugins_url( 'after-the-deadline/tinymce/editor_plugin.js?v=' . ATD_VERSION, __FILE__ );
 	return $plugin_array;
 }
 
-/* 
+/*
  * Update the TinyMCE init block with AtD specific settings
  */
 function AtD_change_mce_settings( $init_array ) {
@@ -116,15 +117,15 @@ function AtD_change_mce_settings( $init_array ) {
 	return $init_array;
 }
 
-/* 
+/*
  * Sanitizes AtD AJAX data to acceptable chars, caller needs to make sure ' is escaped
  */
 function AtD_sanitize( $untrusted ) {
         return preg_replace( '/[^a-zA-Z0-9\-\',_ ]/i', "", $untrusted );
 }
 
-/* 
- * AtD HTML Editor Stuff 
+/*
+ * AtD HTML Editor Stuff
  */
 function AtD_settings() {
         $user = wp_get_current_user();
@@ -156,20 +157,20 @@ function AtD_load_javascripts() {
         	wp_enqueue_script( 'AtD_jquery', plugins_url( '/after-the-deadline/jquery.atd.js', __FILE__ ), array('jquery'), ATD_VERSION );
         	wp_enqueue_script( 'AtD_settings', admin_url() . 'admin-ajax.php?action=atd_settings', array('AtD_jquery'), ATD_VERSION );
 		wp_enqueue_script( 'AtD_autoproofread', plugins_url( '/after-the-deadline/atd-autoproofread.js', __FILE__ ), array('AtD_jquery'), ATD_VERSION );
-	}		
+	}
 }
 
 /* Spits out user options for auto-proofreading on publish/update */
 function AtD_load_submit_check_javascripts() {
 	global $pagenow;
-	
+
 	$user = wp_get_current_user();
 	if ( ! $user || $user->ID == 0 )
 		return;
-	
+
 	if ( AtD_should_load_on_page() ) {
 		$atd_check_when = AtD_get_setting( $user->ID, 'AtD_check_when' );
-		
+
 		if ( !empty( $atd_check_when ) ) {
 			$check_when = array();
 			/* Set up the options in json */
@@ -238,7 +239,7 @@ add_action( 'init', 'AtD_addbuttons' );
 
 /* setup hooks for our PHP functions we want to make available via an AJAX call */
 add_action( 'wp_ajax_proxy_atd', 'AtD_redirect_call' );
-add_action( 'wp_ajax_atd_ignore', 'AtD_ignore_call' );    
+add_action( 'wp_ajax_atd_ignore', 'AtD_ignore_call' );
 add_action( 'wp_ajax_atd_settings', 'AtD_settings' );
 
 /* load and install the localization stuff */

diff --git a/plugins/jetpack/modules/after-the-deadline/atd-autoproofread.js b/plugins/jetpack/modules/after-the-deadline/atd-autoproofread.js
index b76a757..53ef766 100644
--- a/plugins/jetpack/modules/after-the-deadline/atd-autoproofread.js
+++ b/plugins/jetpack/modules/after-the-deadline/atd-autoproofread.js
@@ -37,13 +37,13 @@ function AtD_submit_check_callback(count) {
 	} else {
 		var original_post_status = jQuery('#original_post_status').val()
 
-		/* Okay, the user has tried to publish/update already but there are still errors. Ask them what to do */ 
+		/* Okay, the user has tried to publish/update already but there are still errors. Ask them what to do */
 		var message;
 		if ( original_post_status == 'publish' )
 			message = AtD.getLang('dialog_confirm_post_publish', 'The proofreader has suggestions for this post. Are you sure you want to publish it?\n\nPress OK to publish your post, or Cancel to view the suggestions and edit your post.');
 		else
 			message = AtD.getLang('dialog_confirm_post_update', 'The proofreader has suggestions for this post. Are you sure you want to update it?\n\nPress OK to update your post, or Cancel to view the suggestions and edit your post.');
-			
+
 		if ( confirm( message ) ) {
 			AtD_update_post();
 		} else {
@@ -66,7 +66,7 @@ function AtD_kill_autoproofread() {
 function AtD_update_post() {
 
 	if ( typeof(tinyMCE) == 'undefined' || !tinyMCE.activeEditor || tinyMCE.activeEditor.isHidden() )
-		AtD_restore_if_proofreading(); 
+		AtD_restore_if_proofreading();
 
 	jQuery('#publish').unbind('click.AtD_submit_check').click();
 }

diff --git a/plugins/jetpack/modules/after-the-deadline/atd-nonvis-editor-plugin.js b/plugins/jetpack/modules/after-the-deadline/atd-nonvis-editor-plugin.js
index 5d84497..88f2d9c 100644
--- a/plugins/jetpack/modules/after-the-deadline/atd-nonvis-editor-plugin.js
+++ b/plugins/jetpack/modules/after-the-deadline/atd-nonvis-editor-plugin.js
@@ -3,7 +3,7 @@ var AtD_qtbutton;
 function AtD_restore_text_area()
 {
 	/* clear the error HTML out of the preview div */
-	AtD.remove('content'); 
+	AtD.remove('content');
 
 	/* swap the preview div for the textarea, notice how I have to restore the appropriate class/id/style attributes */
     var content = jQuery('#content').html();
@@ -13,7 +13,7 @@ function AtD_restore_text_area()
 
 	jQuery('#content').replaceWith( AtD.content_canvas );
 	jQuery('#content').val( content.replace(/\&lt\;/g, '<').replace(/\&gt\;/g, '>').replace(/\&amp;/g, '&') );
-	jQuery('#content').height(AtD.height); 
+	jQuery('#content').height(AtD.height);
 
 	if ( AtD_qtbutton ) {
 		/* change the link text back to its original label */
@@ -42,7 +42,7 @@ if ( typeof(QTags) != 'undefined' && QTags.addButton ) {
 }
 
 function AtD_restore_if_proofreading() {
-	if ( AtD_qtbutton && jQuery(AtD_qtbutton).val() == AtD.getLang('button_edit_text', 'edit text') ) 
+	if ( AtD_qtbutton && jQuery(AtD_qtbutton).val() == AtD.getLang('button_edit_text', 'edit text') )
 		AtD_restore_text_area();
 }
 
@@ -84,8 +84,8 @@ function AtD_check(button) {
 
 	/* If the text of the link says edit comment, then restore the textarea so the user can edit the text */
 
-	if ( jQuery(AtD_qtbutton).val() == AtD.getLang('button_edit_text', 'edit text') ) {                               
-		AtD_restore_text_area(); 
+	if ( jQuery(AtD_qtbutton).val() == AtD.getLang('button_edit_text', 'edit text') ) {
+		AtD_restore_text_area();
 	} else {
 		/* initialize some of the stuff related to this plugin */
 		if ( !AtD.height ) {
@@ -124,7 +124,7 @@ function AtD_check(button) {
 		} else {
 			jQuery('#content').replaceWith('<div class="input" id="content">' + text + '</div>');
 			jQuery('#content').css( { 'overflow' : 'auto', 'background-color' : 'white', 'color' : 'black', 'white-space' : 'pre-wrap' } );
-			jQuery('#content').height(AtD.height); 
+			jQuery('#content').height(AtD.height);
 		}
 
 		/* kill autosave... :) */
@@ -144,16 +144,16 @@ function AtD_check(button) {
 			ready: function(errorCount) {
 				jQuery(AtD_qtbutton).attr('disabled', false);
 
-				if ( typeof callback === 'function' ) 
+				if ( typeof callback === 'function' )
 					callback( errorCount );
 			},
 
 			error: function(reason) {
 				jQuery(AtD_qtbutton).attr('disabled', false);
 
-				if ( typeof callback === 'function' ) 
+				if ( typeof callback === 'function' )
 					callback( -1 );
-				else 
+				else
 					alert( AtD.getLang('message_server_error', 'There was a problem communicating with the Proofreading service. Try again in one minute.') );
 
 				AtD_restore_if_proofreading();
@@ -164,7 +164,7 @@ function AtD_check(button) {
 
 				if ( text != null )
 					element.replaceWith( text );
-			}, 
+			},
 
 			explain: function(url) {
 				var left = (screen.width / 2) - (480 / 2);

diff --git a/plugins/jetpack/modules/after-the-deadline/atd.core.js b/plugins/jetpack/modules/after-the-deadline/atd.core.js
index 0e3d1c4..5d6efc9 100644
--- a/plugins/jetpack/modules/after-the-deadline/atd.core.js
+++ b/plugins/jetpack/modules/after-the-deadline/atd.core.js
@@ -74,18 +74,18 @@ AtDCore.prototype.showTypes = function(string) {
         });
 
         this.map(this.ignore_types, function(string) {
-                if (types[string] != undefined) 
+                if (types[string] != undefined)
                         ignore_types.push(string);
         });
 
         this.ignore_types = ignore_types;
 };
 
-/* 
+/*
  * Error Parsing Code
  */
 
-AtDCore.prototype.makeError = function(error_s, tokens, type, seps, pre) {        
+AtDCore.prototype.makeError = function(error_s, tokens, type, seps, pre) {
 	var struct = new Object();
 	struct.type = type;
 	struct.string = error_s;
@@ -110,20 +110,20 @@ AtDCore.prototype.makeError = function(error_s, tokens, type, seps, pre) {
 };
 
 AtDCore.prototype.addToErrorStructure = function(errors, list, type, seps) {
-	var parent = this;                  
+	var parent = this;
 
 	this.map(list, function(error) {
 		var tokens = error["word"].split(/\s+/);
 		var pre    = error["pre"];
 		var first  = tokens[0];
 
-		if (errors['__' + first] == undefined) {      
+		if (errors['__' + first] == undefined) {
 			errors['__' + first] = new Object();
 			errors['__' + first].pretoks  = {};
 			errors['__' + first].defaults = new Array();
 		}
 
-		if (pre == "") {               
+		if (pre == "") {
 			errors['__' + first].defaults.push(parent.makeError(error["word"], tokens, type, seps, pre));
 		} else {
 			if (errors['__' + first].pretoks['__' + pre] == undefined)
@@ -138,7 +138,7 @@ AtDCore.prototype.buildErrorStructure = function(spellingList, enrichmentList, g
 	var seps   = this._getSeparators();
 	var errors = {};
 
-	this.addToErrorStructure(errors, spellingList, "hiddenSpellError", seps);            
+	this.addToErrorStructure(errors, spellingList, "hiddenSpellError", seps);
 	this.addToErrorStructure(errors, grammarList, "hiddenGrammarError", seps);
 	this.addToErrorStructure(errors, enrichmentList, "hiddenSuggestion", seps);
 	return errors;
@@ -153,7 +153,7 @@ AtDCore.prototype._getSeparators = function() {
 		re += '\\' + str.charAt(i);
 
 	return "(?:(?:[\xa0" + re  + "])|(?:\\-\\-))+";
-};        
+};
 
 AtDCore.prototype.processXML = function(responseXML) {
 
@@ -183,8 +183,8 @@ AtDCore.prototype.processXML = function(responseXML) {
 
 			var errorContext;
 
-			if (errors[i].getElementsByTagName('precontext').item(0).firstChild != null) 
-				errorContext = errors[i].getElementsByTagName('precontext').item(0).firstChild.data;   
+			if (errors[i].getElementsByTagName('precontext').item(0).firstChild != null)
+				errorContext = errors[i].getElementsByTagName('precontext').item(0).firstChild.data;
 			else
 				errorContext = "";
 
@@ -236,11 +236,11 @@ AtDCore.prototype.processXML = function(responseXML) {
 
 				if (errorDescription == "Repeated Word")
 					suggestion["description"] = this.getLang('menu_title_repeated_word', 'Repeated Word');
-				
+
 				if (errorDescription == "Did you mean...")
 					suggestion["description"] = this.getLang('menu_title_confused_word', 'Did you mean...');
 			} // end if ignore[errorString] == undefined
-		} // end if 
+		} // end if
 	} // end for loop
 
 	var errorStruct;
@@ -265,10 +265,10 @@ AtDCore.prototype.findSuggestion = function(element) {
 
 	var errorDescription = undefined;
 	var len = this.suggestions.length;
-   
+
 	for (var i = 0; i < len; i++) {
 		var key = this.suggestions[i]["string"];
-   
+
 		if ((context == "" || context == this.suggestions[i]["context"]) && this.suggestions[i]["matcher"].test(text)) {
 			errorDescription = this.suggestions[i];
 			break;
@@ -299,7 +299,7 @@ TokenIterator.prototype.next = function() {
 		if (current[0] == "'")
 			current = current.substring(1, current.length);
 
-		if (current[current.length - 1] == "'") 
+		if (current[current.length - 1] == "'")
 			current = current.substring(0, current.length - 1);
 	}
 
@@ -311,7 +311,7 @@ TokenIterator.prototype.hasNext = function() {
 };
 
 TokenIterator.prototype.hasNextN = function(n) {
-	return (this.index + n) < this.tokens.length;            
+	return (this.index + n) < this.tokens.length;
 };
 
 TokenIterator.prototype.skip = function(m, n) {
@@ -334,10 +334,10 @@ TokenIterator.prototype.peek = function(n) {
 	return peepers;
 };
 
-/* 
+/*
  *  code to manage highlighting of errors
  */
-AtDCore.prototype.markMyWords = function(container_nodes, errors) {           
+AtDCore.prototype.markMyWords = function(container_nodes, errors) {
 	var seps  = new RegExp(this._getSeparators());
 	var nl = new Array();
 	var ecount = 0; /* track number of highlighted errors */
@@ -345,16 +345,16 @@ AtDCore.prototype.markMyWords = function(container_nodes, errors) {
 
 	/* Collect all text nodes */
 	/* Our goal--ignore nodes that are already wrapped */
-   
+
 	this._walk(container_nodes, function(n) {
 		if (n.nodeType == 3 && !parent.isMarkedNode(n))
 			nl.push(n);
 	});
- 
-	/* walk through the relevant nodes */  
-   
+
+	/* walk through the relevant nodes */
+
 	var iterator;
-      
+
 	this.map(nl, function(n) {
 		var v;
 
@@ -431,7 +431,7 @@ AtDCore.prototype.markMyWords = function(container_nodes, errors) {
 								return parent.create('<span class="mceItemHidden">&nbsp;</span>' + node.nodeValue.substr(1, node.nodeValue.length - 1).replace(regexp, result), false);
 							else
 								return parent.create(node.nodeValue.replace(regexp, result), false);
-						} 
+						}
 						else {
 							var contents = parent.contents(node);
 
@@ -462,8 +462,8 @@ AtDCore.prototype.markMyWords = function(container_nodes, errors) {
 
 				parent.replaceWith(n, newNode);
 			}
-		} 
-	}); 
+		}
+	});
 
 	return ecount;
 };
@@ -474,9 +474,9 @@ AtDCore.prototype._walk = function(elements, f) {
 		f.call(f, elements[i]);
 		this._walk(this.contents(elements[i]), f);
 	}
-};  
+};
 
-AtDCore.prototype.removeWords = function(node, w) {   
+AtDCore.prototype.removeWords = function(node, w) {
 	var count = 0;
 	var parent = this;
 
@@ -518,7 +518,7 @@ AtDCore.prototype.applySuggestion = function(element, suggestion) {
 	}
 };
 
-/* 
+/*
  * Check for an error
  */
 AtDCore.prototype.hasErrorMessage = function(xmlr) {

diff --git a/plugins/jetpack/modules/after-the-deadline/atd.css b/plugins/jetpack/modules/after-the-deadline/atd.css
index 5014fea..2f59bd2 100644
--- a/plugins/jetpack/modules/after-the-deadline/atd.css
+++ b/plugins/jetpack/modules/after-the-deadline/atd.css
@@ -25,7 +25,7 @@
  * Project      : http://jquery-spellchecker.googlecode.com
  */
 
-#suggestmenu 
+#suggestmenu
 {
    min-width: 122px;
    background: #ebeaeb;
@@ -39,27 +39,27 @@
    font-family: Tahoma, Verdana, Arial, Helvetica;
 }
 
-#suggestmenu strong 
+#suggestmenu strong
 {
    background: #cccccc;
    font-weight: bold;
-   padding:3px 6px 3px 6px;    
-   display:block;               
+   padding:3px 6px 3px 6px;
+   display:block;
    border:1px solid #dddddd;
-   border-bottom: 1px solid #aaaaaa; 
+   border-bottom: 1px solid #aaaaaa;
    color: black;
 }
 
-#suggestmenu em 
+#suggestmenu em
 {
-   text-align:center;    
-   padding:3px 6px 3px 6px;    
-   display:block;               
+   text-align:center;
+   padding:3px 6px 3px 6px;
+   display:block;
    border-top:1px solid #ccc;
    border-left:1px solid #ccc;
 }
 
-#suggestmenu a, #suggestmenu a:visited 
+#suggestmenu a, #suggestmenu a:visited
 {
    background: #ebeaeb;
    border-left:1px solid #dddddd;
@@ -72,34 +72,34 @@
    outline:none
 }
 
-#suggestmenu a.first, #suggestmenu a.first:visited 
+#suggestmenu a.first, #suggestmenu a.first:visited
 {
    border-top:1px solid #dddddd;
 }
 
-.spell_sep_bottom 
+.spell_sep_bottom
 {
    border-bottom: 1px solid #dddddd;
 }
 
-.spell_sep_top 
+.spell_sep_top
 {
    border-top: 1px solid #aaaaaa;
 }
 
-#suggestmenu a:hover 
+#suggestmenu a:hover
 {
    color:#000;
    background: #f5f5f5;
 }
 
-#suggestmenu .foot 
+#suggestmenu .foot
 {
    border-top:1px solid #aaaaaa;
    background:#fff
 }
 
-#suggestmenu .foot a, #suggestmenu .foot a:visited 
+#suggestmenu .foot a, #suggestmenu .foot a:visited
 {
    outline:none
 }

diff --git a/plugins/jetpack/modules/after-the-deadline/config-options.php b/plugins/jetpack/modules/after-the-deadline/config-options.php
index 097b062..db4a49c 100644
--- a/plugins/jetpack/modules/after-the-deadline/config-options.php
+++ b/plugins/jetpack/modules/after-the-deadline/config-options.php
@@ -49,8 +49,8 @@ function AtD_display_options_form() {
 		 <td>
    <p><?php _e( 'Automatically proofread content when:', 'jetpack' ); ?>
 
-   <p><?php 
-		AtD_print_option( 'onpublish', __('a post or page is first published', 'jetpack'), $options_check_when ); 
+   <p><?php
+		AtD_print_option( 'onpublish', __('a post or page is first published', 'jetpack'), $options_check_when );
 		echo '<br />';
 		AtD_print_option( 'onupdate', __('a post or page is updated', 'jetpack'), $options_check_when );
    ?></p>
@@ -59,12 +59,12 @@ function AtD_display_options_form() {
 
    <p><?php _e('Enable proofreading for the following grammar and style rules when writing posts and pages:', 'jetpack'); ?></p>
 
-   <p><?php 
+   <p><?php
 		AtD_print_option( 'Bias Language', __('Bias Language', 'jetpack'), $options_show_types );
 		echo '<br />';
 		AtD_print_option( 'Cliches', __('Clich&eacute;s', 'jetpack'), $options_show_types );
 		echo '<br />';
-		AtD_print_option( 'Complex Expression', __('Complex Phrases', 'jetpack'), $options_show_types ); 
+		AtD_print_option( 'Complex Expression', __('Complex Phrases', 'jetpack'), $options_show_types );
 		echo '<br />';
 		AtD_print_option( 'Diacritical Marks', __('Diacritical Marks', 'jetpack'), $options_show_types );
 		echo '<br />';
@@ -72,15 +72,15 @@ function AtD_display_options_form() {
 		echo '<br />';
 		AtD_print_option( 'Hidden Verbs', __('Hidden Verbs', 'jetpack'), $options_show_types );
 		echo '<br />';
-		AtD_print_option( 'Jargon Language', __('Jargon', 'jetpack'), $options_show_types ); 
+		AtD_print_option( 'Jargon Language', __('Jargon', 'jetpack'), $options_show_types );
 		echo '<br />';
-		AtD_print_option( 'Passive voice', __('Passive Voice', 'jetpack'), $options_show_types ); 
+		AtD_print_option( 'Passive voice', __('Passive Voice', 'jetpack'), $options_show_types );
 		echo '<br />';
-		AtD_print_option( 'Phrases to Avoid', __('Phrases to Avoid', 'jetpack'), $options_show_types ); 
+		AtD_print_option( 'Phrases to Avoid', __('Phrases to Avoid', 'jetpack'), $options_show_types );
 		echo '<br />';
-		AtD_print_option( 'Redundant Expression', __('Redundant Phrases', 'jetpack'), $options_show_types ); 
+		AtD_print_option( 'Redundant Expression', __('Redundant Phrases', 'jetpack'), $options_show_types );
    ?></p>
-   <p><?php printf( __( '<a href="%s">Learn more</a> about these options.', 'jetpack' ), 'http://support.wordpress.com/proofreading/' ); 
+   <p><?php printf( __( '<a href="%s">Learn more</a> about these options.', 'jetpack' ), 'http://support.wordpress.com/proofreading/' );
 ?></p>
 
    <p style="font-weight: bold"><?php _e( 'Language', 'jetpack' ); ?></font>
@@ -103,14 +103,14 @@ function AtD_display_options_form() {
  */
 function AtD_get_options( $user_id, $name ) {
 	$options_raw = AtD_get_setting( $user_id, $name, 'single' );
-	
+
 	$options = array();
 	$options['name'] = $name;
 
 	if ( $options_raw )
-		foreach ( explode( ',', $options_raw ) as $option ) 
+		foreach ( explode( ',', $options_raw ) as $option )
 			$options[ $option ] = 1;
-	
+
 	return $options;
 }
 
@@ -125,6 +125,6 @@ function AtD_update_options( $user_id, $name ) {
 	} else {
 		AtD_update_setting( $user_id, AtD_sanitize( $name ), '');
 	}
-	
+
 	return;
 }

diff --git a/plugins/jetpack/modules/after-the-deadline/config-unignore.php b/plugins/jetpack/modules/after-the-deadline/config-unignore.php
index 9d49fa2..84b18ff 100644
--- a/plugins/jetpack/modules/after-the-deadline/config-unignore.php
+++ b/plugins/jetpack/modules/after-the-deadline/config-unignore.php
@@ -1,5 +1,5 @@
 <?php
-/* 
+/*
  *  Called by the TinyMCE plugin when Ignore Always is clicked (setup as an action through admin-ajax.php)
  */
 function AtD_ignore_call() {
@@ -24,7 +24,7 @@ function AtD_ignore_call() {
 	die();
 }
 
-/* 
+/*
  *  Called when a POST occurs, used to save AtD ignored phrases
  */
 function AtD_process_unignore_update() {
@@ -100,10 +100,10 @@ function atd_ignore () {
 
 	/* update the UI */
 	atd_show_phrases( ignored );
-	jQuery( '#AtD_add_ignore' ).val('');             
+	jQuery( '#AtD_add_ignore' ).val('');
 
 	/* show that nifteroo messaroo to the useroo */
-        jQuery( '#AtD_message' ).show(); 
+        jQuery( '#AtD_message' ).show();
 }
 
 function atd_ignore_init() {
@@ -124,7 +124,7 @@ else
    <input type="hidden" name="AtD_ignored_phrases" id="AtD_ignored_phrases" value="<?php echo esc_attr( $ignores ); ?>">
 
           <p style="font-weight: bold"><?php _e( 'Ignored Phrases', 'jetpack' ); ?></font>
-     
+
           <p><?php _e( 'Identify words and phrases to ignore while proofreading your posts and pages:', 'jetpack' ); ?></p>
 
           <p><input type="text" id="AtD_add_ignore" name="AtD_add_ignore"> <input type="button" value="<?php _e( 'Add', 'jetpack' ); ?>" onclick="javascript:atd_ignore()"></p>

diff --git a/plugins/jetpack/modules/after-the-deadline/install_atd_l10n.js b/plugins/jetpack/modules/after-the-deadline/install_atd_l10n.js
index 7d18bb9..3215de6 100644
--- a/plugins/jetpack/modules/after-the-deadline/install_atd_l10n.js
+++ b/plugins/jetpack/modules/after-the-deadline/install_atd_l10n.js
@@ -2,7 +2,7 @@
 function atd_sprintf(format, values) {
 	var result = format;
 	for (var x = 0; x < values.length; x++)
-		result = result.replace(new RegExp('%' + (x + 1) + '\\$', 'g'), values[x]); 
+		result = result.replace(new RegExp('%' + (x + 1) + '\\$', 'g'), values[x]);
 	return result;
 }
 
@@ -15,7 +15,7 @@ function install_atd_l10n() {
 	/* set the AtD l10n instance */
 	AtD.addI18n(AtD_l10n_r0ar);
 }
-        
+
 /* document.ready() does not execute in IE6 unless it's at the bottom of the page. oi! */
 if (navigator.appName == 'Microsoft Internet Explorer')
         setTimeout( install_atd_l10n, 2500 );

diff --git a/plugins/jetpack/modules/after-the-deadline/jquery.atd.js b/plugins/jetpack/modules/after-the-deadline/jquery.atd.js
index e520107..ee2ef6b 100644
--- a/plugins/jetpack/modules/after-the-deadline/jquery.atd.js
+++ b/plugins/jetpack/modules/after-the-deadline/jquery.atd.js
@@ -5,7 +5,7 @@
  * Project     :  http://www.afterthedeadline.com/development.slp
  * Contact     : raffi@automattic.com
  *
- * Derived from: 
+ * Derived from:
  *
  * jquery.spellchecker.js - a simple jQuery Spell Checker
  * Copyright (c) 2008 Richard Willis
@@ -14,7 +14,7 @@
  * Contact      : willis.rh@gmail.com
  */
 
-var AtD = 
+var AtD =
 {
 	rpc : '', /* see the proxy.php that came with the AtD/TinyMCE plugin */
 	rpc_css : 'http://www.polishmywriting.com/atd-jquery/server/proxycss.php?data=', /* you may use this, but be nice! */
@@ -46,8 +46,8 @@ AtD.showTypes = function(string) {
 
 AtD.checkCrossAJAX = function(container_id, callback_f) {
 	/* checks if a global var for click stats exists and increments it if it does... */
-	if (typeof AtD_proofread_click_count != "undefined")  
-		AtD_proofread_click_count++; 
+	if (typeof AtD_proofread_click_count != "undefined")
+		AtD_proofread_click_count++;
 
 	AtD.callback_f = callback_f; /* remember the callback for later */
 	AtD.remove(container_id);
@@ -74,7 +74,7 @@ AtD.checkCrossAJAX = function(container_id, callback_f) {
 			xml = new ActiveXObject("Microsoft.XMLDOM");
 			xml.async = false;
 			xml.loadXML(response);
-		} 
+		}
 		else {
 			xml = (new DOMParser()).parseFromString(response, 'text/xml');
 		}
@@ -85,7 +85,7 @@ AtD.checkCrossAJAX = function(container_id, callback_f) {
 				AtD.callback_f.error(AtD.core.getErrorMessage(xml));
 
 			return;
-		} 
+		}
 
 		/* highlight the errors */
 
@@ -107,12 +107,12 @@ AtD.checkCrossAJAX = function(container_id, callback_f) {
 AtD.check = function(container_id, callback_f) {
 	/* checks if a global var for click stats exists and increments it if it does... */
 	if (typeof AtD_proofread_click_count != "undefined")
-		AtD_proofread_click_count++; 
+		AtD_proofread_click_count++;
 
 	AtD.callback_f = callback_f; /* remember the callback for later */
 
-	AtD.remove(container_id);	
-		
+	AtD.remove(container_id);
+
 	var container = jQuery('#' + container_id);
 
 	var html = container.html();
@@ -124,14 +124,14 @@ AtD.check = function(container_id, callback_f) {
 		type : "POST",
 		url : AtD.rpc + '/checkDocument',
 		data : 'key=' + AtD.api_key + '&data=' + text,
-		format : 'raw', 
+		format : 'raw',
 		dataType : (jQuery.browser.msie) ? "text" : "xml",
 
 		error : function(XHR, status, error) {
 			if (AtD.callback_f != undefined && AtD.callback_f.error != undefined)
  				AtD.callback_f.error(status + ": " + error);
 		},
-	
+
 		success : function(data) {
 			/* apparently IE likes to return XML as plain text-- work around from:
 			   http://docs.jquery.com/Specifying_the_Data_Type_for_AJAX_Requests */
@@ -141,7 +141,7 @@ AtD.check = function(container_id, callback_f) {
 				xml = new ActiveXObject("Microsoft.XMLDOM");
 				xml.async = false;
 				xml.loadXML(data);
-			} 
+			}
 			else {
 				xml = data;
 			}
@@ -169,7 +169,7 @@ AtD.check = function(container_id, callback_f) {
 		}
 	});
 };
-	
+
 AtD.remove = function(container_id) {
 	AtD._removeWords(container_id, null);
 };
@@ -182,7 +182,7 @@ AtD.clickListener = function(event) {
 AtD.processXML = function(container_id, responseXML) {
 
 	var results = AtD.core.processXML(responseXML);
-   
+
 	if (results.count > 0)
 		results.count = AtD.core.markMyWords(jQuery('#' + container_id).contents(), results.errors);
 
@@ -214,7 +214,7 @@ AtD.editSelection = function() {
 };
 
 AtD.ignoreSuggestion = function() {
-	AtD.core.removeParent(AtD.errorElement); 
+	AtD.core.removeParent(AtD.errorElement);
 
 	AtD.counter --;
 	if (AtD.counter == 0 && AtD.callback_f != undefined && AtD.callback_f.success != undefined)
@@ -253,7 +253,7 @@ AtD.suggest = function(element) {
 		suggest.hide();
 	}
 
-	/* find the correct suggestions object */          
+	/* find the correct suggestions object */
 
 	errorDescription = AtD.core.findSuggestion(element);
 
@@ -297,7 +297,7 @@ AtD.suggest = function(element) {
 			suggest.append('<a href="javascript:AtD.ignoreAll(\'' + AtD.container + '\')">' + AtD.getLang('menu_option_ignore_always', 'Ignore always') + '</a>');
 		else
 			suggest.append('<a href="javascript:AtD.ignoreAll(\'' + AtD.container + '\')">' + AtD.getLang('menu_option_ignore_all', 'Ignore all') + '</a>');
- 
+
 		suggest.append('<a href="javascript:AtD.editSelection(\'' + AtD.container + '\')" class="spell_sep_bottom spell_sep_top">' + AtD.getLang('menu_option_edit_selection', 'Edit Selection...') + '</a>');
 	}
 	else {
@@ -313,8 +313,8 @@ AtD.suggest = function(element) {
 	var width = jQuery(element).width();
 
         /* a sanity check for Internet Explorer--my favorite browser in every possible way */
-        if (width > 100) 
-                width = 50; 
+        if (width > 100)
+                width = 50;
 
 	jQuery(suggest).css({ left: (pos.left + width) + 'px', top: pos.top + 'px' });
 
@@ -327,13 +327,13 @@ AtD.suggest = function(element) {
 	setTimeout(function() {
 		jQuery("body").bind("click", function() {
 			if (!AtD.suggestShow)
-				jQuery('#suggestmenu').fadeOut(200);      
+				jQuery('#suggestmenu').fadeOut(200);
 		});
 	}, 1);
 
 	setTimeout(function() {
 		AtD.suggestShow = false;
-	}, 2); 
+	}, 2);
 };
 
 AtD._removeWords = function(container_id, w) {
@@ -341,7 +341,7 @@ AtD._removeWords = function(container_id, w) {
 };
 
 /*
- * Set prototypes used by AtD Core UI 
+ * Set prototypes used by AtD Core UI
  */
 AtD.initCoreModule = function() {
 	var core = new AtDCore();

diff --git a/plugins/jetpack/modules/after-the-deadline/proxy.php b/plugins/jetpack/modules/after-the-deadline/proxy.php
index 04bbd28..3d5ef3b 100644
--- a/plugins/jetpack/modules/after-the-deadline/proxy.php
+++ b/plugins/jetpack/modules/after-the-deadline/proxy.php
@@ -21,21 +21,21 @@ function AtD_http_post( $request, $host, $path, $port = 80 ) {
 	$AtD_url = "http://{$host}{$path}";
 	$response = wp_remote_post( $AtD_url, $http_args );
 	$code = (int) wp_remote_retrieve_response_code( $response );
-	
+
 	if ( is_wp_error( $response ) ) {
 		do_action( 'atd_http_post_error', 'http-error' );
 		return array();
 	} elseif ( 200 != $code ) {
 		do_action( 'atd_http_post_error', $code );
 	}
-	
+
 	return array(
-		wp_remote_retrieve_headers( $response ), 
+		wp_remote_retrieve_headers( $response ),
 		wp_remote_retrieve_body( $response ),
 	);
 }
 
-/* 
+/*
  *  This function is called as an action handler to admin-ajax.php
  */
 function AtD_redirect_call() {

diff --git a/plugins/jetpack/modules/after-the-deadline/tinymce/editor_plugin.js b/plugins/jetpack/modules/after-the-deadline/tinymce/editor_plugin.js
index fc9f01f..f9251cd 100644
--- a/plugins/jetpack/modules/after-the-deadline/tinymce/editor_plugin.js
+++ b/plugins/jetpack/modules/after-the-deadline/tinymce/editor_plugin.js
@@ -1,5 +1,5 @@
 /*
- * TinyMCE Writing Improvement Tool Plugin 
+ * TinyMCE Writing Improvement Tool Plugin
  * Author: Raphael Mudge (raffi@automattic.com)
  *
  * http://www.afterthedeadline.com
@@ -15,15 +15,15 @@
  *    Moxiecode Spell Checker plugin released under the LGPL with TinyMCE
  */
 
-(function() 
+(function()
 {
-   var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM; 
+   var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM;
 
-   tinymce.create('tinymce.plugins.AfterTheDeadlinePlugin', 
+   tinymce.create('tinymce.plugins.AfterTheDeadlinePlugin',
    {
-      getInfo : function() 
+      getInfo : function()
       {
-         return 
+         return
          ({
 	    longname :  'After The Deadline',
             author :    'Raphael Mudge',
@@ -40,12 +40,12 @@
 
          core.map = each;
 
-         core.getAttrib = function(node, key) 
-         { 
-            return editor.dom.getAttrib(node, key); 
+         core.getAttrib = function(node, key)
+         {
+            return editor.dom.getAttrib(node, key);
          };
 
-	 core.findSpans = function(parent) 
+	 core.findSpans = function(parent)
          {
             if (parent == undefined)
                return editor.dom.select('span');
@@ -53,39 +53,39 @@
                return editor.dom.select('span', parent);
          };
 
-         core.hasClass = function(node, className) 
-         { 
-            return editor.dom.hasClass(node, className); 
+         core.hasClass = function(node, className)
+         {
+            return editor.dom.hasClass(node, className);
          };
-         
-         core.contents = function(node) 
-         { 
-            return node.childNodes;  
+
+         core.contents = function(node)
+         {
+            return node.childNodes;
          };
 
-         core.replaceWith = function(old_node, new_node) 
-         { 
-            return editor.dom.replace(new_node, old_node); 
+         core.replaceWith = function(old_node, new_node)
+         {
+            return editor.dom.replace(new_node, old_node);
          };
 
-         core.create = function(node_html) 
-         { 
+         core.create = function(node_html)
+         {
             return editor.dom.create('span', { 'class': 'mceItemHidden' }, node_html);
          };
 
-         core.removeParent = function(node) 
+         core.removeParent = function(node)
          {
 	    editor.dom.remove(node, 1);
             return node;
          };
 
-         core.remove = function(node) 
-         { 
-            editor.dom.remove(node); 
+         core.remove = function(node)
+         {
+            editor.dom.remove(node);
          };
 
-         core.getLang = function(key, defaultk) 
-         { 
+         core.getLang = function(key, defaultk)
+         {
              return editor.getLang("AtD." + key, defaultk);
          };
 
@@ -93,9 +93,9 @@
          core.showTypes(editor.getParam("atd_show_types", ""));
          return core;
       },
- 
+
       /* called when the plugin is initialized */
-      init : function(ed, url) 
+      init : function(ed, url)
       {
          if ( typeof(AtDCore) == 'undefined' )
          	return;
@@ -118,7 +118,7 @@
          }
 
          /* add a command to request a document check and process the results. */
-         editor.addCommand('mceWritingImprovementTool', function(callback) 
+         editor.addCommand('mceWritingImprovementTool', function(callback)
          {
             /* checks if a global var for click stats exists and increments it if it does... */
             if (typeof AtD_proofread_click_count != "undefined")
@@ -162,7 +162,7 @@
                if (results.count > 0)
                {
                   ecount = plugin.markMyWords(results.errors);
-                  ed.suggestions = results.suggestions; 
+                  ed.suggestions = results.suggestions;
                }
 
                if (ecount == 0 && (!callback || callback == undefined))
@@ -171,9 +171,9 @@
                   callback(ecount);
             });
          });
-          
+
          /* load cascading style sheet for this plugin */
-     	 editor.onInit.add(function() 
+     	 editor.onInit.add(function()
          {
             /* loading the content.css file, why? I have no clue */
             if (editor.settings.content_css !== false)
@@ -189,13 +189,13 @@
 	 editor.onContextMenu.add(plugin._showMenu, plugin);
 
          /* strip out the markup before the contents is serialized (and do it on a copy of the markup so we don't affect the user experience) */
-         editor.onPreProcess.add(function(sender, object) 
+         editor.onPreProcess.add(function(sender, object)
          {
             var dom = sender.dom;
 
-            each(dom.select('span', object.node).reverse(), function(n) 
+            each(dom.select('span', object.node).reverse(), function(n)
             {
-               if (n && (dom.hasClass(n, 'hiddenGrammarError') || dom.hasClass(n, 'hiddenSpellError') || dom.hasClass(n, 'hiddenSuggestion') || dom.hasClass(n, 'mceItemHidden') || (dom.getAttrib(n, 'class') == "" && dom.getAttrib(n, 'style') == "" && dom.getAttrib(n, 'id') == "" && !dom.hasClass(n, 'Apple-style-span') && dom.getAttrib(n, 'mce_name') == ""))) 
+               if (n && (dom.hasClass(n, 'hiddenGrammarError') || dom.hasClass(n, 'hiddenSpellError') || dom.hasClass(n, 'hiddenSuggestion') || dom.hasClass(n, 'mceItemHidden') || (dom.getAttrib(n, 'class') == "" && dom.getAttrib(n, 'style') == "" && dom.getAttrib(n, 'id') == "" && !dom.hasClass(n, 'Apple-style-span') && dom.getAttrib(n, 'mce_name') == "")))
                {
                   dom.remove(n, 1);
                }
@@ -203,7 +203,7 @@
          });
 
          /* cleanup the HTML before executing certain commands */
-	 editor.onBeforeExecCommand.add(function(editor, command) 
+	 editor.onBeforeExecCommand.add(function(editor, command)
          {
             if (command == 'mceCodeEditor')
             {
@@ -214,15 +214,15 @@
                plugin._done();
             }
          });
-         
-		ed.addButton('AtD', { 
+
+		ed.addButton('AtD', {
 			title: ed.getLang('AtD.button_proofread_tooltip', 'Proofread Writing'),
-			image: ed.getParam('atd_button_url', url + '/atdbuttontr.gif'), 
+			image: ed.getParam('atd_button_url', url + '/atdbuttontr.gif'),
 			cmd: 'mceWritingImprovementTool'
 		});
       },
 
-      _removeWords : function(w) 
+      _removeWords : function(w)
       {
          var ed = this.editor, dom = ed.dom, se = ed.selection, b = se.getBookmark();
 
@@ -247,17 +247,17 @@
          return ecount;
       },
 
-      _showMenu : function(ed, e) 
+      _showMenu : function(ed, e)
       {
          var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin());
          var plugin = this;
 
-         if (!m) 
+         if (!m)
          {
             p1 = DOM.getPos(ed.getContentAreaContainer());
             //p2 = DOM.getPos(ed.getContainer());
 
-            m = ed.controlManager.createDropMenu('spellcheckermenu', 
+            m = ed.controlManager.createDropMenu('spellcheckermenu',
             {
                offset_x : p1.x,
                offset_y : p1.y,
@@ -292,8 +292,8 @@
                   (function(sugg)
                    {
                       m.add({
-                         title   : sugg, 
-                         onclick : function() 
+                         title   : sugg,
+                         onclick : function()
                          {
                             ed.core.applySuggestion(e.target, sugg);
                             t._checkDone();
@@ -304,14 +304,14 @@
 
                m.addSeparator();
             }
-             
+
             if (errorDescription != undefined && errorDescription["moreinfo"] != null)
             {
                (function(url)
                 {
                    m.add({
                      title : plugin.editor.getLang('AtD.menu_option_explain', 'Explain...'),
-                     onclick : function() 
+                     onclick : function()
                      {
                         ed.windowManager.open({
                            url : url,
@@ -328,7 +328,7 @@
 
             m.add({
                title : plugin.editor.getLang('AtD.menu_option_ignore_once', 'Ignore suggestion'),
-               onclick : function() 
+               onclick : function()
                {
                   dom.remove(e.target, 1);
                   t._checkDone();
@@ -339,7 +339,7 @@
             {
                 m.add({
                   title : plugin.editor.getLang('AtD.menu_option_ignore_always', 'Ignore always'),
-                  onclick : function() 
+                  onclick : function()
                   {
                       var url = t.editor.getParam('atd_ignore_rpc_url', '{backend}');
 
@@ -347,10 +347,10 @@
                       {
                          /* Default scheme is to save ignore preferences in a cookie */
 
-                         var ignore = tinymce.util.Cookie.getHash('atd_ignore'); 
+                         var ignore = tinymce.util.Cookie.getHash('atd_ignore');
                          if (ignore == undefined) { ignore = {}; }
                          ignore[e.target.innerHTML] = 1;
-                  
+
                          tinymce.util.Cookie.setHash('atd_ignore', ignore, new Date( (new Date().getTime()) + 157680000000) );
                       }
                       else
@@ -370,7 +370,7 @@
                              },
                              error        : function( type, req, o )
                              {
-                                alert( "Ignore preference save failed\n" + type + "\n" + req.status + "\nAt: " + o.url ); 
+                                alert( "Ignore preference save failed\n" + type + "\n" + req.status + "\nAt: " + o.url );
                              }
                          });
 
@@ -387,7 +387,7 @@
             {
                 m.add({
                   title : plugin.editor.getLang('menu_option_ignore_all', 'Ignore all'),
-                  onclick : function() 
+                  onclick : function()
                   {
                      t._removeWords(e.target.innerHTML);
                      t._checkDone();
@@ -401,7 +401,7 @@
             m.showMenu(p1.x, p1.y + e.target.offsetHeight - vp.y);
 
             return tinymce.dom.Event.cancel(e);
-         } 
+         }
          else
          {
             m.hideMenu();
@@ -409,11 +409,11 @@
       },
 
       /* loop through editor DOM, call _done if no mce tags exist. */
-      _checkDone : function() 
+      _checkDone : function()
       {
          var t = this, ed = t.editor, dom = ed.dom, o;
 
-         each(dom.select('span'), function(n) 
+         each(dom.select('span'), function(n)
          {
             if (n && dom.hasClass(n, 'mceItemHidden'))
             {
@@ -429,7 +429,7 @@
       },
 
       /* remove all tags, hide the menu, and fire a dom change event */
-      _done : function() 
+      _done : function()
       {
          var plugin    = this;
          plugin._removeWords();
@@ -448,24 +448,24 @@
          var url = this.editor.getParam("atd_rpc_url", "{backend}");
          var plugin = this;
 
-         if (url == '{backend}' || id == '12345678') 
+         if (url == '{backend}' || id == '12345678')
          {
             this.editor.setProgressState(0);
             alert('Please specify: atd_rpc_url and atd_rpc_id');
             return;
          }
-   
+
          tinymce.util.XHR.send({
             url          : url + "/" + file,
             content_type : 'text/xml',
             type         : "POST",
-            data         : "data=" + encodeURI(data).replace(/&/g, '%26') + "&key=" + id, 
+            data         : "data=" + encodeURI(data).replace(/&/g, '%26') + "&key=" + id,
             async        : true,
             success      : success,
             error        : function( type, req, o )
             {
 	       plugin.editor.setProgressState(0);
-               alert( type + "\n" + req.status + "\nAt: " + o.url ); 
+               alert( type + "\n" + req.status + "\nAt: " + o.url );
             }
          });
       }

diff --git a/plugins/jetpack/modules/carousel.php b/plugins/jetpack/modules/carousel.php
index 2637f43..e8db24b 100644
--- a/plugins/jetpack/modules/carousel.php
+++ b/plugins/jetpack/modules/carousel.php
@@ -5,6 +5,7 @@
  * Module Description: Transform your standard image galleries into an immersive full-screen experience.
  * Sort Order: 4
  * First Introduced: 1.5
+ * Requires Connection: No
  */
 
 include dirname( __FILE__ ) . '/carousel/jetpack-carousel.php';

diff --git a/plugins/jetpack/modules/carousel/jetpack-carousel.css b/plugins/jetpack/modules/carousel/jetpack-carousel.css
index 49bdad8..0585449 100644
--- a/plugins/jetpack/modules/carousel/jetpack-carousel.css
+++ b/plugins/jetpack/modules/carousel/jetpack-carousel.css
@@ -48,7 +48,7 @@ only screen and (min-device-pixel-ratio: 1.5) {
 	background: #68c9e8; /* Safari */
 	color: #fff;
 	}
-	
+
 .jp-carousel-info ::-moz-selection {
 	background: #68c9e8; /* Firefox */
 	color: #fff;
@@ -133,7 +133,7 @@ div.jp-carousel-buttons a {
 	padding: 5px 2px 5px 0;
 	text-decoration: none !important;
 	text-shadow: none !important;
-	vertical-align: baseline !important;
+	vertical-align: middle;
 	-webkit-font-smoothing: subpixel-antialiased;
 }
 
@@ -481,7 +481,7 @@ div#carousel-reblog-box {
 	display: none;
 }
 
-.jp-carousel-photo-info h1:before, 
+.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 {
@@ -693,7 +693,7 @@ textarea#jp-carousel-comment-form-comment-field {
 	border-radius: 3px;
 	overflow: hidden;
 	-webkit-box-sizing: border-box;
-	-moz-box-sizing: border-box;    
+	-moz-box-sizing: border-box;
 	box-sizing: border-box;
 }
 
@@ -791,7 +791,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 }
 
 #jp-carousel-comment-post-results {
-	display: none;	
+	display: none;
 	overflow:auto;
 	width:100%;
 }
@@ -1050,14 +1050,14 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 		margin: 0 10px !important;
 	}
 
-	.jp-carousel-next-button, .jp-carousel-previous-button { 
-		display: none !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;
@@ -1065,31 +1065,31 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 		-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;	
+		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;
@@ -1097,8 +1097,8 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 	.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 43f1d1f..f101dbf 100644
--- a/plugins/jetpack/modules/carousel/jetpack-carousel.js
+++ b/plugins/jetpack/modules/carousel/jetpack-carousel.js
@@ -54,9 +54,69 @@ jQuery(document).ready(function($) {
 		}, 200);
 	};
 
-	var prepareGallery = function(){
-		if (!overlay) {
+	// For each image in the carousel, emit likes widget markup
+	var getCarouselLikeWidgets = function( dataCarouselExtra ) {
+
+		// Only do this if likes is enabled
+		if ( "undefined" === typeof jetpackLikesWidgetQueue )
+			return "";
+
+		var blogId = dataCarouselExtra.likes_blog_id;
+		var attachmentId = 0;
+		var protocol = 'http';
+		var originDomain = 'http://wordpress.com';
+
+		if ( dataCarouselExtra.permalink.length ) {
+			var parts = dataCarouselExtra.permalink.split( ':' );
+			var protocol = parts[0];
+			if ( ( protocol != 'http' ) && ( protocol != 'https' ) ) {
+				protocol = 'http';
+			}
+
+			parts = dataCarouselExtra.permalink.split( '/' );
+			if ( parts.length >= 2 ) {
+				originDomain = protocol + "://" + parts[2];
+			}
+		}
+
+		var likesWidgetContainer = $("<div class='likes-widget-container'></div>");
+
+		$( 'div.gallery, div.tiled-gallery' ).find( 'img' ).each( function() {
+
+			attachmentId = $( this ).attr( "data-attachment-id" );
+			var dataSource = protocol + "://widgets.wp.com/likes/#blog_id=" + blogId + "&amp;post_id=" + attachmentId + "&amp;slim=1&amp;origin=" + originDomain;
+
+			if ( 'en' !== jetpackCarouselStrings.lang ) {
+				dataSource += "&amp;lang=" + jetpackCarouselStrings.lang;
+			}
+
+			var likesWidgetWrapper = $( "<div></div>" );
+			likesWidgetWrapper.addClass( "jetpack-likes-widget-wrapper" )
+				.addClass( "jetpack-likes-widget-unloaded" )
+				.addClass( "slim-likes-widget" )
+				.attr( "id", "like-post-wrapper-" + blogId + "-" + attachmentId )
+				.attr( "data-src", dataSource )
+				.attr( "data-name", "like-post-frame-" + blogId + "-" + attachmentId )
+				.attr( "data-attachment-id", attachmentId )
+				.css( "display", "none" )
+				.css( "vertical-align", "middle" );
+
+			var likesWidget = $( "<iframe class='post-likes-widget jetpack-likes-widget jetpack-resizeable'></iframe>" );
+			likesWidget.attr( "name", "like-post-frame-" + blogId + "-" + attachmentId )
+				.attr( "src", dataSource );
+			likesWidget.css( "display", "inline-block" );
+			likesWidgetWrapper.append( likesWidget );
+
+			likesWidgetWrapper.append( "<div class='post-likes-widget-placeholder'></div>" );
+
+			likesWidgetContainer.append( likesWidgetWrapper );
+		});
+
+		return likesWidgetContainer.html();
+	};
 
+	var prepareGallery = function( dataCarouselExtra ){
+		if (!overlay) {
 			overlay = $('<div></div>')
 				.addClass('jp-carousel-overlay')
 				.css({
@@ -68,6 +128,9 @@ jQuery(document).ready(function($) {
 				});
 
 			buttons  = '<a class="jp-carousel-commentlink" href="#">' + jetpackCarouselStrings.comment + '</a>';
+			if ( 1 == jetpackCarouselStrings.is_logged_in ) {
+			}
+			buttons += getCarouselLikeWidgets( dataCarouselExtra );
 			buttons  = $('<div class="jp-carousel-buttons">' + buttons + '</div>');
 
 			caption    = $('<h2></h2>');
@@ -81,6 +144,11 @@ jQuery(document).ready(function($) {
 					'width'      :  '250px'
 				});
 
+			imageMeta.append( buttons );
+			imageMeta.append( "<ul class='jp-carousel-image-exif' style='display:none;'></ul>" );
+			imageMeta.append( "<a class='jp-carousel-image-download' style='display:none;'></a>" );
+			imageMeta.append( "<div class='jp-carousel-image-map' style='display:none;'></div>" );
+
 			titleAndDescription = $('<div></div>')
 				.addClass('jp-carousel-titleanddesc')
 				.css({
@@ -99,15 +167,20 @@ jQuery(document).ready(function($) {
 				commentFormMarkup += '<iframe src="'+iframeSrc+'" width="100%" height="'+iframeHeight+'" style="width:100%;height:'+iframeHeight+'px;" allowtransparency="true" frameBorder="0" scrolling="no" name="jp-carousel-comment-iframe" id="jp-carousel-comment-iframe"></iframe>';
 			} else if ( jetpackCarouselStrings.local_comments_commenting_as && jetpackCarouselStrings.local_comments_commenting_as.length ) {
 				// Jetpack comments not enabled, fallback to local comments
-				commentFormMarkup += '<form id="jp-carousel-comment-form">';
-				commentFormMarkup += '<textarea name="comment" class="jp-carousel-comment-form-field jp-carousel-comment-form-textarea" id="jp-carousel-comment-form-comment-field" placeholder="Write a comment&hellip;"></textarea>';
-				commentFormMarkup += '<div id="jp-carousel-comment-form-submit-and-info-wrapper">';
-				commentFormMarkup += '<div id="jp-carousel-comment-form-commenting-as">' + jetpackCarouselStrings.local_comments_commenting_as + '</div>';
-				commentFormMarkup += '<input type="submit" name="submit" class="jp-carousel-comment-form-button" id="jp-carousel-comment-form-button-submit" value="'+jetpackCarouselStrings.post_comment+'" />';
-				commentFormMarkup += '<span id="jp-carousel-comment-form-spinner">&nbsp;</span>';
-				commentFormMarkup += '<div id="jp-carousel-comment-post-results"></div>';
-				commentFormMarkup += '</div>';
-				commentFormMarkup += '</form>';
+
+				if ( 1 != jetpackCarouselStrings.is_logged_in && 1 == jetpackCarouselStrings.comment_registration ) {
+					commentFormMarkup += '<div id="jp-carousel-comment-form-commenting-as">' + jetpackCarouselStrings.local_comments_commenting_as + '</div>';
+				} else {
+					commentFormMarkup += '<form id="jp-carousel-comment-form">';
+					commentFormMarkup += '<textarea name="comment" class="jp-carousel-comment-form-field jp-carousel-comment-form-textarea" id="jp-carousel-comment-form-comment-field" placeholder="Write a comment&hellip;"></textarea>';
+					commentFormMarkup += '<div id="jp-carousel-comment-form-submit-and-info-wrapper">';
+					commentFormMarkup += '<div id="jp-carousel-comment-form-commenting-as">' + jetpackCarouselStrings.local_comments_commenting_as + '</div>';
+					commentFormMarkup += '<input type="submit" name="submit" class="jp-carousel-comment-form-button" id="jp-carousel-comment-form-button-submit" value="'+jetpackCarouselStrings.post_comment+'" />';
+					commentFormMarkup += '<span id="jp-carousel-comment-form-spinner">&nbsp;</span>';
+					commentFormMarkup += '<div id="jp-carousel-comment-post-results"></div>';
+					commentFormMarkup += '</div>';
+					commentFormMarkup += '</form>';
+				}
 			}
 			commentFormMarkup += '</div>';
 
@@ -134,10 +207,6 @@ jQuery(document).ready(function($) {
 				});
 
 			leftWidth = ( $(window).width() - ( screenPadding * 2 ) ) - (imageMeta.width() + 40);
-			if ( $.browser.mozilla )
-				leftWidth -= 55;
-			else if ( $.browser.msie )
-				leftWidth -= 20;
 			leftWidth += 'px';
 
 			if (isMobile)
@@ -259,6 +328,10 @@ jQuery(document).ready(function($) {
 						container.animate({scrollTop: parseInt(info.position()['top'], 10)}, 'fast');
 						$('#jp-carousel-comment-form-submit-and-info-wrapper').slideDown('fast');
 						$('#jp-carousel-comment-form-comment-field').focus();
+					} else if ( target.hasClass('jp-carousel-comment-login') ) {
+						var url = jetpackCarouselStrings.login_url + '%23jp-carousel-' + attachment_id;
+
+						document.location.href = url;
 					} else if ( target.parents('#jp-carousel-comment-form-container').length ) {
 						var textarea = $('#jp-carousel-comment-form-comment-field')
 							.blur(function(){
@@ -320,12 +393,14 @@ jQuery(document).ready(function($) {
 								ajaxData['author'] = authorField.val();
 								ajaxData['url']    = urlField.val();
 
-								if ( ! ajaxData['email'].length || ! ajaxData['email'].match('@') ) {
-									gallery.jp_carousel('postCommentError', {'field': 'jp-carousel-comment-form-email-field', 'error': jetpackCarouselStrings.no_comment_email});
-									return;
-								} else if ( ! ajaxData['author'].length ) {
-									gallery.jp_carousel('postCommentError', {'field': 'jp-carousel-comment-form-author-field', 'error': jetpackCarouselStrings.no_comment_author});
-									return;
+								if ( 1 == jetpackCarouselStrings.require_name_email ) {
+									if ( ! ajaxData['email'].length || ! ajaxData['email'].match('@') ) {
+										gallery.jp_carousel('postCommentError', {'field': 'jp-carousel-comment-form-email-field', 'error': jetpackCarouselStrings.no_comment_email});
+										return;
+									} else if ( ! ajaxData['author'].length ) {
+										gallery.jp_carousel('postCommentError', {'field': 'jp-carousel-comment-form-author-field', 'error': jetpackCarouselStrings.no_comment_author});
+										return;
+									}
 								}
 							}
 
@@ -369,8 +444,14 @@ jQuery(document).ready(function($) {
 
 					$(window).unbind('keydown', keyListener);
 					$(window).unbind('resize', resizeListener);
-					document.location.hash = '';
 					$(window).scrollTop(scroll);
+				})
+				.bind('jp_carousel.afterClose', function(){
+					if ( history.pushState ) {
+						history.pushState("", document.title, window.location.pathname + window.location.search);
+					} else {
+						document.location.hash = '';
+					}
 					gallery.opened = false;
 				});
 
@@ -382,6 +463,10 @@ jQuery(document).ready(function($) {
 				     preventDefaultEvents: true
 				});
 
+			$( '.jetpack-likes-widget-unloaded' ).each( function() {
+				jetpackLikesWidgetQueue.push( this.id );
+				});
+
 			nextButton.add(previousButton).click(function(e){
 				e.preventDefault();
 				e.stopPropagation();
@@ -397,8 +482,9 @@ 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' ) )
+			if ( ! gallery.length || undefined == gallery.data( 'carousel-extra' ) ) {
 				return false;
+			}
 			return true;
 		},
 
@@ -418,8 +504,8 @@ jQuery(document).ready(function($) {
 			if ( !data )
 				return; // don't run if the default gallery functions weren't used
 
-			prepareGallery();
-			
+			prepareGallery( data );
+
 			if ( gallery.jp_carousel( 'testIfOpened' ) )
 				return; // don't open if already opened
 
@@ -429,8 +515,13 @@ jQuery(document).ready(function($) {
 			$('body').css('overflow', 'hidden');
 			// prevent html from overflowing on some of the new themes.
 			originalHOverflow = $('html').css('overflow');
-			$('html').css('overflow', 'hidden');			
-			
+			$('html').css('overflow', 'hidden');
+
+			// Re-apply inline-block style here and give an initial value for the width
+			// This value will get replaced with a more appropriate value once the slide is loaded
+			// This avoids the likes widget appearing initially full width below the comment button and then shuffling up
+			jQuery( '.slim-likes-widget' ).find( 'iframe' ).css( 'display', 'inline-block' ).css( 'width', '60px' );
+
 			container.data('carousel-extra', data);
 
 			return this.each(function() {
@@ -510,6 +601,10 @@ jQuery(document).ready(function($) {
 		},
 
 		resetButtons : function(current) {
+			if ( current.data('liked') )
+				$('.jp-carousel-buttons a.jp-carousel-like').addClass('liked').text(jetpackCarouselStrings.unlike);
+			else
+				$('.jp-carousel-buttons a.jp-carousel-like').removeClass('liked').text(jetpackCarouselStrings.like);
 		},
 
 		loopSlides : function(reverse){
@@ -604,14 +699,13 @@ jQuery(document).ready(function($) {
 			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);
-			gallery.jp_carousel('getMap', current.data('image-meta'));
-			gallery.jp_carousel('testCommentsOpened', current.data('comments-opened'));
-			gallery.jp_carousel('getComments', {'attachment_id': current.data('attachment-id'), 'offset': 0, 'clear': true});
+			gallery.jp_carousel( 'getTitleDesc', { title: current.data( 'title' ), desc: current.data( 'desc' ) } );
+			gallery.jp_carousel( 'updateLikesWidgetVisibility', current.data( 'attachment-id' ) )
+			gallery.jp_carousel( 'updateExif', current.data( 'image-meta' ) );
+			gallery.jp_carousel( 'updateFullSizeLink', current );
+			gallery.jp_carousel( 'updateMap', current.data( 'image-meta' ) );
+			gallery.jp_carousel( 'testCommentsOpened', current.data( 'comments-opened' ) );
+			gallery.jp_carousel( 'getComments', { 'attachment_id': current.data( 'attachment-id' ), 'offset': 0, 'clear': true } );
 
 			$('#jp-carousel-comment-post-results').slideUp();
 
@@ -832,11 +926,11 @@ jQuery(document).ready(function($) {
 			if ( 'undefined' == typeof args.medium_file || 'undefined' == typeof args.large_file )
 				return args.orig_file;
 
-			var medium_size       = args.medium_file.replace(/^https?:\/\/.+-([\d]+x[\d]+)\..+$/, '$1'),
+			var medium_size       = args.medium_file.replace(/-([\d]+x[\d]+)\..+$/, '$1'),
 				medium_size_parts = (medium_size != args.medium_file) ? medium_size.split('x') : [args.orig_width, 0],
 				medium_width      = parseInt( medium_size_parts[0], 10 ),
 				medium_height     = parseInt( medium_size_parts[1], 10 ),
-				large_size        = args.large_file.replace(/^https?:\/\/.+-([\d]+x[\d]+)\..+$/, '$1'),
+				large_size        = args.large_file.replace(/-([\d]+x[\d]+)\..+$/, '$1'),
 				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 );
@@ -955,11 +1049,25 @@ jQuery(document).ready(function($) {
 			$( 'div#jp-carousel-comments-loading' ).css('margin-top', '20px');
 		},
 
-		getMeta: function( meta ) {
+		updateLikesWidgetVisibility: function( attachmentId ) {
+			// Hide all likes widgets except for the one for the attachmentId passed in
+
+			$( '.jp-carousel-buttons' ).find( '.jetpack-likes-widget-wrapper' ).each( function() {
+				var widgetWrapper = $( this );
+				if ( widgetWrapper.attr('data-attachment-id') == attachmentId ) {
+					widgetWrapper.css( 'display', 'inline-block' );
+				} else {
+					widgetWrapper.css( 'display', 'none' );
+				}
+				});
+		},
+
+		// updateExif updates the contents of the exif UL (.jp-carousel-image-exif)
+		updateExif: function( meta ) {
 			if ( !meta || 1 != jetpackCarouselStrings.display_exif )
 				return false;
 
-			var $ul = $( '<ul></ul>' );
+			var $ul = $( "<ul class='jp-carousel-image-exif'></ul>" );
 			$.each( meta, function( key, val ) {
 				if ( 0 === parseFloat(val) || !val.length || -1 === $.inArray( key, [ 'camera', 'aperture', 'shutter_speed', 'focal_length' ] ) )
 					return;
@@ -982,14 +1090,12 @@ jQuery(document).ready(function($) {
 				$ul.append( '<li><h5>' + jetpackCarouselStrings[key] + '</h5>' + val + '</li>' );
 			});
 
-			$( 'div.jp-carousel-image-meta', 'div.jp-carousel-wrap' )
-				.append( $( buttons ) );
-
-			$( 'div.jp-carousel-image-meta', 'div.jp-carousel-wrap' )
-				.append( $ul );
+			// Update (replace) the content of the ul
+			$( 'div.jp-carousel-image-meta ul.jp-carousel-image-exif' ).replaceWith( $ul );
 		},
 
-		getFullSizeLink: function(current) {
+		// updateFullSizeLink updates the contents of the jp-carousel-image-download link
+		updateFullSizeLink: function(current) {
 			if(!current || !current.data)
 				return false;
 			var original  = current.data('orig-file').replace(/\?.+$/, ''),
@@ -999,11 +1105,11 @@ jQuery(document).ready(function($) {
 					.attr( 'href', original )
 					.attr( 'target', '_blank' );
 
-			$( 'div.jp-carousel-image-meta', 'div.jp-carousel-wrap' )
-				.append( permalink );
+			// Update (replace) the content of the anchor
+			$( 'div.jp-carousel-image-meta a.jp-carousel-image-download' ).replaceWith( permalink );
 		},
 
-		getMap: function( meta ) {
+		updateMap: function( meta ) {
 			if ( !meta.latitude || !meta.longitude || 1 != jetpackCarouselStrings.display_geo )
 				return;
 
@@ -1186,11 +1292,18 @@ jQuery(document).ready(function($) {
 	// 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(){
+		last_known_location_hash = '';
+
 		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;
 
+			if ( document.location.hash == last_known_location_hash )
+				return;
+
+			last_known_location_hash = document.location.hash;
+
 			var gallery = $('div.gallery, div.tiled-gallery'), index = -1, n = document.location.hash.match(/jp-carousel-(\d+)/);
 
 			if ( ! $(this).jp_carousel( 'testForData', gallery ) )

diff --git a/plugins/jetpack/modules/carousel/jetpack-carousel.php b/plugins/jetpack/modules/carousel/jetpack-carousel.php
index 314dd7b..787f177 100644
--- a/plugins/jetpack/modules/carousel/jetpack-carousel.php
+++ b/plugins/jetpack/modules/carousel/jetpack-carousel.php
@@ -92,9 +92,12 @@ class Jetpack_Carousel {
 			// Also: not hardcoding path since there is no guarantee site is running on site root in self-hosted context.
 			$is_logged_in = is_user_logged_in();
 			$current_user = wp_get_current_user();
+			$comment_registration = intval( get_option( 'comment_registration' ) );
+			$require_name_email   = intval( get_option( 'require_name_email' ) );
 			$localize_strings = array(
 				'widths'               => $this->prebuilt_widths,
 				'is_logged_in'         => $is_logged_in,
+				'lang'                 => strtolower( substr( get_locale(), 0, 2 ) ),
 				'ajaxurl'              => admin_url( 'admin-ajax.php', is_ssl() ? 'https' : 'http' ),
 				'nonce'                => wp_create_nonce( 'carousel_nonce' ),
 				'display_exif'         => $this->test_1or0_option( get_option( 'carousel_display_exif' ), true ),
@@ -114,6 +117,9 @@ class Jetpack_Carousel {
 				'aperture'             => __( 'Aperture', 'jetpack' ),
 				'shutter_speed'        => __( 'Shutter Speed', 'jetpack' ),
 				'focal_length'         => __( 'Focal Length', 'jetpack' ),
+				'comment_registration' => $comment_registration,
+				'require_name_email'   => $require_name_email,
+				'login_url'            => wp_login_url( apply_filters( 'the_permalink', get_permalink() ) ),
 			);
 
 			if ( ! isset( $localize_strings['jetpack_comments_iframe_src'] ) || empty( $localize_strings['jetpack_comments_iframe_src'] ) ) {
@@ -122,13 +128,18 @@ class Jetpack_Carousel {
 				if ( $is_logged_in ) {
 					$localize_strings['local_comments_commenting_as'] = '<p id="jp-carousel-commenting-as">' . sprintf( __( 'Commenting as %s', 'jetpack' ), $current_user->data->display_name ) . '</p>';
 				} else {
-					$localize_strings['local_comments_commenting_as'] = ''
-						. '<fieldset><label for="email">' . __( 'Email (Required)', 'jetpack' ) . '</label> '
-						. '<input type="text" name="email" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-email-field" /></fieldset>'
-						. '<fieldset><label for="author">' . __( 'Name (Required)', 'jetpack' ) . '</label> '
-						. '<input type="text" name="author" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-author-field" /></fieldset>'
-						. '<fieldset><label for="url">' . __( 'Website', 'jetpack' ) . '</label> '
-						. '<input type="text" name="url" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-url-field" /></fieldset>';
+					if ( $comment_registration ) {
+						$localize_strings['local_comments_commenting_as'] = '<p id="jp-carousel-commenting-as">' . __( 'You must be <a href="#" class="jp-carousel-comment-login">logged in</a> to post a comment.', 'jetpack' ) . '</p>';
+					} else {
+						$required = ( $require_name_email ) ? __( '%s (Required)', 'jetpack' ) : '%s';
+						$localize_strings['local_comments_commenting_as'] = ''
+							. '<fieldset><label for="email">' . sprintf( $required, __( 'Email', 'jetpack' ) ) . '</label> '
+							. '<input type="text" name="email" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-email-field" /></fieldset>'
+							. '<fieldset><label for="author">' . sprintf( $required, __( 'Name', 'jetpack' ) ) . '</label> '
+							. '<input type="text" name="author" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-author-field" /></fieldset>'
+							. '<fieldset><label for="url">' . __( 'Website', 'jetpack' ) . '</label> '
+							. '<input type="text" name="url" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-url-field" /></fieldset>';
+						}
 				}
 			}
 
@@ -225,7 +236,21 @@ class Jetpack_Carousel {
 
 		if ( isset( $post ) ) {
 			$blog_id = (int) get_current_blog_id();
-			$extra_data = array( 'data-carousel-extra' => array( 'blog_id' => $blog_id, 'permalink' => get_permalink( $post->ID ) ) );
+
+			if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+				$likes_blog_id = $blog_id;
+			} else {
+				$jetpack = Jetpack::init();
+				$likes_blog_id = $jetpack->get_option( 'id' );
+			}
+
+			$extra_data = array(
+				'data-carousel-extra' => array(
+					'blog_id' => $blog_id,
+					'permalink' => get_permalink( $post->ID ),
+					'likes_blog_id' => $likes_blog_id
+					)
+				);
 
 			$extra_data = apply_filters( 'jp_carousel_add_data_to_container', $extra_data );
 			foreach ( (array) $extra_data as $data_key => $data_values ) {
@@ -265,11 +290,10 @@ class Jetpack_Carousel {
 
 		// 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>';
 			$out[] = array(
 				'id'              => $comment->comment_ID,
 				'parent_id'       => $comment->comment_parent,
-				'author_markup'   => $author_markup,
+				'author_markup'   => get_comment_author_link( $comment->comment_ID ),
 				'gravatar_markup' => get_avatar( $comment->comment_author_email, 64 ),
 				'date_gmt'        => $comment->comment_date_gmt,
 				'content'         => wpautop($comment->comment_content),
@@ -326,23 +350,26 @@ class Jetpack_Carousel {
 			$email        = $_POST['email'];
 			$url          = $_POST['url'];
 
-			if ( empty( $display_name ) )
-				die( json_encode( array( 'error' => __( 'Please provide your name.', 'jetpack' ) ) ) );
+			if ( get_option( 'require_name_email' ) ) {
+				if ( empty( $display_name ) )
+					die( json_encode( array( 'error' => __( 'Please provide your name.', 'jetpack' ) ) ) );
 
-			if ( empty( $email ) )
-				die( json_encode( array( 'error' => __( 'Please provide an email address.', 'jetpack' ) ) ) );
+				if ( empty( $email ) )
+					die( json_encode( array( 'error' => __( 'Please provide an email address.', 'jetpack' ) ) ) );
 
-			if ( ! is_email( $email ) )
-				die( json_encode( array( 'error' => __( 'Please provide a valid email address.', 'jetpack' ) ) ) );
+				if ( ! is_email( $email ) )
+					die( json_encode( array( 'error' => __( 'Please provide a valid email address.', 'jetpack' ) ) ) );
+			}
 		}
 
 		$comment_data =  array(
-			'comment_content' => $comment,
-			'comment_post_ID' => $_post_id,
-			'comment_author' => $display_name,
+			'comment_content'      => $comment,
+			'comment_post_ID'      => $_post_id,
+			'comment_author'       => $display_name,
 			'comment_author_email' => $email,
-			'comment_author_url' => $url,
-			'comment_approved' => 0,
+			'comment_author_url'   => $url,
+			'comment_approved'     => 0,
+			'comment_type'         => '',
 		);
 
 		if ( ! empty( $user_id ) )

diff --git a/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css b/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css
index 0d010eb..c34fcfb 100644
--- a/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css
+++ b/plugins/jetpack/modules/carousel/rtl/jetpack-carousel-rtl.css
@@ -1,4 +1,4 @@
-/* This file was automatically generated on Jan 29 2013 22:51:19 */
+/* This file was automatically generated on Apr 17 2013 14:28:54 */
 
 * {
 	line-height:inherit; /* prevent declarations of line-height in the universal selector */
@@ -50,7 +50,7 @@ only screen and (min-device-pixel-ratio: 1.5) {
 	background: #68c9e8; /* Safari */
 	color: #fff;
 	}
-	
+
 .jp-carousel-info ::-moz-selection {
 	background: #68c9e8; /* Firefox */
 	color: #fff;
@@ -135,7 +135,7 @@ div.jp-carousel-buttons a {
 	padding: 5px 0 5px 2px;
 	text-decoration: none !important;
 	text-shadow: none !important;
-	vertical-align: baseline !important;
+	vertical-align: middle;
 	-webkit-font-smoothing: subpixel-antialiased;
 }
 
@@ -483,7 +483,7 @@ div#carousel-reblog-box {
 	display: none;
 }
 
-.jp-carousel-photo-info h1:before, 
+.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 {
@@ -695,7 +695,7 @@ textarea#jp-carousel-comment-form-comment-field {
 	border-radius: 3px;
 	overflow: hidden;
 	-webkit-box-sizing: border-box;
-	-moz-box-sizing: border-box;    
+	-moz-box-sizing: border-box;
 	box-sizing: border-box;
 }
 
@@ -793,7 +793,7 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 }
 
 #jp-carousel-comment-post-results {
-	display: none;	
+	display: none;
 	overflow:auto;
 	width:100%;
 }
@@ -1052,14 +1052,14 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 		margin: 0 10px !important;
 	}
 
-	.jp-carousel-next-button, .jp-carousel-previous-button { 
-		display: none !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;
@@ -1067,31 +1067,31 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 		-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;	
+		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;
@@ -1099,8 +1099,8 @@ textarea#jp-carousel-comment-form-comment-field:focus::-webkit-input-placeholder
 	.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 d5d4da4..26bc504 100644
--- a/plugins/jetpack/modules/comments.php
+++ b/plugins/jetpack/modules/comments.php
@@ -5,6 +5,7 @@
  * Module Description: A new comment system that has integrated social media login options.
  * First Introduced: 1.4
  * Sort Order: 2
+ * Requires Connection: Yes
  */
 
 require dirname( __FILE__ ) . '/comments/comments.php';

diff --git a/plugins/jetpack/modules/comments/admin.php b/plugins/jetpack/modules/comments/admin.php
index 342b7f6..946f473 100644
--- a/plugins/jetpack/modules/comments/admin.php
+++ b/plugins/jetpack/modules/comments/admin.php
@@ -30,7 +30,7 @@ class Jetpack_Comments_Settings {
 
 		return $instance;
 	}
-	
+
 	public function __construct( Highlander_Comments_Base $jetpack_comments ) {
 		$this->jetpack_comments = $jetpack_comments;
 

diff --git a/plugins/jetpack/modules/comments/base.php b/plugins/jetpack/modules/comments/base.php
index f1b5440..858b6e3 100644
--- a/plugins/jetpack/modules/comments/base.php
+++ b/plugins/jetpack/modules/comments/base.php
@@ -102,22 +102,22 @@ class Highlander_Comments_Base {
  	 */
 	function comments_array( $comments ) {
 		global $wpdb, $post;
-	
+
 		$commenter = $this->get_current_commenter();
 
 		if ( !$commenter['user_id'] )
 			return $comments;
-	
+
 		if ( !$commenter['comment_author'] )
 			return $comments;
-	
+
 		$in_moderation_comments = $wpdb->get_results( $wpdb->prepare(
 			"SELECT * FROM `$wpdb->comments` WHERE `comment_post_ID` = %d AND `user_id` = 0 AND `comment_author` = %s AND `comment_author_email` = %s AND `comment_approved` = '0' ORDER BY `comment_date_gmt` /* Highlander_Comments_Base::comments_array() */",
 			$post->ID,
 			wp_specialchars_decode( $commenter['comment_author'], ENT_QUOTES ),
 			$commenter['comment_author_email']
 		) );
-	
+
 		if ( !$in_moderation_comments )
 			return $comments;
 
@@ -180,7 +180,7 @@ class Highlander_Comments_Base {
 	/**
 	 * Allows a logged out user to leave a comment as a facebook or twitter credentialed user.
 	 * Overrides WordPress' core comment_registration option to treat these commenters as "registered" (verified) users.
-	 * 
+	 *
 	 * @since JetpackComments (1.4)
 	 * @return If no
 	 */
@@ -256,12 +256,12 @@ class Highlander_Comments_Base {
 		if ( empty( $comment ) || is_wp_error( $comment ) ) {
 			return;
 		}
-	
+
 		$id_source = $this->is_highlander_comment_post();
 		if ( empty( $id_source ) ) {
 			return;
 		}
-	
+
 		// Set comment author cookies
 		if ( ( 'wordpress' != $id_source ) && is_user_logged_in() ) {
 			$comment_cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );

diff --git a/plugins/jetpack/modules/comments/comments.php b/plugins/jetpack/modules/comments/comments.php
index 8dae39b..fa156bb 100644
--- a/plugins/jetpack/modules/comments/comments.php
+++ b/plugins/jetpack/modules/comments/comments.php
@@ -141,19 +141,19 @@ class Jetpack_Comments extends Highlander_Comments_Base {
 			// 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 );
 	}
@@ -184,14 +184,14 @@ class Jetpack_Comments extends Highlander_Comments_Base {
 
 		// If users are required to be logged in, and they're not, then we don't need to do anything else
 		if ( get_option( 'comment_registration' ) && !is_user_logged_in() ) {
-			echo '<p id="must-log-in-to-comment">' . sprintf( apply_filters( 'jetpack_must_log_in_to_comment', __( 'You must <a href="%s">log in</a> to post a comment.', 'jetpack' ) ), wp_login_url( get_permalink() . '#respond' ) ) . '</p>';
+			echo '<p class="must-log-in">' . sprintf( apply_filters( 'jetpack_must_log_in_to_comment', __( 'You must <a href="%s">log in</a> to post a comment.', 'jetpack' ) ), wp_login_url( get_permalink() . '#respond' ) ) . '</p>';
 			return;
 		}
 
 		if ( in_array( 'subscriptions', Jetpack::get_active_modules() ) ) {
 			$stb_enabled = get_option( 'stb_enabled', 1 );
 			$stb_enabled = empty( $stb_enabled ) ? 0 : 1;
-		
+
 			$stc_enabled = get_option( 'stc_enabled', 1 );
 			$stc_enabled = empty( $stc_enabled ) ? 0 : 1;
 		} else {
@@ -209,6 +209,7 @@ class Jetpack_Comments extends Highlander_Comments_Base {
 			'show_avatars'         => ( get_option( 'show_avatars' )         ? '1' : '0' ),
 			'avatar_default'       => get_option( 'avatar_default' ),
 			'greeting'             => get_option( 'highlander_comment_form_prompt', __( 'Leave a Reply', 'jetpack' ) ),
+			'greeting_reply'       => apply_filters( 'jetpack_comment_form_prompt_reply', __( 'Leave a Reply to %s' , 'jetpack' ) ),
 			'color_scheme'         => get_option( 'jetpack_comment_form_color_scheme', $this->default_color_scheme ),
 			'lang'                 => get_bloginfo( 'language' ),
 			'jetpack_version'      => JETPACK__VERSION,
@@ -246,9 +247,11 @@ class Jetpack_Comments extends Highlander_Comments_Base {
 		// The actual iframe (loads comment form from Jetpack server)
 		?>
 
-		<div id="respond">
-			<div id="cancel-comment-reply-link" style="display:none; float:right;"><a href="#"><?php echo esc_html( __( 'Cancel Reply', 'jetpack' ) ); ?></a></div>
-			<iframe src="<?php echo esc_url( $url ); ?>" allowtransparency="<?php echo $transparent; ?>" style="width:100%; height: <?php echo $height; ?>px;border:0px;" frameBorder="0" scrolling="no" name="jetpack_remote_comment" id="jetpack_remote_comment"></iframe>
+		<div id="respond" class="comment-respond">
+			<h3 id="reply-title" class="comment-reply-title"><?php comment_form_title( esc_html( $params['greeting'] ), esc_html( $params['greeting_reply'] ) ); ?> <small><?php cancel_comment_reply_link( esc_html__( 'Cancel reply' , 'jetpack') ); ?></small></h3>
+			<div id="commentform" class="comment-form">
+				<iframe src="<?php echo esc_url( $url ); ?>" allowtransparency="<?php echo $transparent; ?>" style="width:100%; height: <?php echo $height; ?>px;border:0px;" frameBorder="0" scrolling="no" name="jetpack_remote_comment" id="jetpack_remote_comment"></iframe>
+			</div>
 		</div>
 
 		<?php // Below is required for comment reply JS to work ?>

diff --git a/plugins/jetpack/modules/contact-form.php b/plugins/jetpack/modules/contact-form.php
index d53fc4c..21f409f 100644
--- a/plugins/jetpack/modules/contact-form.php
+++ b/plugins/jetpack/modules/contact-form.php
@@ -1,9 +1,10 @@
 <?php
 /**
  * Module Name: Contact Form
- * Module Description: Easily insert a contact form any where on your site.
+ * Module Description: Easily insert a contact form anywhere on your site.
  * Sort Order: 9
  * First Introduced: 1.3
+ * Requires Connection: No
  */
 
 include dirname( __FILE__ ) . '/contact-form/grunion-contact-form.php';

diff --git a/plugins/jetpack/modules/contact-form/admin.php b/plugins/jetpack/modules/contact-form/admin.php
index d3efefa..5a6af06 100644
--- a/plugins/jetpack/modules/contact-form/admin.php
+++ b/plugins/jetpack/modules/contact-form/admin.php
@@ -1,21 +1,10 @@
 <?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>';
+function grunion_menu_alter() {
+	wp_enqueue_style( 'grunion-menu-alter', plugins_url( 'css/menu-alter.css', __FILE__ ) );
 }
 
-add_action('admin_head', 'menu_alter');
+add_action( 'admin_enqueue_scripts', 'grunion_menu_alter' );
 
 /**
  * Add a contact form button to the post composition screen
@@ -27,8 +16,13 @@ function grunion_media_button( ) {
 	$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" ) );
+	?>
+
+	<a id="insert-jetpack-contact-form" class="button thickbox" title="<?php esc_html_e( 'Add Contact Form', 'jetpack' ); ?>" data-editor="content" href="<?php echo $site_url ?>&id=add_form">
+		<span class="jetpack-contact-form-icon"></span> <?php esc_html_e( 'Add Contact Form', 'jetpack' ); ?>
+	</a>
 
-	echo '<a href="' . $site_url . '&id=add_form" class="thickbox" title="' . $title . '"><div class="grunion-menu-button" alt="' . $title . '"></div></a>';
+	<?php
 }
 
 add_action( 'wp_ajax_grunion_form_builder', 'display_form_view' );
@@ -42,14 +36,14 @@ function display_form_view() {
 add_action( 'admin_print_styles', 'grunion_admin_css' );
 function grunion_admin_css() {
 	global $current_screen;
-	if ( 'edit-feedback' != $current_screen->id )
+	if ( ! in_array( $current_screen->id, array( 'edit-feedback', 'jetpack_page_omnisearch', 'dashboard_page_omnisearch' ) ) )
 		return;
 
 	wp_enqueue_script( 'wp-lists' );
 ?>
 
 <style type='text/css'>
-.add-new-h2, .view-switch, body.no-js .tablenav select[name^=action], body.no-js #doaction, body.no-js #doaction2 { 
+.add-new-h2, .view-switch, body.no-js .tablenav select[name^=action], body.no-js #doaction, body.no-js #doaction2 {
 	display: none
 }
 
@@ -191,7 +185,7 @@ function grunion_admin_view_tabs( $views ) {
 	preg_match( '|post_type=feedback\'( class="current")?\>(.*)\<span class=|', $views['all'], $match );
 	if ( !empty( $match[2] ) )
 		$views['all'] = str_replace( $match[2], 'Messages ', $views['all'] );
-	
+
 	return $views;
 }
 
@@ -336,7 +330,7 @@ jQuery(document).ready( function($) {
 			function( r ) {
 				$('#post-<?php echo $post_id; ?>')
 					.css( {backgroundColor:'#FF7979'} )
-					.fadeOut(350, function() { 
+					.fadeOut(350, function() {
 						$(this).remove();
 						$('.subsubsub').html(r);
 				});
@@ -394,7 +388,7 @@ jQuery(document).ready( function($) {
 			function( r ) {
 				$('#post-<?php echo $post_id; ?>')
 					.css( {backgroundColor:'#59C859'} )
-					.fadeOut(350, function() { 
+					.fadeOut(350, function() {
 						$(this).remove();
 						$('.subsubsub').html(r);
 				});
@@ -473,7 +467,7 @@ function grunion_ajax_shortcode() {
 // and constructs a json object representing its contents and attributes
 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'] ) ) {
@@ -583,7 +577,7 @@ function grunion_ajax_spam() {
 	$sql = "
 		SELECT post_status,
 			COUNT( * ) AS post_count
-		FROM `{$wpdb->posts}` 
+		FROM `{$wpdb->posts}`
 		WHERE post_type =  'feedback'
 		GROUP BY post_status
 	";
@@ -631,3 +625,12 @@ function grunion_ajax_spam() {
 	echo $status_html;
 	exit;
 }
+
+add_action( 'omnisearch_add_providers', 'grunion_omnisearch_add_providers' );
+function grunion_omnisearch_add_providers() {
+	// Feedback uses capability_type 'page'
+	if ( current_user_can( 'edit_pages' ) ) {
+		require_once( GRUNION_PLUGIN_DIR . '/grunion-omnisearch.php' );
+		new Jetpack_Omnisearch_Grunion;
+	}
+}

diff --git a/plugins/jetpack/modules/contact-form/css/grunion.css b/plugins/jetpack/modules/contact-form/css/grunion.css
index 0003518..d47948b 100644
--- a/plugins/jetpack/modules/contact-form/css/grunion.css
+++ b/plugins/jetpack/modules/contact-form/css/grunion.css
@@ -1,5 +1,5 @@
 .contact-form .clear-form { clear: both; }
-.contact-form input[type='text'], .contact-form input[type='email'] { width: 300px; margin-bottom: 13px; }
+.contact-form input[type='text'], .contact-form input[type='email'] { width: 300px; max-width: 98%; 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; }
@@ -7,4 +7,4 @@
 .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; }
 .form-errors .form-error-message { color: red; }
-.textwidget input[type='text'], .textwidget input[type='email'], .textwidget textarea { width: 250px; }
+.textwidget input[type='text'], .textwidget input[type='email'], .textwidget textarea { width: 250px; max-width: 98%; }

diff --git a/plugins/jetpack/modules/contact-form/grunion-contact-form.php b/plugins/jetpack/modules/contact-form/grunion-contact-form.php
index 5600feb..76e43be 100644
--- a/plugins/jetpack/modules/contact-form/grunion-contact-form.php
+++ b/plugins/jetpack/modules/contact-form/grunion-contact-form.php
@@ -67,10 +67,20 @@ class Grunion_Contact_Form_Plugin {
 
 		add_action( 'loop_start', array( 'Grunion_Contact_Form', '_style_on' ) );
 
+		add_action( 'wp_ajax_grunion-contact-form', array( $this, 'ajax_request' ) );
+		add_action( 'wp_ajax_nopriv_grunion-contact-form', array( $this, 'ajax_request' ) );
+
+		// Export to CSV feature
+		if ( is_admin() ) {
+			add_action( 'admin_init',    array( $this, 'download_feedback_as_csv' ) );
+			add_action( 'load-edit.php', array( $this, 'export_form' ) );
+			add_action( 'admin_footer',  array( $this, 'move_export_form_to_bottom' ) );
+		}
+
 		// custom post type we'll use to keep copies of the feedback items
 		register_post_type( 'feedback', array(
 			'labels'            => array(
-				'name'               => __( 'Feedbacks', 'jetpack' ),
+				'name'               => __( 'Feedback', 'jetpack' ),
 				'singular_name'      => __( 'Feedback', 'jetpack' ),
 				'search_items'       => __( 'Search Feedback', 'jetpack' ),
 				'not_found'          => __( 'No feedback found', 'jetpack' ),
@@ -98,7 +108,7 @@ class Grunion_Contact_Form_Plugin {
 
 		// POST handler
 		if (
-			'POST' == strtoupper( $_SERVER['REQUEST_METHOD'] )
+			isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' == strtoupper( $_SERVER['REQUEST_METHOD'] )
 		&&
 			isset( $_POST['action'] ) && 'grunion-contact-form' == $_POST['action']
 		&&
@@ -136,9 +146,10 @@ class Grunion_Contact_Form_Plugin {
 			// It's a form embedded in a text widget
 
 			$this->current_widget_id = substr( $id, 7 ); // remove "widget-"
-			
+			$widget_type = implode( '-', array_slice( explode( '-', $this->current_widget_id ), 0, -1 ) ); // Remove trailing -#
+
 			// Is the widget active?
-			$sidebar = is_active_widget( false, $this->current_widget_id, 'text' );
+			$sidebar = is_active_widget( false, $this->current_widget_id, $widget_type );
 
 			// 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;
@@ -161,12 +172,34 @@ class Grunion_Contact_Form_Plugin {
 
 		$form = Grunion_Contact_Form::$last;
 
-		if ( !$form || ( is_wp_error( $form->errors ) && $form->errors->get_error_codes() ) ) {
-			return;
-		}
+		if ( ! $form )
+			return false;
+
+		if ( is_wp_error( $form->errors ) && $form->errors->get_error_codes() )
+			return $form->errors;
 
 		// Process the form
-		$form->process_submission();
+		return $form->process_submission();
+	}
+
+	function ajax_request() {
+		$submission_result = self::process_form_submission();
+
+		if ( ! $submission_result ) {
+			header( "HTTP/1.1 500 Server Error", 500, true );
+			echo '<div class="form-error"><ul class="form-errors"><li class="form-error-message">';
+			esc_html_e( 'An error occurred. Please try again later.', 'jetpack' );
+			echo '</li></ul></div>';
+		} elseif ( is_wp_error( $submission_result ) ) {
+			header( "HTTP/1.1 400 Bad Request", 403, true );
+			echo '<div class="form-error"><ul class="form-errors"><li class="form-error-message">';
+			echo esc_html( $submission_result->get_error_message() );
+			echo '</li></ul></div>';
+		} else {
+			echo '<h3>' . esc_html__( 'Message Sent', 'jetpack' ) . '</h3>' . $submission_result;
+		}
+
+		die;
 	}
 
 	/**
@@ -263,7 +296,7 @@ class Grunion_Contact_Form_Plugin {
 		foreach ( $_SERVER as $k => $value )
 			if ( !in_array( $k, $ignore ) && is_string( $value ) )
 				$form["$k"] = $value;
-			
+
 		return $form;
 	}
 
@@ -277,7 +310,7 @@ class Grunion_Contact_Form_Plugin {
 	 */
 	function is_spam_akismet( $form ) {
 		global $akismet_api_host, $akismet_api_port;
-	
+
 		if ( !function_exists( 'akismet_http_post' ) )
 			return false;
 
@@ -307,6 +340,194 @@ class Grunion_Contact_Form_Plugin {
 		$response = akismet_http_post( $query_string, $akismet_api_host, "/1.1/submit-{$as}", $akismet_api_port );
 		return trim( $response[1] );
 	}
+
+	/**
+	 * There aren't any usable actions in core to output the "export feedback" form in the correct place,
+	 * so this inline JS moves it from the top of the page to the bottom.
+	 */
+	function move_export_form_to_bottom() {
+		if ( get_current_screen()->id != 'edit-feedback' )
+			return;
+
+		// if there aren't any feedbacks, bail out
+		if ( ! (int) wp_count_posts( 'feedback' )->publish )
+			return;
+
+		echo "
+		<script type='text/javascript'>
+		var menu = document.getElementById( 'feedback-export' ),
+		wrapper = document.getElementsByClassName( 'wrap' )[0];
+		wrapper.appendChild(menu);
+		menu.style.display = 'block';
+		</script>
+		";
+	}
+
+	/**
+	 * Prints the menu
+	 */
+	function export_form() {
+		if ( get_current_screen()->id != 'edit-feedback' )
+			return;
+
+		// if there aren't any feedbacks, bail out
+		if ( ! (int) wp_count_posts( 'feedback' )->publish )
+			return;
+		?>
+
+		<div id="feedback-export" style="display:none">
+			<h2><?php _e( 'Export feedback as CSV', 'jetpack' ) ?></h2>
+			<div class="clear"></div>
+			<form action="<?php echo admin_url( 'admin-post.php' ); ?>" method="post" class="form">
+				<?php wp_nonce_field( 'feedback_export','feedback_export_nonce' ); ?>
+
+				<input name="action" value="feedback_export" type="hidden">
+				<label for="post"><? _e( 'Select feedback to download', 'jetpack' ) ?></label>
+				<select name="post">
+					<option value="all"><?php esc_html_e( 'All posts', 'jetpack' ) ?></option>
+					<?php echo $this->get_feedbacks_as_options() ?>
+				</select>
+
+				<br><br>
+				<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_html_e( 'Download', 'jetpack' ); ?>">
+			</form>
+		</div>
+
+		<?php
+	}
+
+	/**
+	 * download as a csv a contact form or all of them in a csv file
+	 */
+	function download_feedback_as_csv() {
+		if ( empty( $_POST['feedback_export_nonce'] ) )
+			return;
+
+		check_admin_referer( 'feedback_export', 'feedback_export_nonce' );
+
+		$args = array(
+			'posts_per_page'   => -1,
+			'post_type'        => 'feedback',
+			'post_status'      => 'publish',
+			'meta_key'         => '_feedback_subject',
+			'orderby'          => 'meta_value',
+			'fields'           => 'ids',
+			'suppress_filters' => false,
+		);
+
+		$filename = date( "Y-m-d" ) . '-feedback-export.csv';
+
+		// Check if we want to download all the feedbacks or just a certain contact form
+		if ( ! empty( $_POST['post'] ) && $_POST['post'] !== 'all' ) {
+			$args['post_parent'] = (int) $_POST['post'];
+			$filename            = date( "Y-m-d" ) . '-' . str_replace( '&nbsp;', '-', get_the_title( (int) $_POST['post'] ) ) . '.csv';
+		}
+
+		$feedbacks = get_posts( $args );
+		$filename  = sanitize_file_name( $filename );
+		$fields    = $this->get_field_names( $feedbacks );
+		array_unshift( $fields, __( 'Contact Form', 'jetpack' ) );
+
+		if ( empty( $feedbacks ) )
+			return;
+
+		// Forces the download of the CSV instead of echoing
+		header( 'Content-Disposition: attachment; filename=' . $filename );
+		header( 'Pragma: no-cache' );
+		header( 'Expires: 0' );
+		header( 'Content-Type: text/csv; charset=utf-8' );
+
+		$output = fopen( 'php://output', 'w' );
+
+		// Prints the header
+		fputcsv( $output, $fields );
+
+		// Create the csv string from the array of post ids
+		foreach ( $feedbacks as $feedback ) {
+			fputcsv( $output, self::make_csv_row_from_feedback( $feedback, $fields ) );
+		}
+
+		fclose( $output );
+	}
+
+	/**
+	 * Returns a string of HTML <option> items from an array of posts
+	 *
+	 * @return string a string of HTML <option> items
+	 */
+	protected function get_feedbacks_as_options() {
+		$options = '';
+
+		// Get the feedbacks' parents' post IDs
+		$feedbacks = get_posts( array(
+			'fields'           => 'id=>parent',
+			'posts_per_page'   => -1,
+			'post_type'        => 'feedback',
+			'post_status'      => 'publish',
+			'suppress_filters' => false,
+		) );
+		$parents = array_unique( array_values( $feedbacks ) );
+
+		$posts = get_posts( array(
+			'orderby'          => 'ID',
+			'posts_per_page'   => -1,
+			'post_type'        => 'any',
+			'post__in'         => array_values( $parents ),
+			'suppress_filters' => false,
+		) );
+
+		// creates the string of <option> elements
+		foreach ( $posts as $post ) {
+			$options .= sprintf( '<option value="%s">%s</option>', esc_attr( $post->ID ), esc_html( $post->post_title ) );
+		}
+
+		return $options;
+	}
+
+	/**
+	 * Get the names of all the form's fields
+	 *
+	 * @param  array|int $posts the post we want the fields of
+	 * @return array     the array of fields
+	 */
+	protected function get_field_names( $posts ) {
+		$posts = (array) $posts;
+		$all_fields = array();
+
+		foreach ( $posts as $post ){
+			$extra_fields = array_keys( get_post_meta( $post, '_feedback_all_fields', true ) );
+			$all_fields = array_merge( $all_fields, $extra_fields );
+		}
+
+		$all_fields = array_unique( $all_fields );
+		return $all_fields;
+	}
+
+	/**
+	 * Creates a valid csv row from a post id
+	 *
+	 * @param  int    $post_id The id of the post
+	 * @param  array  $fields  An array containing the names of all the fields of the csv
+	 * @return String The csv row
+	 */
+	protected static function make_csv_row_from_feedback( $post_id, $fields ) {
+		$all_fields = get_post_meta( $post_id, '_feedback_all_fields', true );
+
+		// The first element in all of the exports will be the subject
+		$row_items[] = get_post_meta( $post_id, '_feedback_subject', true );
+
+		// Loop the fields array in order to fill the $row_items array correctly
+		foreach ( $fields as $field ) {
+			if ( $field === __( 'Contact Form', 'jetpack' ) ) // the first field will ever be the contact form, so we can continue
+				continue;
+			elseif ( array_key_exists( $field, $all_fields ) )
+				$row_items[] = $all_fields[$field];
+			else
+				$row_items[] = '';
+		}
+
+		return $row_items;
+	}
 }
 
 /**
@@ -520,11 +741,12 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 		}
 
 		$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.
+			'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.
+			'submit_button_text' => __( 'Submit &#187;', 'jetpack' ),
 		);
 
 		$attributes = shortcode_atts( $this->defaults, $attributes );
@@ -622,7 +844,7 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 
 		$r = '';
 		$r .= "<div id='contact-form-$id'>\n";
-	
+
 		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";
@@ -645,62 +867,7 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 
 			// 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() ) );
+				$r_success_message .= self::success_message( $feedback_id, $form );
 			}
 
 			$r .= apply_filters( 'grunion_contact_form_success_message', $r_success_message );
@@ -721,7 +888,7 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 			$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<input type='submit' value='" . esc_attr( $form->get_attribute( 'submit_button_text' ) ) . "' 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";
@@ -734,6 +901,69 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 		return $r;
 	}
 
+	static function success_message( $feedback_id, $form ) {
+		$r_success_message = '';
+
+		$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() ) );
+
+		return $r_success_message;
+	}
+
 	/**
 	 * 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.
@@ -844,7 +1074,7 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 
 		// No one to send it to :(
 		if ( !$valid_emails ) {
-			return;
+			return false;
 		}
 
 		$to = $valid_emails;
@@ -852,11 +1082,11 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 		// 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;
+				return false;
 			}
 		} else {
 			if ( $post->ID != $_POST['contact-form-id'] ) {
-				return;
+				return false;
 			}
 		}
 
@@ -937,7 +1167,7 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 		// 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
+			return $is_spam; // abort
 		else if ( $is_spam === TRUE )  // TRUE to flag a spam
 			$spam = '***SPAM*** ';
 
@@ -959,14 +1189,16 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 
 		$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') . "\""; 
+					"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' ) );
-	
+		$date_time_format = _x( '%1$s \a\t %2$s', '{$date_format} \a\t {$time_format}', 'jetpack' );
+		$date_time_format = sprintf( $date_time_format, get_option( 'date_format' ), get_option( 'time_format' ) );
+		$time = date_i18n( $date_time_format, current_time( 'timestamp' ) );
+
 		$extra_content = '';
-	
+
 		foreach ( $extra_values as $label => $value ) {
 			$extra_content .= $label . ': ' . trim( $value ) . "\n";
 		}
@@ -1072,6 +1304,10 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
 		elseif ( apply_filters( 'grunion_still_email_spam', FALSE ) == TRUE ) // don't send spam by default.  Filterable.
 			wp_mail( $to, "{$spam}{$subject}", $message, $headers );
 
+		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
+			return self::success_message( $post_id, $this );
+		}
+
 		$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'];
@@ -1168,12 +1404,12 @@ class Grunion_Contact_Form_Field extends Crunion_Contact_Form_Shortcode {
 			$unescaped_label = preg_replace( '/[^a-zA-Z0-9.-_:]/', '', $unescaped_label );
 
 			if ( empty( $id ) ) {
-				$id = sanitize_title_with_dashes( 'g' + $form_id . '-' . $unescaped_label );
+				$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 );
+					$id = sanitize_title_with_dashes( 'g' . $form_id . '-' . $unescaped_label . '-' . $i );
 
 					if ( $i > $max_tries ) {
 						break;
@@ -1320,7 +1556,7 @@ class Grunion_Contact_Form_Field extends Crunion_Contact_Form_Shortcode {
 		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";
+			$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";
@@ -1328,6 +1564,14 @@ class Grunion_Contact_Form_Field extends Crunion_Contact_Form_Shortcode {
 			$r .= "\t</select>\n";
 			$r .= "\t</div>\n";
 			break;
+		case 'date' :
+			$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='date' 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";
+
+			wp_enqueue_script( 'grunion-frontend', plugins_url( 'js/grunion-frontend.js', __FILE__ ), array( 'jquery', 'jquery-ui-datepicker' ) );
+			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
@@ -1373,7 +1617,7 @@ function grunion_delete_old_spam() {
 	# nothing special about 5000 or 11
 	# just trying to periodically recover deleted rows
 	$random_num = mt_rand( 1, 5000 );
-	if ( apply_filters( 'grunion_optimize_table', ( $random_number == 11 ) ) ) {
+	if ( apply_filters( 'grunion_optimize_table', ( $random_num == 11 ) ) ) {
 		$wpdb->query( "OPTIMIZE TABLE $wpdb->posts" );
 	}
 

diff --git a/plugins/jetpack/modules/contact-form/grunion-form-view.php b/plugins/jetpack/modules/contact-form/grunion-form-view.php
index 836369a..79d1242 100644
--- a/plugins/jetpack/modules/contact-form/grunion-form-view.php
+++ b/plugins/jetpack/modules/contact-form/grunion-form-view.php
@@ -72,8 +72,8 @@ wp_localize_script( 'grunion', 'GrunionFB_i18n', array(
 	#sidemenu a { text-decoration:none; border-top: 1px solid #FFF; display:block; float:left; line-height:28px; padding:0 13px; outline: none; }
 	#sidemenu a.current { background-color:#F9F9F9; border-color:#DFDFDF #DFDFDF #F9F9F9; color:#D54E21; -moz-border-radius:4px 4px 0 0; border-radius:4px 4px 0 0; -webkit-border-radius:4px 4px 0 0; border-style:solid; border-width:1px; font-weight:normal; }
 	#sidemenu li { display:inline; margin-bottom:6px; line-height:200%; list-style:none outside none; margin:0; padding:0; text-align:center; white-space:nowrap; }
-	.button { background-color:#FFFFFF; background:url("<?php echo get_bloginfo('url'); ?>/wp-admin/images/white-grad.png") repeat-x scroll left top #F2F2F2; border-color:#BBBBBB; min-width:80px; text-align:center; color:#464646; text-shadow:0 1px 0 #FFFFFF; border-style:solid; border-width:1px; cursor:pointer; width: auto; font-size:11px !important; line-height:13px; padding:3px 11px; margin-top: 12px; text-decoration:none; -moz-border-radius:11px; border-radius:11px; -webkit-border-radius:11px }
-	.button-primary { background-color:#FFFFFF; font-weight: bold; background: url('<?php echo get_bloginfo('url'); ?>/wp-admin/images/button-grad-active.png') repeat-x scroll left top #21759B; border-color:#298CBA; text-align:center; color:#EAF2FA; text-shadow:0 -1px 0 rgba(0, 0, 0, 0.3); border-style:solid; border-width:1px; cursor:pointer; width: auto; font-size:11px !important; line-height:13px; padding:3px 11px; margin-top: 21px; text-decoration:none; -moz-border-radius:11px; border-radius:11px; -webkit-border-radius:11px }
+	.button { background-color:#f2f2f2; border-color:#BBBBBB; min-width:80px; text-align:center; color:#464646; text-shadow:0 1px 0 #FFFFFF; border-style:solid; border-width:1px; cursor:pointer; width: auto; font-size:11px !important; line-height:13px; padding:3px 11px; margin-top: 12px; text-decoration:none; -moz-border-radius:11px; border-radius:11px; -webkit-border-radius:11px }
+	.button-primary { background-color:#21759B; font-weight: bold; border-color:#298CBA; text-align:center; color:#EAF2FA; text-shadow:0 -1px 0 rgba(0, 0, 0, 0.3); border-style:solid; border-width:1px; cursor:pointer; width: auto; font-size:11px !important; line-height:13px; padding:3px 11px; margin-top: 21px; text-decoration:none; -moz-border-radius:11px; border-radius:11px; -webkit-border-radius:11px }
 	.clear { clear: both; }
 	.fb-add-field { padding-left: 10px; }
 	.fb-add-option { margin: 0 0 14px 100px; }
@@ -132,8 +132,8 @@ wp_localize_script( 'grunion', 'GrunionFB_i18n', array(
 			); ?></p>
 			<h3 style="margin-top: 21px;"><?php esc_html_e( 'Can I view my feedback within WordPress?', 'jetpack' ); ?></h3>
 			<p><?php printf(
-				esc_html( _x( 'Yep, you can read your feedback at any time by clicking the "%1$s" link in the admin menu.', '%1$s = "Feedbacks" in an HTML link', 'jetpack' ) ),
-				'<a id="fb-feedback" href="' . admin_url( 'edit.php?post_type=feedback' ) . '">' . esc_html__( 'Feedbacks', 'jetpack' ) . '</a>'
+				esc_html( _x( 'Yep, you can read your feedback at any time by clicking the "%1$s" link in the admin menu.', '%1$s = "Feedback" in an HTML link', 'jetpack' ) ),
+				'<a id="fb-feedback" href="' . admin_url( 'edit.php?post_type=feedback' ) . '">' . esc_html__( 'Feedback', 'jetpack' ) . '</a>'
 			); ?></p>
 			<div class="clear"></div>
 		</div>
@@ -144,10 +144,10 @@ wp_localize_script( 'grunion', 'GrunionFB_i18n', array(
 		</div>
 		<div id="fb-add-field" style="display: none;">
 			<h3><?php esc_html_e( 'Edit this new field', 'jetpack' ); ?></h3>
-			
+
 			<label for="fb-new-label"><?php esc_html_e( 'Label', 'jetpack' ); ?></label>
 			<input type="text" id="fb-new-label" value="<?php esc_attr_e( 'New field', 'jetpack' ); ?>" />
-			
+
 			<label for="fb-new-label"><?php esc_html_e( 'Field type', 'jetpack' ); ?></label>
 			<select id="fb-new-type">
 				<option value="checkbox"><?php esc_html_e( 'Checkbox', 'jetpack' ); ?></option>
@@ -160,7 +160,7 @@ wp_localize_script( 'grunion', 'GrunionFB_i18n', array(
 				<option value="url"><?php esc_html_e( 'Website', 'jetpack' ); ?></option>
 			</select>
 			<div class="clear"></div>
-			
+
 			<div id="fb-options" style="display: none;">
 				<div id="fb-new-options">
 					<label for="fb-option0"><?php esc_html_e( 'Options', 'jetpack' ); ?></label>
@@ -170,14 +170,14 @@ wp_localize_script( 'grunion', 'GrunionFB_i18n', array(
 					<a href="#" id="fb-another-option"><?php esc_html_e( 'Add another option', 'jetpack' ); ?></a>
 				</div>
 			</div>
-			
+
 			<div class="fb-required">
 				<label for="fb-new-label"></label>
 				<input type="checkbox" id="fb-new-required" />
 				<label for="fb-new-label" class="fb-radio-label"><?php esc_html_e( 'Required?', 'jetpack' ); ?></label>
 				<div class="clear"></div>
 			</div>
-			
+
 			<input type="hidden" id="fb-field-id" />
 			<input type="submit" class="button" value="<?php esc_attr_e( 'Save this field', 'jetpack' ); ?>" id="fb-save-field" name="save">
 		</div>
@@ -186,9 +186,9 @@ wp_localize_script( 'grunion', 'GrunionFB_i18n', array(
 		<div id="fb-preview-form" class="fb-container">
 			<h1><?php esc_html_e( 'Here&#8217;s what your form will look like', 'jetpack' ); ?></h1>
 			<div id="sortable" class="fb-form-case">
-				
+
 				<div id="fb-extra-fields" class="fb-extra-fields"></div>
-				
+
 				<a href="#" id="fb-new-field" class="fb-add-field"><?php esc_html_e( 'Add a new field', 'jetpack' ); ?></a>
 			</div>
 			<input type="submit" class="button-primary" tabindex="4" value="<?php esc_attr_e( 'Add this form to my post', 'jetpack' ); ?>" id="fb-save-form" name="save">

diff --git a/plugins/jetpack/modules/contact-form/js/grunion.js b/plugins/jetpack/modules/contact-form/js/grunion.js
index 835f7f8..bbfd89e 100644
--- a/plugins/jetpack/modules/contact-form/js/grunion.js
+++ b/plugins/jetpack/modules/contact-form/js/grunion.js
@@ -1,5 +1,5 @@
-if (!window.FB) {
-    window.FB = {};
+if ( ! window.FB ) {
+	window.FB = {};
 }
 
 GrunionFB_i18n = jQuery.extend( {
@@ -426,7 +426,7 @@ FB.ContactForm = function() {
 	function showAndHideMessage (message) {
 		try {
 			var newMessage = (!message) ? GrunionFB_i18n.savedMessage : message;
-			jQuery('#fb-success').html(newMessage);
+			jQuery('#fb-success').text(newMessage);
 			jQuery('#fb-success').slideDown('fast');
 			setTimeout(function () {
 				 jQuery('#fb-success').slideUp('fast');
@@ -463,9 +463,9 @@ FB.ContactForm = function() {
 			var thisLabel = jQuery('#fb-new-label').val();
 			// Update preview
 			if (thisLabel.length === 0) {
-				jQuery('#fb-new-field' + thisId + ' label .label-text').html("New field");
+				jQuery('#fb-new-field' + thisId + ' label .label-text').text( GrunionFB_i18n.newLabel );
 			} else {
-				jQuery('#fb-new-field' + thisId + ' label .label-text').html(thisLabel);
+				jQuery('#fb-new-field' + thisId + ' label .label-text').text( thisLabel );
 			}
 			// Update fbForm object
 			fbForm.fields[thisId].label = thisLabel;
@@ -493,7 +493,7 @@ FB.ContactForm = function() {
 			var thisType = jQuery('#fb-new-type').val();
 			// Update preview
 			if (thisType === "radio") {
-				jQuery('#fb-radio-' + thisId + '-' + thisOptionid + ' span').html(thisOptionValue);
+				jQuery('#fb-radio-' + thisId + '-' + thisOptionid + ' span').text(thisOptionValue);
 			} else {
 				jQuery('#fb-' + thisId + '-' + thisOptionid).text(thisOptionValue);
 			}
@@ -538,7 +538,7 @@ 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-text').html(); }
+			if (!thisLabelText) { var thisLabelText = jQuery('#fb-new-field' + thisId + ' .label-text').text(); }
 			var isRequired = (thisRequired) ? '<span class="label-required">' + GrunionFB_i18n.requiredLabel + '</span>' : '';
 			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" />';
@@ -645,6 +645,8 @@ FB.ContactForm = function() {
 				content: contentSource
 			};
 
+			var $doc = jQuery(document);
+
 			jQuery.post(ajaxurl, data, function(response) {
 				// Setup fbForm
 				parseShortcode(jQuery.parseJSON(response));
@@ -666,7 +668,7 @@ FB.ContactForm = function() {
 			jQuery('#fb-new-required').click(function () {
 				updateRequired();
 			});
-			jQuery('.fb-remove').live('click', function () {
+			$doc.on('click', '.fb-remove', function () {
 				showDesc();
 				deleteField(jQuery(this));
 				grabShortcode();
@@ -680,13 +682,13 @@ FB.ContactForm = function() {
 					hidePopup();
 				}
 			});
-			jQuery('#fb-another-option').live('click', function () {
+			$doc.on('click', '#fb-another-option', function () {
 				addOption();
 			});
-			jQuery('.fb-options').live('keyup', function () {
+			$doc.on('keyup', '.fb-options', function () {
 				updateOption(jQuery(this));
 			});
-			jQuery('.fb-remove-option').live('click', function () {
+			$doc.on('click', '.fb-remove-option', function () {
 				removeOption(jQuery(this).attr('optionid'));
 			});
 			jQuery('#tab-preview a').click(function () {
@@ -708,21 +710,21 @@ FB.ContactForm = function() {
 			jQuery('#fb-field-subject').blur(function () {
 				updateSubject();
 			});
-			jQuery('.fb-form-case .fb-new-fields').live('mouseenter', function () {
+			$doc.on('mouseenter', '.fb-form-case .fb-new-fields', function () {
 				hideShowEditLink('show', jQuery(this));
 			});
-			jQuery('.fb-form-case .fb-new-fields').live('mouseleave', function () {
+			$doc.on('mouseleave', '.fb-form-case .fb-new-fields', function () {
 				hideShowEditLink('hide');
 				return false;
 			});
-			jQuery('.fb-edit-field').live('click', function () {
+			$doc.on('click', '.fb-edit-field', function () {
 				editField(jQuery(this));
 				return false;
 			});
-			jQuery('.fb-edit-field .fb-reorder').live('click', function () {
+			$doc.on('click', '.fb-edit-field .fb-reorder', function () {
 				return false;
 			});
-			jQuery('#fb-save-field').live('click', function () {
+			$doc.on('click', '#fb-save-field', function () {
 				showDesc();
 				showAndHideMessage();
 				return false;

diff --git a/plugins/jetpack/modules/custom-css.php b/plugins/jetpack/modules/custom-css.php
index 2b5e6a3..051976a 100644
--- a/plugins/jetpack/modules/custom-css.php
+++ b/plugins/jetpack/modules/custom-css.php
@@ -5,6 +5,7 @@
  * Module Description: Customize the appearance of your site using CSS but without modifying your theme.
  * Sort Order: 11
  * First Introduced: 1.7
+ * Requires Connection: No
  */
 
 function jetpack_load_custom_css() {

diff --git a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php
index f458a46..c5826a0 100644
--- a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php
+++ b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy.php
@@ -736,7 +736,7 @@ class csstidy {
 
 										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 (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 . '"';
 												}
@@ -778,7 +778,7 @@ class csstidy {
 									}
 									else {
 										$this->sub_value = "format(";
-										
+
 										foreach ($format_strings as $format_string) {
 											$this->sub_value .= '"' . str_replace('"', '\\"', $format_string) . '",';
 										}
@@ -844,7 +844,7 @@ class csstidy {
 					$_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 
+					// 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};
@@ -1171,6 +1171,7 @@ class csstidy {
 	 * @version 1.0
 	 */
 	function property_is_valid($property) {
+		$property = strtolower($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 );

diff --git a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_optimise.php b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_optimise.php
index 364573a..2ed9f80 100644
--- a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_optimise.php
+++ b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_optimise.php
@@ -19,7 +19,7 @@
  *   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/>.
  *
@@ -262,8 +262,7 @@ class csstidy_optimise {
 	 */
 	function compress_important(&$string) {
 		if (csstidy::is_important($string)) {
-			$string = csstidy::gvw_important($string) . '!important';
-		}
+			$string = csstidy::gvw_important($string) . ' !important';		}
 		return $string;
 	}
 
@@ -627,7 +626,7 @@ class csstidy_optimise {
 		// 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');
@@ -713,7 +712,7 @@ class csstidy_optimise {
 		// 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

diff --git a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_print.php b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_print.php
index 00a1956..e2ed97e 100644
--- a/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_print.php
+++ b/plugins/jetpack/modules/custom-css/csstidy/class.csstidy_print.php
@@ -19,7 +19,7 @@
  *   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/>.
  *
@@ -312,7 +312,7 @@ class csstidy_print {
 			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);

diff --git a/plugins/jetpack/modules/custom-css/csstidy/data-wp.inc.php b/plugins/jetpack/modules/custom-css/csstidy/data-wp.inc.php
index f39ecbf..de2d0bd 100644
--- a/plugins/jetpack/modules/custom-css/csstidy/data-wp.inc.php
+++ b/plugins/jetpack/modules/custom-css/csstidy/data-wp.inc.php
@@ -51,6 +51,14 @@ $GLOBALS['csstidy']['at_rules']['-moz-keyframes'] = 'at';
 $GLOBALS['csstidy']['at_rules']['-ms-keyframes'] = 'at';
 
 /**
+ * Non-standard viewport rule.
+ */
+$GLOBALS['csstidy']['at_rules']['viewport'] = 'is';
+$GLOBALS['csstidy']['at_rules']['-webkit-viewport'] = 'is';
+$GLOBALS['csstidy']['at_rules']['-moz-viewport'] = 'is';
+$GLOBALS['csstidy']['at_rules']['-ms-viewport'] = 'is';
+
+/**
  * 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.
  */

diff --git a/plugins/jetpack/modules/custom-css/csstidy/data.inc.php b/plugins/jetpack/modules/custom-css/csstidy/data.inc.php
index c085568..dfb576d 100644
--- a/plugins/jetpack/modules/custom-css/csstidy/data.inc.php
+++ b/plugins/jetpack/modules/custom-css/csstidy/data.inc.php
@@ -77,7 +77,7 @@ $GLOBALS['csstidy']['at_rules'] = array('page' => 'is','font-face' => 'is','char
 $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', 
+											'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');
 
 /**
@@ -587,7 +587,7 @@ $GLOBALS['csstidy']['quoted_string_properties'] = array('content', 'font', 'font
  *
  * @global array $GLOBALS['csstidy']['quoted_string_properties']
  */
-$GLOBALS['csstidy']['multiple_properties'] = array_merge( $GLOBALS['csstidy']['unit_values'], array('background', 'background-image', 'transition') );
+$GLOBALS['csstidy']['multiple_properties'] = array_merge( $GLOBALS['csstidy']['color_values'], $GLOBALS['csstidy']['unit_values'], array( 'transition', 'background-image', 'border-image', 'list-style-image' ) );
 
 /**
  * An array containing all predefined templates.

diff --git a/plugins/jetpack/modules/custom-css/csstidy/lang.inc.php b/plugins/jetpack/modules/custom-css/csstidy/lang.inc.php
index 9e6b24b..61f95c7 100644
--- a/plugins/jetpack/modules/custom-css/csstidy/lang.inc.php
+++ b/plugins/jetpack/modules/custom-css/csstidy/lang.inc.php
@@ -16,7 +16,7 @@
  *   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/>.
  *
@@ -128,7 +128,7 @@ $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'][19] = 'Optionen';
 $lang['de'][20] = 'Selektoren sortieren (Vorsicht)';
 $lang['de'][21] = 'Eigenschaften sortieren';
 $lang['de'][22] = 'Selektoren umgruppieren';
@@ -140,7 +140,7 @@ $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'][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';
@@ -271,7 +271,7 @@ $lang['zh'][24] = '壓縮色彩語法';
 $lang['zh'][25] = '改用小寫選擇符';
 $lang['zh'][26] = '屬性的字形:';
 $lang['zh'][27] = '小寫';
-$lang['zh'][28] = '沒有輸入CSS, 語法不符合規定, 或是網址錯誤!'; 
+$lang['zh'][28] = '沒有輸入CSS, 語法不符合規定, 或是網址錯誤!';
 $lang['zh'][29] = '大寫';
 $lang['zh'][30] = 'XHTML必須使用小寫的元素名稱';
 $lang['zh'][31] = '移除不必要的反斜線';

diff --git a/plugins/jetpack/modules/custom-css/custom-css.php b/plugins/jetpack/modules/custom-css/custom-css.php
index 9bc0c21..02fa758 100644
--- a/plugins/jetpack/modules/custom-css/custom-css.php
+++ b/plugins/jetpack/modules/custom-css/custom-css.php
@@ -47,6 +47,8 @@ class Jetpack_Custom_CSS {
 			exit;
 		}
 
+		add_action( 'admin_enqueue_scripts', array( 'Jetpack_Custom_CSS', 'enqueue_scripts' ) );
+
 		if ( isset( $_GET['page'] ) && 'editcss' == $_GET['page'] && is_admin() ) {
 			// Do migration routine if necessary
 			Jetpack_Custom_CSS::upgrade();
@@ -56,6 +58,9 @@ class Jetpack_Custom_CSS {
 
 		add_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
 
+		add_filter( 'jetpack_content_width', array( 'Jetpack_Custom_CSS', 'jetpack_content_width' ) );
+		add_filter( 'editor_max_image_size', array( 'Jetpack_Custom_CSS', 'editor_max_image_size' ), 10, 3 );
+
 		if ( !current_user_can( 'switch_themes' ) && !is_super_admin() )
 			return;
 
@@ -65,7 +70,7 @@ class Jetpack_Custom_CSS {
 			check_admin_referer( 'safecss' );
 
 			$save_result = self::save( array(
-				'css' => $_POST['safecss'],
+				'css' => stripslashes( $_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,
@@ -108,6 +113,11 @@ class Jetpack_Custom_CSS {
 
 		$args = wp_parse_args( $args, $defaults );
 
+		if ( $args['content_width'] && intval( $args['content_width']) > 0 && ( ! isset( $GLOBALS['content_width'] ) || $args['content_width'] != $GLOBALS['content_width'] ) )
+			$args['content_width'] = intval( $args['content_width'] );
+		else
+			$args['content_width'] = false;
+
 		// 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' );
@@ -132,7 +142,7 @@ class Jetpack_Custom_CSS {
 		$csstidy->set_cfg( 'preserve_css',               true );
 		$csstidy->set_cfg( 'template',                   dirname( __FILE__ ) . '/csstidy/wordpress-standard.tpl' );
 
-		$css = $orig = stripslashes( $args['css'] );
+		$css = $orig = $args['css'];
 
 		$css = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $prev = $css );
 
@@ -161,11 +171,6 @@ class Jetpack_Custom_CSS {
 			$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
@@ -179,9 +184,12 @@ class Jetpack_Custom_CSS {
 			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, 'content_width', $args['content_width'] );
 			update_metadata( 'post', $safecss_revision_id, 'custom_css_preprocessor', $args['preprocessor'] );
 
+			delete_option( 'safecss_add' );
+			delete_option( 'safecss_content_width' );
+
 			if ( $args['is_preview'] ) {
 				return $safecss_revision_id;
 			}
@@ -198,12 +206,18 @@ class Jetpack_Custom_CSS {
 		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, 'content_width', $args['content_width'] );
 		update_post_meta( $safecss_post_id, 'custom_css_preprocessor', $args['preprocessor'] );
+
+		delete_option( 'safecss_add' );
+		delete_option( 'safecss_content_width' );
+
 		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'], 'content_width', $args['content_width'] );
 		update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_preprocessor', $args['preprocessor'] );
 
+		delete_option( 'safecss_preview_add' );
+
 		return $safecss_post_id;
 	}
 
@@ -230,16 +244,16 @@ class Jetpack_Custom_CSS {
 		$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(
+			$custom_css_posts = 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;
+			if ( count( $custom_css_posts ) > 0 )
+				$custom_css_post_id = $custom_css_posts[0]->ID;
 			else
 				$custom_css_post_id = 0;
 
@@ -350,19 +364,35 @@ class Jetpack_Custom_CSS {
 	}
 
 	static function skip_stylesheet() {
-		if ( Jetpack_Custom_CSS::is_customizer_preview() ) {
+		$skip_stylesheet = apply_filters( 'safecss_skip_stylesheet', null );
+
+		if ( null !== $skip_stylesheet ) {
+			return $skip_stylesheet;
+		} elseif ( Jetpack_Custom_CSS::is_customizer_preview() ) {
 			return false;
-		}
-		else {
+		} 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' );
+				if ( $safecss_post )
+					return (bool) ( get_post_meta( $safecss_post['ID'], 'custom_css_add', true ) == 'no' );
+				else
+					return (bool) ( get_option( 'safecss_preview_add' ) == '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' ) );
+				if ( $custom_css_post_id ) {
+					$custom_css_add = get_post_meta( $custom_css_post_id, 'custom_css_add', true );
+
+					// It is possible for the CSS to be stored in a post but for the safecss_add option
+					// to have not been upgraded yet if the user hasn't opened their Custom CSS editor
+					// since October 2012.
+					if ( ! empty( $custom_css_add ) )
+						return (bool) ( $custom_css_add === 'no' );
+				}
+
+				return (bool) ( get_option( 'safecss_add' ) == 'no' );
 			}
 		}
 	}
@@ -494,7 +524,7 @@ class Jetpack_Custom_CSS {
 		if ( $css == '' )
 			return;
 
-		$href = trailingslashit( site_url() );
+		$href = home_url( '/' );
 		$href = add_query_arg( 'custom-css', 1, $href );
 		$href = add_query_arg( 'csblog', $blog_id, $href );
 		$href = add_query_arg( 'cscache', 6, $href );
@@ -508,6 +538,8 @@ class Jetpack_Custom_CSS {
 		?>
 		<link rel="stylesheet" id="custom-css-css" type="text/css" href="<?php echo esc_url( $href ); ?>" />
 		<?php
+
+		do_action( 'safecss_link_tag_post' );
 	}
 
 	static function style_filter( $current ) {
@@ -571,7 +603,7 @@ class Jetpack_Custom_CSS {
 		$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' ) );
@@ -588,26 +620,6 @@ class Jetpack_Custom_CSS {
 
 	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 ) {
@@ -626,159 +638,39 @@ class Jetpack_Custom_CSS {
 		return __( 'Custom CSS Stylesheet', 'jetpack' );
 	}
 
-	static function enqueue_scripts() {
+	static function enqueue_scripts( $hook ) {
+		if ( 'appearance_page_editcss' != $hook )
+			return;
+
 		wp_enqueue_script( 'postbox' );
+		wp_enqueue_script( 'custom-css-editor', plugins_url( 'custom-css/js/css-editor.js', __FILE__ ), 'jquery', '20130325', true );
+		wp_enqueue_style( 'custom-css-editor', plugins_url( 'custom-css/css/css-editor.css', __FILE__ ) );
 
 		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-less', $url . 'ace/mode-less.js', array( 'safecss-ace' ), '20130213', true );
+			wp_enqueue_script( 'safecss-ace-scss', $url . 'ace/mode-scss.js', array( 'safecss-ace' ), '20130213', true );
 			wp_enqueue_script( 'safecss-ace-use', $url . 'safecss-ace.js', array( 'jquery', 'safecss-ace-css' ), '20130213', true );
+
+			wp_enqueue_style( 'custom-css-ace', plugins_url( 'custom-css/css/ace.css', __FILE__ ) );
 		}
 	}
 
 	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
-			}
-
+		if ( defined( 'SAFECSS_USE_ACE' ) && SAFECSS_USE_ACE ) {
 			?>
-		</style>
-		<script type="text/javascript">
-			/*<![CDATA[*/
-			var safecssResize, safecssInit;
-
+			<script type="text/javascript">
+				/*<![CDATA[*/
+				var SAFECSS_USE_ACE = true;
+				var safecssAceSrcPath = <?php echo json_encode( parse_url( plugins_url( 'custom-css/js/ace/', __FILE__ ), PHP_URL_PATH ) ); ?>;
+				/*]]>*/
+			</script>
 			<?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() {
@@ -787,12 +679,12 @@ class Jetpack_Custom_CSS {
 
 	static function admin() {
 		add_meta_box( 'submitdiv', __( 'Publish', 'jetpack' ), array( __CLASS__, 'publish_box' ), 'editcss', 'side' );
+		add_action( 'custom_css_submitbox_misc_actions', array( __CLASS__, 'content_width_settings' ) );
 
 		$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' ); ?>
@@ -833,6 +725,103 @@ class Jetpack_Custom_CSS {
 		<?php
 	}
 
+	/**
+	 * Content width setting callback
+	 */
+	static function content_width_settings() {
+		$safecss_post = Jetpack_Custom_CSS::get_current_revision();
+
+		$custom_content_width = get_post_meta( $safecss_post['ID'], 'content_width', true );
+
+		// If custom content width hasn't been overridden and the theme has a content_width value, use that as a default.
+		if ( $custom_content_width <= 0 && ! empty( $GLOBALS['content_width'] ) )
+			$custom_content_width = $GLOBALS['content_width'];
+
+		if ( ! $custom_content_width || ( isset( $GLOBALS['content_width'] ) && $custom_content_width == $GLOBALS['content_width'] ) )
+			$custom_content_width = '';
+
+		?>
+		<div class="misc-pub-section">
+			<label><?php esc_html_e( 'Content Width:', 'jetpack' ); ?></label>
+			<span id="content-width-display" data-default-text="<?php esc_attr_e( 'Default', 'jetpack' ); ?>" data-custom-text="<?php esc_attr_e( '%s px', 'jetpack' ); ?>"><?php echo $custom_content_width ? sprintf( esc_html__( '%s px', 'jetpack' ), $custom_content_width ) : esc_html_e( 'Default', 'jetpack' ); ?></span>
+			<a class="edit-content-width hide-if-no-js" href="#content-width"><?php echo esc_html_e( 'Edit', 'jetpack' ); ?></a>
+			<div id="content-width-select" class="hide-if-js">
+				<input type="hidden" name="custom_content_width" id="custom_content_width" value="<?php echo esc_attr( $custom_content_width ); ?>" />
+				<p>
+					<?php
+
+					printf(
+						__( 'Limit width to %1$s pixels for videos, full size images, and other shortcodes. (<a href="%2$s">More info</a>.)', 'jetpack' ),
+						'<input type="text" id="custom_content_width_visible" value="' . esc_attr( $custom_content_width ) . '" size="4" />',
+						apply_filters( 'safecss_limit_width_link', 'http://jetpack.me/support/custom-css/#limited-width' )
+					);
+
+					?>
+				</p>
+				<?php
+
+				if ( !empty( $GLOBALS['content_width'] ) && $custom_content_width != $GLOBALS['content_width'] ) {
+					if ( function_exists( 'wp_get_theme' ) )
+						$current_theme = wp_get_theme()->Name;
+					else
+						$current_theme = get_current_theme();
+
+					?>
+					<p><?php printf( __( 'The default content width for the %s theme is %d pixels.', 'jetpack' ), $current_theme, intval( $GLOBALS['content_width'] ) ); ?></p>
+					<?php
+				}
+
+				?>
+				<a class="save-content-width hide-if-no-js button" href="#content-width"><?php esc_html_e( 'OK', 'jetpack' ); ?></a>
+				<a class="cancel-content-width hide-if-no-js" href="#content-width"><?php esc_html_e( 'Cancel', 'jetpack' ); ?></a>
+			</div>
+			<script type="text/javascript">
+				jQuery( function ( $ ) {
+					var defaultContentWidth = <?php echo isset( $GLOBALS['content_width'] ) ? json_encode( intval( $GLOBALS['content_width'] ) ) : 0; ?>;
+
+					$( '.edit-content-width' ).bind( 'click', function ( e ) {
+						e.preventDefault();
+
+						$( '#content-width-select' ).slideDown();
+						$( this ).hide();
+					} );
+
+					$( '.cancel-content-width' ).bind( 'click', function ( e ) {
+						e.preventDefault();
+
+						$( '#content-width-select' ).slideUp( function () {
+							$( '.edit-content-width' ).show();
+							$( '#custom_content_width_visible' ).val( $( '#custom_content_width' ).val() );
+						} );
+					} );
+
+					$( '.save-content-width' ).bind( 'click', function ( e ) {
+						e.preventDefault();
+
+						$( '#content-width-select' ).slideUp();
+
+						var newContentWidth = parseInt( $( '#custom_content_width_visible' ).val(), 10 );
+
+						if ( newContentWidth && newContentWidth != defaultContentWidth ) {
+							$( '#content-width-display' ).text(
+								$( '#content-width-display' )
+									.data( 'custom-text' )
+										.replace( '%s', $( '#custom_content_width_visible' ).val() )
+							);
+						}
+						else {
+							$( '#content-width-display' ).text( $( '#content-width-display' ).data( 'default-text' ) );
+						}
+
+						$( '#custom_content_width' ).val( $( '#custom_content_width_visible' ).val() );
+						$( '.edit-content-width' ).show();
+					} );
+				} );
+			</script>
+		</div>
+		<?php
+	}
+
 	static function publish_box() {
 		?>
 		<div id="minor-publishing">
@@ -897,34 +886,6 @@ class Jetpack_Custom_CSS {
 						<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>
@@ -1012,9 +973,15 @@ class Jetpack_Custom_CSS {
 		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', '' );
+
+		delete_option( 'safecss_add' );
+		delete_option( 'safecss_content_width' );
+
 		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', '' );
+
+		delete_option( 'safecss_preview_add' );
 	}
 
 	static function is_customizer_preview() {
@@ -1072,9 +1039,15 @@ class Jetpack_Custom_CSS {
 		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 );
+
+		delete_option( 'safecss_add' );
+		delete_option( 'safecss_content_width' );
+
 		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 );
+
+		delete_option( 'safecss_preview_add' );
 	}
 
 	/**
@@ -1194,6 +1167,40 @@ class Jetpack_Custom_CSS {
 
 		return esc_url_raw( $post_link );
 	}
+
+	/**
+	 * When on the edit screen, make sure the custom content width
+	 * setting is applied to the large image size.
+	 */
+	static function editor_max_image_size( $dims, $size = 'medium', $context = null ) {
+		list( $width, $height ) = $dims;
+
+		if ( 'large' == $size && 'edit' == $context )
+			$width = Jetpack::get_content_width();
+
+		return array( $width, $height );
+	}
+
+	/**
+	 * Override the content_width with a custom value if one is set.
+	 */
+	static function jetpack_content_width( $content_width ) {
+		$custom_content_width = 0;
+
+		if ( Jetpack_Custom_CSS::is_preview() ) {
+			$safecss_post = Jetpack_Custom_CSS::get_current_revision();
+			$custom_content_width = intval( get_post_meta( $safecss_post['ID'], 'content_width', true ) );
+		} else if ( ! Jetpack_Custom_CSS::is_freetrial() ) {
+			$custom_css_post_id = Jetpack_Custom_CSS::post_id();
+			if ( $custom_css_post_id )
+				$custom_content_width = intval( get_post_meta( $custom_css_post_id, 'content_width', true ) );
+		}
+
+		if ( $custom_content_width > 0 )
+			$content_width = $custom_content_width;
+
+		return $content_width;
+	}
 }
 
 class Jetpack_Safe_CSS {

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
index 520b8fc..375915b 100644
--- a/plugins/jetpack/modules/custom-css/custom-css/js/ace/ace.js
+++ b/plugins/jetpack/modules/custom-css/custom-css/js/ace/ace.js
@@ -8,4 +8,3 @@
                         ace[key] = a[key];
                 });
             })();
-        
\ 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
index 59ceeaf..54c2a3e 100644
--- 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
@@ -1 +1,7886 @@
-"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.ge
 tOwnPropertyDescriptor=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(fun
 ction(){})}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)D
 ate.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;re
 turn 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\v\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.addEventListe
 ner=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.stri
 ngReverse=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.defer
 redUpdate=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.getAllL
 ines().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.le
 ngth},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())retu
 rn 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=fun
 ction(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.star
 t.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.colum
 n,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.$clipPositionT
 oDocument=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.crea
 teTokenData=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}funct
 ion 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=C
 olors[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 is
 NameStart(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",lig
 htgreen:"#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",saddlebrow
 n:"#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 EventTa
 rget,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_S
 YM)&&(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.mu
 stMatch(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._tok
 enStream,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.BOTTOMRIGHT
 CORNER_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._tokenSt
 ream;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._ne
 gation],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:"p
 roperty",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._readWh
 itespace()&&(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._r
 eadWhitespace(),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},parseStyleAttribut
 e: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:"n
 ormal | 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||ValidationType
 s.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:"<lengt
 h> | <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","bord
 er-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-b
 efore":"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 | tab
 le-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-pu
 nctuation":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 | hi
 dden | 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",rotat
 ion: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":"<in
 teger> | 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._mark
 s.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.createTok
 en(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&&isWhitespa
 ce(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:"TOPR
 IGHT_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:"DO
 T",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;whi
 le(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=="ident
 ifier"},"<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.roll
 up?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.add
 Listener("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){functi
 on 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.p
 ropCount==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=t
 his;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
+"no use strict";
+
+if (typeof window != "undefined" && window.document)
+    throw "atempt to load ace worker into main window instead of webWorker";
+
+var console = {
+    log: function() {
+        var msgs = Array.prototype.slice.call(arguments, 0);
+        postMessage({type: "log", data: msgs});
+    },
+    error: function() {
+        var msgs = Array.prototype.slice.call(arguments, 0);
+        postMessage({type: "log", data: msgs});
+    }
+};
+var window = {
+    console: console
+};
+
+var normalizeModule = function(parentId, moduleName) {
+    // normalize plugin requires
+    if (moduleName.indexOf("!") !== -1) {
+        var chunks = moduleName.split("!");
+        return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
+    }
+    // normalize relative requires
+    if (moduleName.charAt(0) == ".") {
+        var base = parentId.split("/").slice(0, -1).join("/");
+        moduleName = base + "/" + moduleName;
+
+        while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
+            var previous = moduleName;
+            moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
+        }
+    }
+
+    return moduleName;
+};
+
+var require = function(parentId, id) {
+    if (!id.charAt)
+        throw new Error("worker.js require() accepts only (parentId, id) as arguments");
+
+    id = normalizeModule(parentId, id);
+
+    var module = require.modules[id];
+    if (module) {
+        if (!module.initialized) {
+            module.initialized = true;
+            module.exports = module.factory().exports;
+        }
+        return module.exports;
+    }
+
+    var chunks = id.split("/");
+    chunks[0] = require.tlns[chunks[0]] || chunks[0];
+    var path = chunks.join("/") + ".js";
+
+    require.id = id;
+    importScripts(path);
+    return require(parentId, id);
+};
+
+require.modules = {};
+require.tlns = {};
+
+var define = function(id, deps, factory) {
+    if (arguments.length == 2) {
+        factory = deps;
+        if (typeof id != "string") {
+            deps = id;
+            id = require.id;
+        }
+    } else if (arguments.length == 1) {
+        factory = id;
+        id = require.id;
+    }
+
+    if (id.indexOf("text!") === 0)
+        return;
+
+    var req = function(deps, factory) {
+        return require(id, deps, factory);
+    };
+
+    require.modules[id] = {
+        factory: function() {
+            var module = {
+                exports: {}
+            };
+            var returnExports = factory(req, module.exports, module);
+            if (returnExports)
+                module.exports = returnExports;
+            return module;
+        }
+    };
+};
+
+function initBaseUrls(topLevelNamespaces) {
+    require.tlns = topLevelNamespaces;
+}
+
+function initSender() {
+
+    var EventEmitter = require(null, "ace/lib/event_emitter").EventEmitter;
+    var oop = require(null, "ace/lib/oop");
+
+    var Sender = function() {};
+
+    (function() {
+
+        oop.implement(this, EventEmitter);
+
+        this.callback = function(data, callbackId) {
+            postMessage({
+                type: "call",
+                id: callbackId,
+                data: data
+            });
+        };
+
+        this.emit = function(name, data) {
+            postMessage({
+                type: "event",
+                name: name,
+                data: data
+            });
+        };
+
+    }).call(Sender.prototype);
+
+    return new Sender();
+}
+
+var main;
+var sender;
+
+onmessage = function(e) {
+    var msg = e.data;
+    if (msg.command) {
+        if (main[msg.command])
+            main[msg.command].apply(main, msg.args);
+        else
+            throw new Error("Unknown command:" + msg.command);
+    }
+    else if (msg.init) {
+        initBaseUrls(msg.tlns);
+        require(null, "ace/lib/fixoldbrowsers");
+        sender = initSender();
+        var clazz = require(null, msg.module)[msg.classname];
+        main = new clazz(sender);
+    }
+    else if (msg.event && sender) {
+        sender._emit(msg.event, msg.data);
+    }
+};
+// vim:set ts=4 sts=4 sw=4 st:
+
+define('ace/lib/fixoldbrowsers', ['require', 'exports', 'module' , 'ace/lib/regexp', 'ace/lib/es5-shim'], function(require, exports, module) {
+
+
+require("./regexp");
+require("./es5-shim");
+
+});
+
+define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+    var real = {
+            exec: RegExp.prototype.exec,
+            test: RegExp.prototype.test,
+            match: String.prototype.match,
+            replace: String.prototype.replace,
+            split: String.prototype.split
+        },
+        compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups
+        compliantLastIndexIncrement = function () {
+            var x = /^/g;
+            real.test.call(x, "");
+            return !x.lastIndex;
+        }();
+
+    if (compliantLastIndexIncrement && compliantExecNpcg)
+        return;
+    RegExp.prototype.exec = function (str) {
+        var match = real.exec.apply(this, arguments),
+            name, r2;
+        if ( typeof(str) == 'string' && match) {
+            if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
+                r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", ""));
+                real.replace.call(str.slice(match.index), r2, function () {
+                    for (var i = 1; i < arguments.length - 2; i++) {
+                        if (arguments[i] === undefined)
+                            match[i] = undefined;
+                    }
+                });
+            }
+            if (this._xregexp && this._xregexp.captureNames) {
+                for (var i = 1; i < match.length; i++) {
+                    name = this._xregexp.captureNames[i - 1];
+                    if (name)
+                       match[name] = match[i];
+                }
+            }
+            if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
+                this.lastIndex--;
+        }
+        return match;
+    };
+    if (!compliantLastIndexIncrement) {
+        RegExp.prototype.test = function (str) {
+            var match = real.exec.call(this, str);
+            if (match && this.global && !match[0].length && (this.lastIndex > match.index))
+                this.lastIndex--;
+            return !!match;
+        };
+    }
+
+    function getNativeFlags (regex) {
+        return (regex.global     ? "g" : "") +
+               (regex.ignoreCase ? "i" : "") +
+               (regex.multiline  ? "m" : "") +
+               (regex.extended   ? "x" : "") + // Proposed for ES4; included in AS3
+               (regex.sticky     ? "y" : "");
+    }
+
+    function indexOf (array, item, from) {
+        if (Array.prototype.indexOf) // Use the native array method if available
+            return array.indexOf(item, from);
+        for (var i = from || 0; i < array.length; i++) {
+            if (array[i] === item)
+                return i;
+        }
+        return -1;
+    }
+
+});
+
+define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+function Empty() {}
+
+if (!Function.prototype.bind) {
+    Function.prototype.bind = function bind(that) { // .length is 1
+        var target = this;
+        if (typeof target != "function") {
+            throw new TypeError("Function.prototype.bind called on incompatible " + target);
+        }
+        var args = slice.call(arguments, 1); // for normal call
+        var bound = function () {
+
+            if (this instanceof bound) {
+
+                var result = target.apply(
+                    this,
+                    args.concat(slice.call(arguments))
+                );
+                if (Object(result) === result) {
+                    return result;
+                }
+                return this;
+
+            } else {
+                return target.apply(
+                    that,
+                    args.concat(slice.call(arguments))
+                );
+
+            }
+
+        };
+        if(target.prototype) {
+            Empty.prototype = target.prototype;
+            bound.prototype = new Empty();
+            Empty.prototype = null;
+        }
+        return bound;
+    };
+}
+var call = Function.prototype.call;
+var prototypeOfArray = Array.prototype;
+var prototypeOfObject = Object.prototype;
+var slice = prototypeOfArray.slice;
+var _toString = call.bind(prototypeOfObject.toString);
+var owns = call.bind(prototypeOfObject.hasOwnProperty);
+var defineGetter;
+var defineSetter;
+var lookupGetter;
+var lookupSetter;
+var supportsAccessors;
+if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
+    defineGetter = call.bind(prototypeOfObject.__defineGetter__);
+    defineSetter = call.bind(prototypeOfObject.__defineSetter__);
+    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
+    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
+}
+if ([1,2].splice(0).length != 2) {
+    if(function() { // test IE < 9 to splice bug - see issue #138
+        function makeArray(l) {
+            var a = new Array(l+2);
+            a[0] = a[1] = 0;
+            return a;
+        }
+        var array = [], lengthBefore;
+
+        array.splice.apply(array, makeArray(20));
+        array.splice.apply(array, makeArray(26));
+
+        lengthBefore = array.length; //46
+        array.splice(5, 0, "XXX"); // add one element
+
+        lengthBefore + 1 == array.length
+
+        if (lengthBefore + 1 == array.length) {
+            return true;// has right splice implementation without bugs
+        }
+    }()) {//IE 6/7
+        var array_splice = Array.prototype.splice;
+        Array.prototype.splice = function(start, deleteCount) {
+            if (!arguments.length) {
+                return [];
+            } else {
+                return array_splice.apply(this, [
+                    start === void 0 ? 0 : start,
+                    deleteCount === void 0 ? (this.length - start) : deleteCount
+                ].concat(slice.call(arguments, 2)))
+            }
+        };
+    } else {//IE8
+        Array.prototype.splice = function(pos, removeCount){
+            var length = this.length;
+            if (pos > 0) {
+                if (pos > length)
+                    pos = length;
+            } else if (pos == void 0) {
+                pos = 0;
+            } else if (pos < 0) {
+                pos = Math.max(length + pos, 0);
+            }
+
+            if (!(pos+removeCount < length))
+                removeCount = length - pos;
+
+            var removed = this.slice(pos, pos+removeCount);
+            var insert = slice.call(arguments, 2);
+            var add = insert.length;
+            if (pos === length) {
+                if (add) {
+                    this.push.apply(this, insert);
+                }
+            } else {
+                var remove = Math.min(removeCount, length - pos);
+                var tailOldPos = pos + remove;
+                var tailNewPos = tailOldPos + add - remove;
+                var tailCount = length - tailOldPos;
+                var lengthAfterRemove = length - remove;
+
+                if (tailNewPos < tailOldPos) { // case A
+                    for (var i = 0; i < tailCount; ++i) {
+                        this[tailNewPos+i] = this[tailOldPos+i];
+                    }
+                } else if (tailNewPos > tailOldPos) { // case B
+                    for (i = tailCount; i--; ) {
+                        this[tailNewPos+i] = this[tailOldPos+i];
+                    }
+                } // else, add == remove (nothing to do)
+
+                if (add && pos === lengthAfterRemove) {
+                    this.length = lengthAfterRemove; // truncate array
+                    this.push.apply(this, insert);
+                } else {
+                    this.length = lengthAfterRemove + add; // reserves space
+                    for (i = 0; i < add; ++i) {
+                        this[pos+i] = insert[i];
+                    }
+                }
+            }
+            return removed;
+        };
+    }
+}
+if (!Array.isArray) {
+    Array.isArray = function isArray(obj) {
+        return _toString(obj) == "[object Array]";
+    };
+}
+var boxedString = Object("a"),
+    splitString = boxedString[0] != "a" || !(0 in boxedString);
+
+if (!Array.prototype.forEach) {
+    Array.prototype.forEach = function forEach(fun /*, thisp*/) {
+        var object = toObject(this),
+            self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                object,
+            thisp = arguments[1],
+            i = -1,
+            length = self.length >>> 0;
+        if (_toString(fun) != "[object Function]") {
+            throw new TypeError(); // TODO message
+        }
+
+        while (++i < length) {
+            if (i in self) {
+                fun.call(thisp, self[i], i, object);
+            }
+        }
+    };
+}
+if (!Array.prototype.map) {
+    Array.prototype.map = function map(fun /*, thisp*/) {
+        var object = toObject(this),
+            self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                object,
+            length = self.length >>> 0,
+            result = Array(length),
+            thisp = arguments[1];
+        if (_toString(fun) != "[object Function]") {
+            throw new TypeError(fun + " is not a function");
+        }
+
+        for (var i = 0; i < length; i++) {
+            if (i in self)
+                result[i] = fun.call(thisp, self[i], i, object);
+        }
+        return result;
+    };
+}
+if (!Array.prototype.filter) {
+    Array.prototype.filter = function filter(fun /*, thisp */) {
+        var object = toObject(this),
+            self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                    object,
+            length = self.length >>> 0,
+            result = [],
+            value,
+            thisp = arguments[1];
+        if (_toString(fun) != "[object Function]") {
+            throw new TypeError(fun + " is not a function");
+        }
+
+        for (var i = 0; i < length; i++) {
+            if (i in self) {
+                value = self[i];
+                if (fun.call(thisp, value, i, object)) {
+                    result.push(value);
+                }
+            }
+        }
+        return result;
+    };
+}
+if (!Array.prototype.every) {
+    Array.prototype.every = function every(fun /*, thisp */) {
+        var object = toObject(this),
+            self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                object,
+            length = self.length >>> 0,
+            thisp = arguments[1];
+        if (_toString(fun) != "[object Function]") {
+            throw new TypeError(fun + " is not a function");
+        }
+
+        for (var i = 0; i < length; i++) {
+            if (i in self && !fun.call(thisp, self[i], i, object)) {
+                return false;
+            }
+        }
+        return true;
+    };
+}
+if (!Array.prototype.some) {
+    Array.prototype.some = function some(fun /*, thisp */) {
+        var object = toObject(this),
+            self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                object,
+            length = self.length >>> 0,
+            thisp = arguments[1];
+        if (_toString(fun) != "[object Function]") {
+            throw new TypeError(fun + " is not a function");
+        }
+
+        for (var i = 0; i < length; i++) {
+            if (i in self && fun.call(thisp, self[i], i, object)) {
+                return true;
+            }
+        }
+        return false;
+    };
+}
+if (!Array.prototype.reduce) {
+    Array.prototype.reduce = function reduce(fun /*, initial*/) {
+        var object = toObject(this),
+            self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                object,
+            length = self.length >>> 0;
+        if (_toString(fun) != "[object Function]") {
+            throw new TypeError(fun + " is not a function");
+        }
+        if (!length && arguments.length == 1) {
+            throw new TypeError("reduce of empty array with no initial value");
+        }
+
+        var i = 0;
+        var result;
+        if (arguments.length >= 2) {
+            result = arguments[1];
+        } else {
+            do {
+                if (i in self) {
+                    result = self[i++];
+                    break;
+                }
+                if (++i >= length) {
+                    throw new TypeError("reduce of empty array with no initial value");
+                }
+            } while (true);
+        }
+
+        for (; i < length; i++) {
+            if (i in self) {
+                result = fun.call(void 0, result, self[i], i, object);
+            }
+        }
+
+        return result;
+    };
+}
+if (!Array.prototype.reduceRight) {
+    Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
+        var object = toObject(this),
+            self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                object,
+            length = self.length >>> 0;
+        if (_toString(fun) != "[object Function]") {
+            throw new TypeError(fun + " is not a function");
+        }
+        if (!length && arguments.length == 1) {
+            throw new TypeError("reduceRight of empty array with no initial value");
+        }
+
+        var result, i = length - 1;
+        if (arguments.length >= 2) {
+            result = arguments[1];
+        } else {
+            do {
+                if (i in self) {
+                    result = self[i--];
+                    break;
+                }
+                if (--i < 0) {
+                    throw new TypeError("reduceRight of empty array with no initial value");
+                }
+            } while (true);
+        }
+
+        do {
+            if (i in this) {
+                result = fun.call(void 0, result, self[i], i, object);
+            }
+        } while (i--);
+
+        return result;
+    };
+}
+if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) {
+    Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
+        var self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                toObject(this),
+            length = self.length >>> 0;
+
+        if (!length) {
+            return -1;
+        }
+
+        var i = 0;
+        if (arguments.length > 1) {
+            i = toInteger(arguments[1]);
+        }
+        i = i >= 0 ? i : Math.max(0, length + i);
+        for (; i < length; i++) {
+            if (i in self && self[i] === sought) {
+                return i;
+            }
+        }
+        return -1;
+    };
+}
+if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) {
+    Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
+        var self = splitString && _toString(this) == "[object String]" ?
+                this.split("") :
+                toObject(this),
+            length = self.length >>> 0;
+
+        if (!length) {
+            return -1;
+        }
+        var i = length - 1;
+        if (arguments.length > 1) {
+            i = Math.min(i, toInteger(arguments[1]));
+        }
+        i = i >= 0 ? i : length - Math.abs(i);
+        for (; i >= 0; i--) {
+            if (i in self && sought === self[i]) {
+                return i;
+            }
+        }
+        return -1;
+    };
+}
+if (!Object.getPrototypeOf) {
+    Object.getPrototypeOf = function getPrototypeOf(object) {
+        return object.__proto__ || (
+            object.constructor ?
+            object.constructor.prototype :
+            prototypeOfObject
+        );
+    };
+}
+if (!Object.getOwnPropertyDescriptor) {
+    var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " +
+                         "non-object: ";
+    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
+        if ((typeof object != "object" && typeof object != "function") || object === null)
+            throw new TypeError(ERR_NON_OBJECT + object);
+        if (!owns(object, property))
+            return;
+
+        var descriptor, getter, setter;
+        descriptor =  { enumerable: true, configurable: true };
+        if (supportsAccessors) {
+            var prototype = object.__proto__;
+            object.__proto__ = prototypeOfObject;
+
+            var getter = lookupGetter(object, property);
+            var setter = lookupSetter(object, property);
+            object.__proto__ = prototype;
+
+            if (getter || setter) {
+                if (getter) descriptor.get = getter;
+                if (setter) descriptor.set = setter;
+                return descriptor;
+            }
+        }
+        descriptor.value = object[property];
+        return descriptor;
+    };
+}
+if (!Object.getOwnPropertyNames) {
+    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
+        return Object.keys(object);
+    };
+}
+if (!Object.create) {
+    var createEmpty;
+    if (Object.prototype.__proto__ === null) {
+        createEmpty = function () {
+            return { "__proto__": null };
+        };
+    } else {
+        createEmpty = function () {
+            var empty = {};
+            for (var i in empty)
+                empty[i] = null;
+            empty.constructor =
+            empty.hasOwnProperty =
+            empty.propertyIsEnumerable =
+            empty.isPrototypeOf =
+            empty.toLocaleString =
+            empty.toString =
+            empty.valueOf =
+            empty.__proto__ = null;
+            return empty;
+        }
+    }
+
+    Object.create = function create(prototype, properties) {
+        var object;
+        if (prototype === null) {
+            object = createEmpty();
+        } else {
+            if (typeof prototype != "object")
+                throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
+            var Type = function () {};
+            Type.prototype = prototype;
+            object = new Type();
+            object.__proto__ = prototype;
+        }
+        if (properties !== void 0)
+            Object.defineProperties(object, properties);
+        return object;
+    };
+}
+
+function doesDefinePropertyWork(object) {
+    try {
+        Object.defineProperty(object, "sentinel", {});
+        return "sentinel" in object;
+    } catch (exception) {
+    }
+}
+if (Object.defineProperty) {
+    var definePropertyWorksOnObject = doesDefinePropertyWork({});
+    var definePropertyWorksOnDom = typeof document == "undefined" ||
+        doesDefinePropertyWork(document.createElement("div"));
+    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
+        var definePropertyFallback = Object.defineProperty;
+    }
+}
+
+if (!Object.defineProperty || definePropertyFallback) {
+    var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
+    var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
+    var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
+                                      "on this javascript engine";
+
+    Object.defineProperty = function defineProperty(object, property, descriptor) {
+        if ((typeof object != "object" && typeof object != "function") || object === null)
+            throw new TypeError(ERR_NON_OBJECT_TARGET + object);
+        if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null)
+            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
+        if (definePropertyFallback) {
+            try {
+                return definePropertyFallback.call(Object, object, property, descriptor);
+            } catch (exception) {
+            }
+        }
+        if (owns(descriptor, "value")) {
+
+            if (supportsAccessors && (lookupGetter(object, property) ||
+                                      lookupSetter(object, property)))
+            {
+                var prototype = object.__proto__;
+                object.__proto__ = prototypeOfObject;
+                delete object[property];
+                object[property] = descriptor.value;
+                object.__proto__ = prototype;
+            } else {
+                object[property] = descriptor.value;
+            }
+        } else {
+            if (!supportsAccessors)
+                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
+            if (owns(descriptor, "get"))
+                defineGetter(object, property, descriptor.get);
+            if (owns(descriptor, "set"))
+                defineSetter(object, property, descriptor.set);
+        }
+
+        return object;
+    };
+}
+if (!Object.defineProperties) {
+    Object.defineProperties = function defineProperties(object, properties) {
+        for (var property in properties) {
+            if (owns(properties, property))
+                Object.defineProperty(object, property, properties[property]);
+        }
+        return object;
+    };
+}
+if (!Object.seal) {
+    Object.seal = function seal(object) {
+        return object;
+    };
+}
+if (!Object.freeze) {
+    Object.freeze = function freeze(object) {
+        return object;
+    };
+}
+try {
+    Object.freeze(function () {});
+} catch (exception) {
+    Object.freeze = (function freeze(freezeObject) {
+        return function freeze(object) {
+            if (typeof object == "function") {
+                return object;
+            } else {
+                return freezeObject(object);
+            }
+        };
+    })(Object.freeze);
+}
+if (!Object.preventExtensions) {
+    Object.preventExtensions = function preventExtensions(object) {
+        return object;
+    };
+}
+if (!Object.isSealed) {
+    Object.isSealed = function isSealed(object) {
+        return false;
+    };
+}
+if (!Object.isFrozen) {
+    Object.isFrozen = function isFrozen(object) {
+        return false;
+    };
+}
+if (!Object.isExtensible) {
+    Object.isExtensible = function isExtensible(object) {
+        if (Object(object) === object) {
+            throw new TypeError(); // TODO message
+        }
+        var name = '';
+        while (owns(object, name)) {
+            name += '?';
+        }
+        object[name] = true;
+        var returnValue = owns(object, name);
+        delete object[name];
+        return returnValue;
+    };
+}
+if (!Object.keys) {
+    var hasDontEnumBug = true,
+        dontEnums = [
+            "toString",
+            "toLocaleString",
+            "valueOf",
+            "hasOwnProperty",
+            "isPrototypeOf",
+            "propertyIsEnumerable",
+            "constructor"
+        ],
+        dontEnumsLength = dontEnums.length;
+
+    for (var key in {"toString": null}) {
+        hasDontEnumBug = false;
+    }
+
+    Object.keys = function keys(object) {
+
+        if (
+            (typeof object != "object" && typeof object != "function") ||
+            object === null
+        ) {
+            throw new TypeError("Object.keys called on a non-object");
+        }
+
+        var keys = [];
+        for (var name in object) {
+            if (owns(object, name)) {
+                keys.push(name);
+            }
+        }
+
+        if (hasDontEnumBug) {
+            for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
+                var dontEnum = dontEnums[i];
+                if (owns(object, dontEnum)) {
+                    keys.push(dontEnum);
+                }
+            }
+        }
+        return keys;
+    };
+
+}
+if (!Date.now) {
+    Date.now = function now() {
+        return new Date().getTime();
+    };
+}
+if("0".split(void 0, 0).length) {
+    var string_split = String.prototype.split;
+    String.prototype.split = function(separator, limit) {
+        if(separator === void 0 && limit === 0)return [];
+        return string_split.apply(this, arguments);
+    }
+}
+if("".substr && "0b".substr(-1) !== "b") {
+    var string_substr = String.prototype.substr;
+    String.prototype.substr = function(start, length) {
+        return string_substr.call(
+            this,
+            start < 0 ? (start = this.length + start) < 0 ? 0 : start : start,
+            length
+        );
+    }
+}
+var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
+    "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
+    "\u2029\uFEFF";
+if (!String.prototype.trim || ws.trim()) {
+    ws = "[" + ws + "]";
+    var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
+        trimEndRegexp = new RegExp(ws + ws + "*$");
+    String.prototype.trim = function trim() {
+        if (this === undefined || this === null) {
+            throw new TypeError("can't convert "+this+" to object");
+        }
+        return String(this)
+            .replace(trimBeginRegexp, "")
+            .replace(trimEndRegexp, "");
+    };
+}
+
+function toInteger(n) {
+    n = +n;
+    if (n !== n) { // isNaN
+        n = 0;
+    } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) {
+        n = (n > 0 || -1) * Math.floor(Math.abs(n));
+    }
+    return n;
+}
+
+function isPrimitive(input) {
+    var type = typeof input;
+    return (
+        input === null ||
+        type === "undefined" ||
+        type === "boolean" ||
+        type === "number" ||
+        type === "string"
+    );
+}
+
+function toPrimitive(input) {
+    var val, valueOf, toString;
+    if (isPrimitive(input)) {
+        return input;
+    }
+    valueOf = input.valueOf;
+    if (typeof valueOf === "function") {
+        val = valueOf.call(input);
+        if (isPrimitive(val)) {
+            return val;
+        }
+    }
+    toString = input.toString;
+    if (typeof toString === "function") {
+        val = toString.call(input);
+        if (isPrimitive(val)) {
+            return val;
+        }
+    }
+    throw new TypeError();
+}
+var toObject = function (o) {
+    if (o == null) { // this matches both null and undefined
+        throw new TypeError("can't convert "+o+" to object");
+    }
+    return Object(o);
+};
+
+});
+
+define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+
+var EventEmitter = {};
+
+EventEmitter._emit =
+EventEmitter._dispatchEvent = function(eventName, e) {
+    this._eventRegistry = this._eventRegistry || {};
+    this._defaultHandlers = this._defaultHandlers || {};
+
+    var listeners = this._eventRegistry[eventName] || [];
+    var defaultHandler = this._defaultHandlers[eventName];
+    if (!listeners.length && !defaultHandler)
+        return;
+
+    if (typeof e != "object" || !e)
+        e = {};
+
+    if (!e.type)
+        e.type = eventName;
+
+    if (!e.stopPropagation) {
+        e.stopPropagation = function() {
+            this.propagationStopped = true;
+        };
+    }
+
+    if (!e.preventDefault) {
+        e.preventDefault = function() {
+            this.defaultPrevented = true;
+        };
+    }
+
+    for (var i=0; i<listeners.length; i++) {
+        listeners[i](e);
+        if (e.propagationStopped)
+            break;
+    }
+
+    if (defaultHandler && !e.defaultPrevented)
+        return defaultHandler(e);
+};
+
+EventEmitter.setDefaultHandler = function(eventName, callback) {
+    this._defaultHandlers = this._defaultHandlers || {};
+
+    if (this._defaultHandlers[eventName])
+        throw new Error("The default handler for '" + eventName + "' is already set");
+
+    this._defaultHandlers[eventName] = callback;
+};
+
+EventEmitter.on =
+EventEmitter.addEventListener = function(eventName, callback) {
+    this._eventRegistry = this._eventRegistry || {};
+
+    var listeners = this._eventRegistry[eventName];
+    if (!listeners)
+        listeners = this._eventRegistry[eventName] = [];
+
+    if (listeners.indexOf(callback) == -1)
+        listeners.push(callback);
+};
+
+EventEmitter.removeListener =
+EventEmitter.removeEventListener = function(eventName, callback) {
+    this._eventRegistry = this._eventRegistry || {};
+
+    var listeners = this._eventRegistry[eventName];
+    if (!listeners)
+        return;
+
+    var index = listeners.indexOf(callback);
+    if (index !== -1)
+        listeners.splice(index, 1);
+};
+
+EventEmitter.removeAllListeners = function(eventName) {
+    if (this._eventRegistry) this._eventRegistry[eventName] = [];
+};
+
+exports.EventEmitter = EventEmitter;
+
+});
+
+define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+
+exports.inherits = (function() {
+    var tempCtor = function() {};
+    return function(ctor, superCtor) {
+        tempCtor.prototype = superCtor.prototype;
+        ctor.super_ = superCtor.prototype;
+        ctor.prototype = new tempCtor();
+        ctor.prototype.constructor = ctor;
+    };
+}());
+
+exports.mixin = function(obj, mixin) {
+    for (var key in mixin) {
+        obj[key] = mixin[key];
+    }
+};
+
+exports.implement = function(proto, mixin) {
+    exports.mixin(proto, mixin);
+};
+
+});
+
+define('ace/mode/css_worker', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/worker/mirror', 'ace/mode/css/csslint'], function(require, exports, module) {
+
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var Mirror = require("../worker/mirror").Mirror;
+var CSSLint = require("./css/csslint").CSSLint;
+
+var Worker = exports.Worker = function(sender) {
+    Mirror.call(this, sender);
+    this.setTimeout(400);
+    this.ruleset = null;
+    this.setDisabledRules("ids");
+    this.setInfoRules("adjoining-classes|qualified-headings|zero-units|gradients|import|outline-none");
+};
+
+oop.inherits(Worker, Mirror);
+
+(function() {
+    this.setInfoRules = function(ruleNames) {
+        if (typeof ruleNames == "string")
+            ruleNames = ruleNames.split("|");
+        this.infoRules = lang.arrayToMap(ruleNames);
+        this.doc.getValue() && this.deferredUpdate.schedule(100);
+    };
+
+    this.setDisabledRules = function(ruleNames) {
+        if (!ruleNames) {
+            this.ruleset = null;
+        } else {
+            if (typeof ruleNames == "string")
+                ruleNames = ruleNames.split("|");
+            var all = {};
+
+            CSSLint.getRules().forEach(function(x){
+                all[x.id] = true;
+            });
+            ruleNames.forEach(function(x) {
+                delete all[x];
+            });
+
+            this.ruleset = all;
+        }
+        this.doc.getValue() && this.deferredUpdate.schedule(100);
+    };
+
+    this.onUpdate = function() {
+        var value = this.doc.getValue();
+        var infoRules = this.infoRules;
+
+        var result = CSSLint.verify(value, this.ruleset);
+        this.sender.emit("csslint", result.messages.map(function(msg) {
+            return {
+                row: msg.line - 1,
+                column: msg.col - 1,
+                text: msg.message,
+                type: infoRules[msg.rule.id] ? "info" : msg.type
+            }
+        }));
+    };
+
+}).call(Worker.prototype);
+
+});
+
+define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+
+exports.stringReverse = function(string) {
+    return string.split("").reverse().join("");
+};
+
+exports.stringRepeat = function (string, count) {
+    var result = '';
+    while (count > 0) {
+        if (count & 1)
+            result += string;
+
+        if (count >>= 1)
+            string += string;
+    }
+    return result;
+};
+
+var trimBeginRegexp = /^\s\s*/;
+var trimEndRegexp = /\s\s*$/;
+
+exports.stringTrimLeft = function (string) {
+    return string.replace(trimBeginRegexp, '');
+};
+
+exports.stringTrimRight = function (string) {
+    return string.replace(trimEndRegexp, '');
+};
+
+exports.copyObject = function(obj) {
+    var copy = {};
+    for (var key in obj) {
+        copy[key] = obj[key];
+    }
+    return copy;
+};
+
+exports.copyArray = function(array){
+    var copy = [];
+    for (var i=0, l=array.length; i<l; i++) {
+        if (array[i] && typeof array[i] == "object")
+            copy[i] = this.copyObject( array[i] );
+        else
+            copy[i] = array[i];
+    }
+    return copy;
+};
+
+exports.deepCopy = function (obj) {
+    if (typeof obj != "object") {
+        return obj;
+    }
+
+    var copy = obj.constructor();
+    for (var key in obj) {
+        if (typeof obj[key] == "object") {
+            copy[key] = this.deepCopy(obj[key]);
+        } else {
+            copy[key] = obj[key];
+        }
+    }
+    return copy;
+};
+
+exports.arrayToMap = function(arr) {
+    var map = {};
+    for (var i=0; i<arr.length; i++) {
+        map[arr[i]] = 1;
+    }
+    return map;
+
+};
+
+exports.createMap = function(props) {
+    var map = Object.create(null);
+    for (var i in props) {
+        map[i] = props[i];
+    }
+    return map;
+};
+exports.arrayRemove = function(array, value) {
+  for (var i = 0; i <= array.length; i++) {
+    if (value === array[i]) {
+      array.splice(i, 1);
+    }
+  }
+};
+
+exports.escapeRegExp = function(str) {
+    return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
+};
+
+exports.escapeHTML = function(str) {
+    return str.replace(/&/g, "&#38;").replace(/"/g, "&#34;").replace(/'/g, "&#39;").replace(/</g, "&#60;");
+};
+
+exports.getMatchOffsets = function(string, regExp) {
+    var matches = [];
+
+    string.replace(regExp, function(str) {
+        matches.push({
+            offset: arguments[arguments.length-2],
+            length: str.length
+        });
+    });
+
+    return matches;
+};
+exports.deferredCall = function(fcn) {
+
+    var timer = null;
+    var callback = function() {
+        timer = null;
+        fcn();
+    };
+
+    var deferred = function(timeout) {
+        deferred.cancel();
+        timer = setTimeout(callback, timeout || 0);
+        return deferred;
+    };
+
+    deferred.schedule = deferred;
+
+    deferred.call = function() {
+        this.cancel();
+        fcn();
+        return deferred;
+    };
+
+    deferred.cancel = function() {
+        clearTimeout(timer);
+        timer = null;
+        return deferred;
+    };
+
+    return deferred;
+};
+
+
+exports.delayedCall = function(fcn, defaultTimeout) {
+    var timer = null;
+    var callback = function() {
+        timer = null;
+        fcn();
+    };
+
+    var _self = function(timeout) {
+        timer && clearTimeout(timer);
+        timer = setTimeout(callback, timeout || defaultTimeout);
+    };
+
+    _self.delay = _self;
+    _self.schedule = function(timeout) {
+        if (timer == null)
+            timer = setTimeout(callback, timeout || 0);
+    };
+
+    _self.call = function() {
+        this.cancel();
+        fcn();
+    };
+
+    _self.cancel = function() {
+        timer && clearTimeout(timer);
+        timer = null;
+    };
+
+    _self.isPending = function() {
+        return timer;
+    };
+
+    return _self;
+};
+});
+define('ace/worker/mirror', ['require', 'exports', 'module' , 'ace/document', 'ace/lib/lang'], function(require, exports, module) {
+
+
+var Document = require("../document").Document;
+var lang = require("../lib/lang");
+
+var Mirror = exports.Mirror = function(sender) {
+    this.sender = sender;
+    var doc = this.doc = new Document("");
+
+    var deferredUpdate = this.deferredUpdate = lang.deferredCall(this.onUpdate.bind(this));
+
+    var _self = this;
+    sender.on("change", function(e) {
+        doc.applyDeltas([e.data]);
+        deferredUpdate.schedule(_self.$timeout);
+    });
+};
+
+(function() {
+
+    this.$timeout = 500;
+
+    this.setTimeout = function(timeout) {
+        this.$timeout = timeout;
+    };
+
+    this.setValue = function(value) {
+        this.doc.setValue(value);
+        this.deferredUpdate.schedule(this.$timeout);
+    };
+
+    this.getValue = function(callbackId) {
+        this.sender.callback(this.doc.getValue(), callbackId);
+    };
+
+    this.onUpdate = function() {
+    };
+
+}).call(Mirror.prototype);
+
+});
+
+define('ace/document', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) {
+
+
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var Range = require("./range").Range;
+var Anchor = require("./anchor").Anchor;
+
+var Document = function(text) {
+    this.$lines = [];
+    if (text.length == 0) {
+        this.$lines = [""];
+    } else if (Array.isArray(text)) {
+        this.insertLines(0, text);
+    } else {
+        this.insert({row: 0, column:0}, text);
+    }
+};
+
+(function() {
+
+    oop.implement(this, EventEmitter);
+    this.setValue = function(text) {
+        var len = this.getLength();
+        this.remove(new Range(0, 0, len, this.getLine(len-1).length));
+        this.insert({row: 0, column:0}, text);
+    };
+    this.getValue = function() {
+        return this.getAllLines().join(this.getNewLineCharacter());
+    };
+    this.createAnchor = function(row, column) {
+        return new Anchor(this, row, column);
+    };
+    if ("aaa".split(/a/).length == 0)
+        this.$split = function(text) {
+            return text.replace(/\r\n|\r/g, "\n").split("\n");
+        }
+    else
+        this.$split = function(text) {
+            return text.split(/\r\n|\r|\n/);
+        };
+
+
+
+    this.$detectNewLine = function(text) {
+        var match = text.match(/^.*?(\r\n|\r|\n)/m);
+        if (match) {
+            this.$autoNewLine = match[1];
+        } else {
+            this.$autoNewLine = "\n";
+        }
+    };
+    this.getNewLineCharacter = function() {
+        switch (this.$newLineMode) {
+          case "windows":
+            return "\r\n";
+
+          case "unix":
+            return "\n";
+
+          default:
+            return this.$autoNewLine;
+        }
+    };
+
+    this.$autoNewLine = "\n";
+    this.$newLineMode = "auto";
+    this.setNewLineMode = function(newLineMode) {
+        if (this.$newLineMode === newLineMode)
+            return;
+
+        this.$newLineMode = newLineMode;
+    };
+    this.getNewLineMode = function() {
+        return this.$newLineMode;
+    };
+    this.isNewLine = function(text) {
+        return (text == "\r\n" || text == "\r" || text == "\n");
+    };
+    this.getLine = function(row) {
+        return this.$lines[row] || "";
+    };
+    this.getLines = function(firstRow, lastRow) {
+        return this.$lines.slice(firstRow, lastRow + 1);
+    };
+    this.getAllLines = function() {
+        return this.getLines(0, this.getLength());
+    };
+    this.getLength = function() {
+        return this.$lines.length;
+    };
+    this.getTextRange = function(range) {
+        if (range.start.row == range.end.row) {
+            return this.$lines[range.start.row].substring(range.start.column,
+                                                         range.end.column);
+        }
+        else {
+            var lines = this.getLines(range.start.row+1, range.end.row-1);
+            lines.unshift((this.$lines[range.start.row] || "").substring(range.start.column));
+            lines.push((this.$lines[range.end.row] || "").substring(0, range.end.column));
+            return lines.join(this.getNewLineCharacter());
+        }
+    };
+
+    this.$clipPosition = function(position) {
+        var length = this.getLength();
+        if (position.row >= length) {
+            position.row = Math.max(0, length - 1);
+            position.column = this.getLine(length-1).length;
+        }
+        return position;
+    };
+    this.insert = function(position, text) {
+        if (!text || text.length === 0)
+            return position;
+
+        position = this.$clipPosition(position);
+        if (this.getLength() <= 1)
+            this.$detectNewLine(text);
+
+        var lines = this.$split(text);
+        var firstLine = lines.splice(0, 1)[0];
+        var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
+
+        position = this.insertInLine(position, firstLine);
+        if (lastLine !== null) {
+            position = this.insertNewLine(position); // terminate first line
+            position = this.insertLines(position.row, lines);
+            position = this.insertInLine(position, lastLine || "");
+        }
+        return position;
+    };
+    this.insertLines = function(row, lines) {
+        if (lines.length == 0)
+            return {row: row, column: 0};
+        if (lines.length > 0xFFFF) {
+            var end = this.insertLines(row, lines.slice(0xFFFF));
+            lines = lines.slice(0, 0xFFFF);
+        }
+
+        var args = [row, 0];
+        args.push.apply(args, lines);
+        this.$lines.splice.apply(this.$lines, args);
+
+        var range = new Range(row, 0, row + lines.length, 0);
+        var delta = {
+            action: "insertLines",
+            range: range,
+            lines: lines
+        };
+        this._emit("change", { data: delta });
+        return end || range.end;
+    };
+    this.insertNewLine = function(position) {
+        position = this.$clipPosition(position);
+        var line = this.$lines[position.row] || "";
+
+        this.$lines[position.row] = line.substring(0, position.column);
+        this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
+
+        var end = {
+            row : position.row + 1,
+            column : 0
+        };
+
+        var delta = {
+            action: "insertText",
+            range: Range.fromPoints(position, end),
+            text: this.getNewLineCharacter()
+        };
+        this._emit("change", { data: delta });
+
+        return end;
+    };
+    this.insertInLine = function(position, text) {
+        if (text.length == 0)
+            return position;
+
+        var line = this.$lines[position.row] || "";
+
+        this.$lines[position.row] = line.substring(0, position.column) + text
+                + line.substring(position.column);
+
+        var end = {
+            row : position.row,
+            column : position.column + text.length
+        };
+
+        var delta = {
+            action: "insertText",
+            range: Range.fromPoints(position, end),
+            text: text
+        };
+        this._emit("change", { data: delta });
+
+        return end;
+    };
+    this.remove = function(range) {
+        range.start = this.$clipPosition(range.start);
+        range.end = this.$clipPosition(range.end);
+
+        if (range.isEmpty())
+            return range.start;
+
+        var firstRow = range.start.row;
+        var lastRow = range.end.row;
+
+        if (range.isMultiLine()) {
+            var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
+            var lastFullRow = lastRow - 1;
+
+            if (range.end.column > 0)
+                this.removeInLine(lastRow, 0, range.end.column);
+
+            if (lastFullRow >= firstFullRow)
+                this.removeLines(firstFullRow, lastFullRow);
+
+            if (firstFullRow != firstRow) {
+                this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
+                this.removeNewLine(range.start.row);
+            }
+        }
+        else {
+            this.removeInLine(firstRow, range.start.column, range.end.column);
+        }
+        return range.start;
+    };
+    this.removeInLine = function(row, startColumn, endColumn) {
+        if (startColumn == endColumn)
+            return;
+
+        var range = new Range(row, startColumn, row, endColumn);
+        var line = this.getLine(row);
+        var removed = line.substring(startColumn, endColumn);
+        var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
+        this.$lines.splice(row, 1, newLine);
+
+        var delta = {
+            action: "removeText",
+            range: range,
+            text: removed
+        };
+        this._emit("change", { data: delta });
+        return range.start;
+    };
+    this.removeLines = function(firstRow, lastRow) {
+        var range = new Range(firstRow, 0, lastRow + 1, 0);
+        var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
+
+        var delta = {
+            action: "removeLines",
+            range: range,
+            nl: this.getNewLineCharacter(),
+            lines: removed
+        };
+        this._emit("change", { data: delta });
+        return removed;
+    };
+    this.removeNewLine = function(row) {
+        var firstLine = this.getLine(row);
+        var secondLine = this.getLine(row+1);
+
+        var range = new Range(row, firstLine.length, row+1, 0);
+        var line = firstLine + secondLine;
+
+        this.$lines.splice(row, 2, line);
+
+        var delta = {
+            action: "removeText",
+            range: range,
+            text: this.getNewLineCharacter()
+        };
+        this._emit("change", { data: delta });
+    };
+    this.replace = function(range, text) {
+        if (text.length == 0 && range.isEmpty())
+            return range.start;
+        if (text == this.getTextRange(range))
+            return range.end;
+
+        this.remove(range);
+        if (text) {
+            var end = this.insert(range.start, text);
+        }
+        else {
+            end = range.start;
+        }
+
+        return end;
+    };
+    this.applyDeltas = function(deltas) {
+        for (var i=0; i<deltas.length; i++) {
+            var delta = deltas[i];
+            var range = Range.fromPoints(delta.range.start, delta.range.end);
+
+            if (delta.action == "insertLines")
+                this.insertLines(range.start.row, delta.lines);
+            else if (delta.action == "insertText")
+                this.insert(range.start, delta.text);
+            else if (delta.action == "removeLines")
+                this.removeLines(range.start.row, range.end.row - 1);
+            else if (delta.action == "removeText")
+                this.remove(range);
+        }
+    };
+    this.revertDeltas = function(deltas) {
+        for (var i=deltas.length-1; i>=0; i--) {
+            var delta = deltas[i];
+
+            var range = Range.fromPoints(delta.range.start, delta.range.end);
+
+            if (delta.action == "insertLines")
+                this.removeLines(range.start.row, range.end.row - 1);
+            else if (delta.action == "insertText")
+                this.remove(range);
+            else if (delta.action == "removeLines")
+                this.insertLines(range.start.row, delta.lines);
+            else if (delta.action == "removeText")
+                this.insert(range.start, delta.text);
+        }
+    };
+    this.indexToPosition = function(index, startRow) {
+        var lines = this.$lines || this.getAllLines();
+        var newlineLength = this.getNewLineCharacter().length;
+        for (var i = startRow || 0, l = lines.length; i < l; i++) {
+            index -= lines[i].length + newlineLength;
+            if (index < 0)
+                return {row: i, column: index + lines[i].length + newlineLength};
+        }
+        return {row: l-1, column: lines[l-1].length};
+    };
+    this.positionToIndex = function(pos, startRow) {
+        var lines = this.$lines || this.getAllLines();
+        var newlineLength = this.getNewLineCharacter().length;
+        var index = 0;
+        var row = Math.min(pos.row, lines.length);
+        for (var i = startRow || 0; i < row; ++i)
+            index += lines[i].length;
+
+        return index + newlineLength * i + pos.column;
+    };
+
+}).call(Document.prototype);
+
+exports.Document = Document;
+});
+
+define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) {
+var Range = function(startRow, startColumn, endRow, endColumn) {
+    this.start = {
+        row: startRow,
+        column: startColumn
+    };
+
+    this.end = {
+        row: endRow,
+        column: endColumn
+    };
+};
+
+(function() {
+    this.isEqual = function(range) {
+        return this.start.row == range.start.row &&
+            this.end.row == range.end.row &&
+            this.start.column == range.start.column &&
+            this.end.column == range.end.column
+    };
+    this.toString = function() {
+        return ("Range: [" + this.start.row + "/" + this.start.column +
+            "] -> [" + this.end.row + "/" + this.end.column + "]");
+    };
+
+    this.contains = function(row, column) {
+        return this.compare(row, column) == 0;
+    };
+    this.compareRange = function(range) {
+        var cmp,
+            end = range.end,
+            start = range.start;
+
+        cmp = this.compare(end.row, end.column);
+        if (cmp == 1) {
+            cmp = this.compare(start.row, start.column);
+            if (cmp == 1) {
+                return 2;
+            } else if (cmp == 0) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else if (cmp == -1) {
+            return -2;
+        } else {
+            cmp = this.compare(start.row, start.column);
+            if (cmp == -1) {
+                return -1;
+            } else if (cmp == 1) {
+                return 42;
+            } else {
+                return 0;
+            }
+        }
+    };
+    this.comparePoint = function(p) {
+        return this.compare(p.row, p.column);
+    };
+    this.containsRange = function(range) {
+        return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
+    };
+    this.intersects = function(range) {
+        var cmp = this.compareRange(range);
+        return (cmp == -1 || cmp == 0 || cmp == 1);
+    };
+    this.isEnd = function(row, column) {
+        return this.end.row == row && this.end.column == column;
+    };
+    this.isStart = function(row, column) {
+        return this.start.row == row && this.start.column == column;
+    };
+    this.setStart = function(row, column) {
+        if (typeof row == "object") {
+            this.start.column = row.column;
+            this.start.row = row.row;
+        } else {
+            this.start.row = row;
+            this.start.column = column;
+        }
+    };
+    this.setEnd = function(row, column) {
+        if (typeof row == "object") {
+            this.end.column = row.column;
+            this.end.row = row.row;
+        } else {
+            this.end.row = row;
+            this.end.column = column;
+        }
+    };
+    this.inside = function(row, column) {
+        if (this.compare(row, column) == 0) {
+            if (this.isEnd(row, column) || this.isStart(row, column)) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    };
+    this.insideStart = function(row, column) {
+        if (this.compare(row, column) == 0) {
+            if (this.isEnd(row, column)) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    };
+    this.insideEnd = function(row, column) {
+        if (this.compare(row, column) == 0) {
+            if (this.isStart(row, column)) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    };
+    this.compare = function(row, column) {
+        if (!this.isMultiLine()) {
+            if (row === this.start.row) {
+                return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);
+            };
+        }
+
+        if (row < this.start.row)
+            return -1;
+
+        if (row > this.end.row)
+            return 1;
+
+        if (this.start.row === row)
+            return column >= this.start.column ? 0 : -1;
+
+        if (this.end.row === row)
+            return column <= this.end.column ? 0 : 1;
+
+        return 0;
+    };
+    this.compareStart = function(row, column) {
+        if (this.start.row == row && this.start.column == column) {
+            return -1;
+        } else {
+            return this.compare(row, column);
+        }
+    };
+    this.compareEnd = function(row, column) {
+        if (this.end.row == row && this.end.column == column) {
+            return 1;
+        } else {
+            return this.compare(row, column);
+        }
+    };
+    this.compareInside = function(row, column) {
+        if (this.end.row == row && this.end.column == column) {
+            return 1;
+        } else if (this.start.row == row && this.start.column == column) {
+            return -1;
+        } else {
+            return this.compare(row, column);
+        }
+    };
+    this.clipRows = function(firstRow, lastRow) {
+        if (this.end.row > lastRow) {
+            var end = {
+                row: lastRow+1,
+                column: 0
+            };
+        }
+
+        if (this.start.row > lastRow) {
+            var start = {
+                row: lastRow+1,
+                column: 0
+            };
+        }
+
+        if (this.start.row < firstRow) {
+            var start = {
+                row: firstRow,
+                column: 0
+            };
+        }
+
+        if (this.end.row < firstRow) {
+            var end = {
+                row: firstRow,
+                column: 0
+            };
+        }
+        return Range.fromPoints(start || this.start, end || this.end);
+    };
+    this.extend = function(row, column) {
+        var cmp = this.compare(row, column);
+
+        if (cmp == 0)
+            return this;
+        else if (cmp == -1)
+            var start = {row: row, column: column};
+        else
+            var end = {row: row, column: column};
+
+        return Range.fromPoints(start || this.start, end || 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 Range.fromPoints(this.start, this.end);
+    };
+    this.collapseRows = function() {
+        if (this.end.column == 0)
+            return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)
+        else
+            return new Range(this.start.row, 0, this.end.row, 0)
+    };
+    this.toScreenRange = function(session) {
+        var screenPosStart =
+            session.documentToScreenPosition(this.start);
+        var screenPosEnd =
+            session.documentToScreenPosition(this.end);
+
+        return new Range(
+            screenPosStart.row, screenPosStart.column,
+            screenPosEnd.row, screenPosEnd.column
+        );
+    };
+
+}).call(Range.prototype);
+Range.fromPoints = function(start, end) {
+    return new Range(start.row, start.column, end.row, end.column);
+};
+
+exports.Range = Range;
+});
+
+define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
+
+
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+
+var Anchor = exports.Anchor = function(doc, row, column) {
+    this.document = doc;
+
+    if (typeof column == "undefined")
+        this.setPosition(row.row, row.column);
+    else
+        this.setPosition(row, column);
+
+    this.$onChange = this.onChange.bind(this);
+    doc.on("change", this.$onChange);
+};
+
+(function() {
+
+    oop.implement(this, EventEmitter);
+
+    this.getPosition = function() {
+        return this.$clipPositionToDocument(this.row, this.column);
+    };
+
+    this.getDocument = function() {
+        return this.document;
+    };
+
+    this.onChange = function(e) {
+        var delta = e.data;
+        var range = delta.range;
+
+        if (range.start.row == range.end.row && range.start.row != this.row)
+            return;
+
+        if (range.start.row > this.row)
+            return;
+
+        if (range.start.row == this.row && range.start.column > this.column)
+            return;
+
+        var row = this.row;
+        var column = this.column;
+
+        if (delta.action === "insertText") {
+            if (range.start.row === row && range.start.column <= column) {
+                if (range.start.row === range.end.row) {
+                    column += range.end.column - range.start.column;
+                }
+                else {
+                    column -= range.start.column;
+                    row += range.end.row - range.start.row;
+                }
+            }
+            else if (range.start.row !== range.end.row && range.start.row < row) {
+                row += range.end.row - range.start.row;
+            }
+        } else if (delta.action === "insertLines") {
+            if (range.start.row <= row) {
+                row += range.end.row - range.start.row;
+            }
+        }
+        else if (delta.action == "removeText") {
+            if (range.start.row == row && range.start.column < column) {
+                if (range.end.column >= column)
+                    column = range.start.column;
+                else
+                    column = Math.max(0, column - (range.end.column - range.start.column));
+
+            } else if (range.start.row !== range.end.row && range.start.row < row) {
+                if (range.end.row == row) {
+                    column = Math.max(0, column - range.end.column) + range.start.column;
+                }
+                row -= (range.end.row - range.start.row);
+            }
+            else if (range.end.row == row) {
+                row -= range.end.row - range.start.row;
+                column = Math.max(0, column - range.end.column) + range.start.column;
+            }
+        } else if (delta.action == "removeLines") {
+            if (range.start.row <= row) {
+                if (range.end.row <= row)
+                    row -= range.end.row - range.start.row;
+                else {
+                    row = range.start.row;
+                    column = 0;
+                }
+            }
+        }
+
+        this.setPosition(row, column, true);
+    };
+
+    this.setPosition = function(row, column, noClip) {
+        var pos;
+        if (noClip) {
+            pos = {
+                row: row,
+                column: column
+            };
+        }
+        else {
+            pos = this.$clipPositionToDocument(row, column);
+        }
+
+        if (this.row == pos.row && this.column == pos.column)
+            return;
+
+        var old = {
+            row: this.row,
+            column: this.column
+        };
+
+        this.row = pos.row;
+        this.column = pos.column;
+        this._emit("change", {
+            old: old,
+            value: pos
+        });
+    };
+
+    this.detach = function() {
+        this.document.removeEventListener("change", this.$onChange);
+    };
+    this.$clipPositionToDocument = function(row, column) {
+        var pos = {};
+
+        if (row >= this.document.getLength()) {
+            pos.row = Math.max(0, this.document.getLength() - 1);
+            pos.column = this.document.getLine(pos.row).length;
+        }
+        else if (row < 0) {
+            pos.row = 0;
+            pos.column = 0;
+        }
+        else {
+            pos.row = row;
+            pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
+        }
+
+        if (column < 0)
+            pos.column = 0;
+
+        return pos;
+    };
+
+}).call(Anchor.prototype);
+
+});
+define('ace/mode/css/csslint', ['require', 'exports', 'module' ], function(require, exports, module) {
+var parserlib = {};
+(function(){
+function EventTarget(){
+    this._listeners = {};
+}
+
+EventTarget.prototype = {
+    constructor: EventTarget,
+    addListener: function(type, listener){
+        if (!this._listeners[type]){
+            this._listeners[type] = [];
+        }
+
+        this._listeners[type].push(listener);
+    },
+    fire: function(event){
+        if (typeof event == "string"){
+            event = { type: event };
+        }
+        if (typeof event.target != "undefined"){
+            event.target = this;
+        }
+
+        if (typeof event.type == "undefined"){
+            throw new Error("Event object missing 'type' property.");
+        }
+
+        if (this._listeners[event.type]){
+            var listeners = this._listeners[event.type].concat();
+            for (var i=0, len=listeners.length; i < len; i++){
+                listeners[i].call(this, event);
+            }
+        }
+    },
+    removeListener: function(type, listener){
+        if (this._listeners[type]){
+            var listeners = this._listeners[type];
+            for (var i=0, len=listeners.length; i < len; i++){
+                if (listeners[i] === listener){
+                    listeners.splice(i, 1);
+                    break;
+                }
+            }
+
+
+        }
+    }
+};
+function StringReader(text){
+    this._input = text.replace(/\n\r?/g, "\n");
+    this._line = 1;
+    this._col = 1;
+    this._cursor = 0;
+}
+
+StringReader.prototype = {
+    constructor: StringReader,
+    getCol: function(){
+        return this._col;
+    },
+    getLine: function(){
+        return this._line ;
+    },
+    eof: function(){
+        return (this._cursor == this._input.length);
+    },
+    peek: function(count){
+        var c = null;
+        count = (typeof count == "undefined" ? 1 : count);
+        if (this._cursor < this._input.length){
+            c = this._input.charAt(this._cursor + count - 1);
+        }
+
+        return c;
+    },
+    read: function(){
+        var c = null;
+        if (this._cursor < this._input.length){
+            if (this._input.charAt(this._cursor) == "\n"){
+                this._line++;
+                this._col=1;
+            } else {
+                this._col++;
+            }
+            c = this._input.charAt(this._cursor++);
+        }
+
+        return c;
+    },
+    mark: function(){
+        this._bookmark = {
+            cursor: this._cursor,
+            line:   this._line,
+            col:    this._col
+        };
+    },
+
+    reset: function(){
+        if (this._bookmark){
+            this._cursor = this._bookmark.cursor;
+            this._line = this._bookmark.line;
+            this._col = this._bookmark.col;
+            delete this._bookmark;
+        }
+    },
+    readTo: function(pattern){
+
+        var buffer = "",
+            c;
+        while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){
+            c = this.read();
+            if (c){
+                buffer += c;
+            } else {
+                throw new Error("Expected \"" + pattern + "\" at line " + this._line  + ", col " + this._col + ".");
+            }
+        }
+
+        return buffer;
+
+    },
+    readWhile: function(filter){
+
+        var buffer = "",
+            c = this.read();
+
+        while(c !== null && filter(c)){
+            buffer += c;
+            c = this.read();
+        }
+
+        return buffer;
+
+    },
+    readMatch: function(matcher){
+
+        var source = this._input.substring(this._cursor),
+            value = null;
+        if (typeof matcher == "string"){
+            if (source.indexOf(matcher) === 0){
+                value = this.readCount(matcher.length);
+            }
+        } else if (matcher instanceof RegExp){
+            if (matcher.test(source)){
+                value = this.readCount(RegExp.lastMatch.length);
+            }
+        }
+
+        return value;
+    },
+    readCount: function(count){
+        var buffer = "";
+
+        while(count--){
+            buffer += this.read();
+        }
+
+        return buffer;
+    }
+
+};
+function SyntaxError(message, line, col){
+    this.col = col;
+    this.line = line;
+    this.message = message;
+
+}
+SyntaxError.prototype = new Error();
+function SyntaxUnit(text, line, col, type){
+    this.col = col;
+    this.line = line;
+    this.text = text;
+    this.type = type;
+}
+SyntaxUnit.fromToken = function(token){
+    return new SyntaxUnit(token.value, token.startLine, token.startCol);
+};
+
+SyntaxUnit.prototype = {
+    constructor: SyntaxUnit,
+    valueOf: function(){
+        return this.toString();
+    },
+    toString: function(){
+        return this.text;
+    }
+
+};
+function TokenStreamBase(input, tokenData){
+    this._reader = input ? new StringReader(input.toString()) : null;
+    this._token = null;
+    this._tokenData = tokenData;
+    this._lt = [];
+    this._ltIndex = 0;
+
+    this._ltIndexCache = [];
+}
+TokenStreamBase.createTokenData = function(tokens){
+
+    var nameMap     = [],
+        typeMap     = {},
+        tokenData     = tokens.concat([]),
+        i            = 0,
+        len            = tokenData.length+1;
+
+    tokenData.UNKNOWN = -1;
+    tokenData.unshift({name:"EOF"});
+
+    for (; i < len; i++){
+        nameMap.push(tokenData[i].name);
+        tokenData[tokenData[i].name] = i;
+        if (tokenData[i].text){
+            typeMap[tokenData[i].text] = i;
+        }
+    }
+
+    tokenData.name = function(tt){
+        return nameMap[tt];
+    };
+
+    tokenData.type = function(c){
+        return typeMap[c];
+    };
+
+    return tokenData;
+};
+
+TokenStreamBase.prototype = {
+    constructor: TokenStreamBase,
+    match: function(tokenTypes, channel){
+        if (!(tokenTypes instanceof Array)){
+            tokenTypes = [tokenTypes];
+        }
+
+        var tt  = this.get(channel),
+            i   = 0,
+            len = tokenTypes.length;
+
+        while(i < len){
+            if (tt == tokenTypes[i++]){
+                return true;
+            }
+        }
+        this.unget();
+        return false;
+    },
+    mustMatch: function(tokenTypes, channel){
+
+        var token;
+        if (!(tokenTypes instanceof Array)){
+            tokenTypes = [tokenTypes];
+        }
+
+        if (!this.match.apply(this, arguments)){
+            token = this.LT(1);
+            throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name +
+                " at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);
+        }
+    },
+    advance: function(tokenTypes, channel){
+
+        while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){
+            this.get();
+        }
+
+        return this.LA(0);
+    },
+    get: function(channel){
+
+        var tokenInfo   = this._tokenData,
+            reader      = this._reader,
+            value,
+            i           =0,
+            len         = tokenInfo.length,
+            found       = false,
+            token,
+            info;
+        if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){
+
+            i++;
+            this._token = this._lt[this._ltIndex++];
+            info = tokenInfo[this._token.type];
+            while((info.channel !== undefined && channel !== info.channel) &&
+                    this._ltIndex < this._lt.length){
+                this._token = this._lt[this._ltIndex++];
+                info = tokenInfo[this._token.type];
+                i++;
+            }
+            if ((info.channel === undefined || channel === info.channel) &&
+                    this._ltIndex <= this._lt.length){
+                this._ltIndexCache.push(i);
+                return this._token.type;
+            }
+        }
+        token = this._getToken();
+        if (token.type > -1 && !tokenInfo[token.type].hide){
+            token.channel = tokenInfo[token.type].channel;
+            this._token = token;
+            this._lt.push(token);
+            this._ltIndexCache.push(this._lt.length - this._ltIndex + i);
+            if (this._lt.length > 5){
+                this._lt.shift();
+            }
+            if (this._ltIndexCache.length > 5){
+                this._ltIndexCache.shift();
+            }
+            this._ltIndex = this._lt.length;
+        }
+        info = tokenInfo[token.type];
+        if (info &&
+                (info.hide ||
+                (info.channel !== undefined && channel !== info.channel))){
+            return this.get(channel);
+        } else {
+            return token.type;
+        }
+    },
+    LA: function(index){
+        var total = index,
+            tt;
+        if (index > 0){
+            if (index > 5){
+                throw new Error("Too much lookahead.");
+            }
+            while(total){
+                tt = this.get();
+                total--;
+            }
+            while(total < index){
+                this.unget();
+                total++;
+            }
+        } else if (index < 0){
+
+            if(this._lt[this._ltIndex+index]){
+                tt = this._lt[this._ltIndex+index].type;
+            } else {
+                throw new Error("Too much lookbehind.");
+            }
+
+        } else {
+            tt = this._token.type;
+        }
+
+        return tt;
+
+    },
+    LT: function(index){
+        this.LA(index);
+        return this._lt[this._ltIndex+index-1];
+    },
+    peek: function(){
+        return this.LA(1);
+    },
+    token: function(){
+        return this._token;
+    },
+    tokenName: function(tokenType){
+        if (tokenType < 0 || tokenType > this._tokenData.length){
+            return "UNKNOWN_TOKEN";
+        } else {
+            return this._tokenData[tokenType].name;
+        }
+    },
+    tokenType: function(tokenName){
+        return this._tokenData[tokenName] || -1;
+    },
+    unget: function(){
+        if (this._ltIndexCache.length){
+            this._ltIndex -= this._ltIndexCache.pop();//--;
+            this._token = this._lt[this._ltIndex - 1];
+        } else {
+            throw new Error("Too much lookahead.");
+        }
+    }
+
+};
+
+
+
+
+parserlib.util = {
+StringReader: StringReader,
+SyntaxError : SyntaxError,
+SyntaxUnit  : SyntaxUnit,
+EventTarget : EventTarget,
+TokenStreamBase : TokenStreamBase
+};
+})();
+(function(){
+var EventTarget = parserlib.util.EventTarget,
+TokenStreamBase = parserlib.util.TokenStreamBase,
+StringReader = parserlib.util.StringReader,
+SyntaxError = parserlib.util.SyntaxError,
+SyntaxUnit  = parserlib.util.SyntaxUnit;
+
+
+var 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"
+};
+function Combinator(text, line, col){
+
+    SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE);
+    this.type = "unknown";
+    if (/^\s+$/.test(text)){
+        this.type = "descendant";
+    } else if (text == ">"){
+        this.type = "child";
+    } else if (text == "+"){
+        this.type = "adjacent-sibling";
+    } else if (text == "~"){
+        this.type = "sibling";
+    }
+
+}
+
+Combinator.prototype = new SyntaxUnit();
+Combinator.prototype.constructor = Combinator;
+function MediaFeature(name, value){
+
+    SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE);
+    this.name = name;
+    this.value = value;
+}
+
+MediaFeature.prototype = new SyntaxUnit();
+MediaFeature.prototype.constructor = MediaFeature;
+function MediaQuery(modifier, mediaType, features, line, col){
+
+    SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE);
+    this.modifier = modifier;
+    this.mediaType = mediaType;
+    this.features = features;
+
+}
+
+MediaQuery.prototype = new SyntaxUnit();
+MediaQuery.prototype.constructor = MediaQuery;
+function Parser(options){
+    EventTarget.call(this);
+
+
+    this.options = options || {};
+
+    this._tokenStream = null;
+}
+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 proto = new EventTarget(),  //new prototype
+        prop,
+        additions =  {
+            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 tokenStream = this._tokenStream,
+                    charset     = null,
+                    count,
+                    token,
+                    tt;
+
+                this.fire("startstylesheet");
+                this._charset();
+
+                this._skipCruft();
+                while (tokenStream.peek() == Tokens.IMPORT_SYM){
+                    this._import();
+                    this._skipCruft();
+                }
+                while (tokenStream.peek() == Tokens.NAMESPACE_SYM){
+                    this._namespace();
+                    this._skipCruft();
+                }
+                tt = tokenStream.peek();
+                while(tt > Tokens.EOF){
+
+                    try {
+
+                        switch(tt){
+                            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:  //unknown @ rule
+                                tokenStream.get();
+                                if (!this.options.strict){
+                                    this.fire({
+                                        type:       "error",
+                                        error:      null,
+                                        message:    "Unknown @ rule: " + tokenStream.LT(0).value + ".",
+                                        line:       tokenStream.LT(0).startLine,
+                                        col:        tokenStream.LT(0).startCol
+                                    });
+                                    count=0;
+                                    while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){
+                                        count++;    //keep track of nesting depth
+                                    }
+
+                                    while(count){
+                                        tokenStream.advance([Tokens.RBRACE]);
+                                        count--;
+                                    }
+
+                                } else {
+                                    throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);
+                                }
+                                break;
+                            case Tokens.S:
+                                this._readWhitespace();
+                                break;
+                            default:
+                                if(!this._ruleset()){
+                                    switch(tt){
+                                        case Tokens.CHARSET_SYM:
+                                            token = tokenStream.LT(1);
+                                            this._charset(false);
+                                            throw new SyntaxError("@charset not allowed here.", token.startLine, token.startCol);
+                                        case Tokens.IMPORT_SYM:
+                                            token = tokenStream.LT(1);
+                                            this._import(false);
+                                            throw new SyntaxError("@import not allowed here.", token.startLine, token.startCol);
+                                        case Tokens.NAMESPACE_SYM:
+                                            token = tokenStream.LT(1);
+                                            this._namespace(false);
+                                            throw new SyntaxError("@namespace not allowed here.", token.startLine, token.startCol);
+                                        default:
+                                            tokenStream.get();  //get the last token
+                                            this._unexpectedToken(tokenStream.token());
+                                    }
+
+                                }
+                        }
+                    } catch(ex) {
+                        if (ex instanceof SyntaxError && !this.options.strict){
+                            this.fire({
+                                type:       "error",
+                                error:      ex,
+                                message:    ex.message,
+                                line:       ex.line,
+                                col:        ex.col
+                            });
+                        } else {
+                            throw ex;
+                        }
+                    }
+
+                    tt = tokenStream.peek();
+                }
+
+                if (tt != Tokens.EOF){
+                    this._unexpectedToken(tokenStream.token());
+                }
+
+                this.fire("endstylesheet");
+            },
+
+            _charset: function(emit){
+                var tokenStream = this._tokenStream,
+                    charset,
+                    token,
+                    line,
+                    col;
+
+                if (tokenStream.match(Tokens.CHARSET_SYM)){
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+
+                    this._readWhitespace();
+                    tokenStream.mustMatch(Tokens.STRING);
+
+                    token = tokenStream.token();
+                    charset = token.value;
+
+                    this._readWhitespace();
+                    tokenStream.mustMatch(Tokens.SEMICOLON);
+
+                    if (emit !== false){
+                        this.fire({
+                            type:   "charset",
+                            charset:charset,
+                            line:   line,
+                            col:    col
+                        });
+                    }
+                }
+            },
+
+            _import: function(emit){
+
+                var tokenStream = this._tokenStream,
+                    tt,
+                    uri,
+                    importToken,
+                    mediaList   = [];
+                tokenStream.mustMatch(Tokens.IMPORT_SYM);
+                importToken = tokenStream.token();
+                this._readWhitespace();
+
+                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);
+                uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1");
+
+                this._readWhitespace();
+
+                mediaList = this._media_query_list();
+                tokenStream.mustMatch(Tokens.SEMICOLON);
+                this._readWhitespace();
+
+                if (emit !== false){
+                    this.fire({
+                        type:   "import",
+                        uri:    uri,
+                        media:  mediaList,
+                        line:   importToken.startLine,
+                        col:    importToken.startCol
+                    });
+                }
+
+            },
+
+            _namespace: function(emit){
+
+                var tokenStream = this._tokenStream,
+                    line,
+                    col,
+                    prefix,
+                    uri;
+                tokenStream.mustMatch(Tokens.NAMESPACE_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+                this._readWhitespace();
+                if (tokenStream.match(Tokens.IDENT)){
+                    prefix = tokenStream.token().value;
+                    this._readWhitespace();
+                }
+
+                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);
+                uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1");
+
+                this._readWhitespace();
+                tokenStream.mustMatch(Tokens.SEMICOLON);
+                this._readWhitespace();
+
+                if (emit !== false){
+                    this.fire({
+                        type:   "namespace",
+                        prefix: prefix,
+                        uri:    uri,
+                        line:   line,
+                        col:    col
+                    });
+                }
+
+            },
+
+            _media: function(){
+                var tokenStream     = this._tokenStream,
+                    line,
+                    col,
+                    mediaList;//       = [];
+                tokenStream.mustMatch(Tokens.MEDIA_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+
+                this._readWhitespace();
+
+                mediaList = this._media_query_list();
+
+                tokenStream.mustMatch(Tokens.LBRACE);
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "startmedia",
+                    media:  mediaList,
+                    line:   line,
+                    col:    col
+                });
+
+                while(true) {
+                    if (tokenStream.peek() == Tokens.PAGE_SYM){
+                        this._page();
+                    } else if (!this._ruleset()){
+                        break;
+                    }
+                }
+
+                tokenStream.mustMatch(Tokens.RBRACE);
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "endmedia",
+                    media:  mediaList,
+                    line:   line,
+                    col:    col
+                });
+            },
+            _media_query_list: function(){
+                var tokenStream = this._tokenStream,
+                    mediaList   = [];
+
+
+                this._readWhitespace();
+
+                if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){
+                    mediaList.push(this._media_query());
+                }
+
+                while(tokenStream.match(Tokens.COMMA)){
+                    this._readWhitespace();
+                    mediaList.push(this._media_query());
+                }
+
+                return mediaList;
+            },
+            _media_query: function(){
+                var tokenStream = this._tokenStream,
+                    type        = null,
+                    ident       = null,
+                    token       = null,
+                    expressions = [];
+
+                if (tokenStream.match(Tokens.IDENT)){
+                    ident = tokenStream.token().value.toLowerCase();
+                    if (ident != "only" && ident != "not"){
+                        tokenStream.unget();
+                        ident = null;
+                    } else {
+                        token = tokenStream.token();
+                    }
+                }
+
+                this._readWhitespace();
+
+                if (tokenStream.peek() == Tokens.IDENT){
+                    type = this._media_type();
+                    if (token === null){
+                        token = tokenStream.token();
+                    }
+                } else if (tokenStream.peek() == Tokens.LPAREN){
+                    if (token === null){
+                        token = tokenStream.LT(1);
+                    }
+                    expressions.push(this._media_expression());
+                }
+
+                if (type === null && expressions.length === 0){
+                    return null;
+                } else {
+                    this._readWhitespace();
+                    while (tokenStream.match(Tokens.IDENT)){
+                        if (tokenStream.token().value.toLowerCase() != "and"){
+                            this._unexpectedToken(tokenStream.token());
+                        }
+
+                        this._readWhitespace();
+                        expressions.push(this._media_expression());
+                    }
+                }
+
+                return new MediaQuery(ident, type, expressions, token.startLine, token.startCol);
+            },
+            _media_type: function(){
+                return this._media_feature();
+            },
+            _media_expression: function(){
+                var tokenStream = this._tokenStream,
+                    feature     = null,
+                    token,
+                    expression  = null;
+
+                tokenStream.mustMatch(Tokens.LPAREN);
+
+                feature = this._media_feature();
+                this._readWhitespace();
+
+                if (tokenStream.match(Tokens.COLON)){
+                    this._readWhitespace();
+                    token = tokenStream.LT(1);
+                    expression = this._expression();
+                }
+
+                tokenStream.mustMatch(Tokens.RPAREN);
+                this._readWhitespace();
+
+                return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null));
+            },
+            _media_feature: function(){
+                var tokenStream = this._tokenStream;
+
+                tokenStream.mustMatch(Tokens.IDENT);
+
+                return SyntaxUnit.fromToken(tokenStream.token());
+            },
+            _page: function(){
+                var tokenStream = this._tokenStream,
+                    line,
+                    col,
+                    identifier  = null,
+                    pseudoPage  = null;
+                tokenStream.mustMatch(Tokens.PAGE_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+
+                this._readWhitespace();
+
+                if (tokenStream.match(Tokens.IDENT)){
+                    identifier = tokenStream.token().value;
+                    if (identifier.toLowerCase() === "auto"){
+                        this._unexpectedToken(tokenStream.token());
+                    }
+                }
+                if (tokenStream.peek() == Tokens.COLON){
+                    pseudoPage = this._pseudo_page();
+                }
+
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "startpage",
+                    id:     identifier,
+                    pseudo: pseudoPage,
+                    line:   line,
+                    col:    col
+                });
+
+                this._readDeclarations(true, true);
+
+                this.fire({
+                    type:   "endpage",
+                    id:     identifier,
+                    pseudo: pseudoPage,
+                    line:   line,
+                    col:    col
+                });
+
+            },
+            _margin: function(){
+                var tokenStream = this._tokenStream,
+                    line,
+                    col,
+                    marginSym   = this._margin_sym();
+
+                if (marginSym){
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+
+                    this.fire({
+                        type: "startpagemargin",
+                        margin: marginSym,
+                        line:   line,
+                        col:    col
+                    });
+
+                    this._readDeclarations(true);
+
+                    this.fire({
+                        type: "endpagemargin",
+                        margin: marginSym,
+                        line:   line,
+                        col:    col
+                    });
+                    return true;
+                } else {
+                    return false;
+                }
+            },
+            _margin_sym: function(){
+
+                var tokenStream = this._tokenStream;
+
+                if(tokenStream.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]))
+                {
+                    return SyntaxUnit.fromToken(tokenStream.token());
+                } else {
+                    return null;
+                }
+
+            },
+
+            _pseudo_page: function(){
+
+                var tokenStream = this._tokenStream;
+
+                tokenStream.mustMatch(Tokens.COLON);
+                tokenStream.mustMatch(Tokens.IDENT);
+
+                return tokenStream.token().value;
+            },
+
+            _font_face: function(){
+                var tokenStream = this._tokenStream,
+                    line,
+                    col;
+                tokenStream.mustMatch(Tokens.FONT_FACE_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "startfontface",
+                    line:   line,
+                    col:    col
+                });
+
+                this._readDeclarations(true);
+
+                this.fire({
+                    type:   "endfontface",
+                    line:   line,
+                    col:    col
+                });
+            },
+
+            _operator: function(){
+
+                var tokenStream = this._tokenStream,
+                    token       = null;
+
+                if (tokenStream.match([Tokens.SLASH, Tokens.COMMA])){
+                    token =  tokenStream.token();
+                    this._readWhitespace();
+                }
+                return token ? PropertyValuePart.fromToken(token) : null;
+
+            },
+
+            _combinator: function(){
+
+                var tokenStream = this._tokenStream,
+                    value       = null,
+                    token;
+
+                if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){
+                    token = tokenStream.token();
+                    value = new Combinator(token.value, token.startLine, token.startCol);
+                    this._readWhitespace();
+                }
+
+                return value;
+            },
+
+            _unary_operator: function(){
+
+                var tokenStream = this._tokenStream;
+
+                if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){
+                    return tokenStream.token().value;
+                } else {
+                    return null;
+                }
+            },
+
+            _property: function(){
+
+                var tokenStream = this._tokenStream,
+                    value       = null,
+                    hack        = null,
+                    tokenValue,
+                    token,
+                    line,
+                    col;
+                if (tokenStream.peek() == Tokens.STAR && this.options.starHack){
+                    tokenStream.get();
+                    token = tokenStream.token();
+                    hack = token.value;
+                    line = token.startLine;
+                    col = token.startCol;
+                }
+
+                if(tokenStream.match(Tokens.IDENT)){
+                    token = tokenStream.token();
+                    tokenValue = token.value;
+                    if (tokenValue.charAt(0) == "_" && this.options.underscoreHack){
+                        hack = "_";
+                        tokenValue = tokenValue.substring(1);
+                    }
+
+                    value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol));
+                    this._readWhitespace();
+                }
+
+                return value;
+            },
+            _ruleset: function(){
+
+                var tokenStream = this._tokenStream,
+                    tt,
+                    selectors;
+                try {
+                    selectors = this._selectors_group();
+                } catch (ex){
+                    if (ex instanceof SyntaxError && !this.options.strict){
+                        this.fire({
+                            type:       "error",
+                            error:      ex,
+                            message:    ex.message,
+                            line:       ex.line,
+                            col:        ex.col
+                        });
+                        tt = tokenStream.advance([Tokens.RBRACE]);
+                        if (tt == Tokens.RBRACE){
+                        } else {
+                            throw ex;
+                        }
+
+                    } else {
+                        throw ex;
+                    }
+                    return true;
+                }
+                if (selectors){
+
+                    this.fire({
+                        type:       "startrule",
+                        selectors:  selectors,
+                        line:       selectors[0].line,
+                        col:        selectors[0].col
+                    });
+
+                    this._readDeclarations(true);
+
+                    this.fire({
+                        type:       "endrule",
+                        selectors:  selectors,
+                        line:       selectors[0].line,
+                        col:        selectors[0].col
+                    });
+
+                }
+
+                return selectors;
+
+            },
+            _selectors_group: function(){
+                var tokenStream = this._tokenStream,
+                    selectors   = [],
+                    selector;
+
+                selector = this._selector();
+                if (selector !== null){
+
+                    selectors.push(selector);
+                    while(tokenStream.match(Tokens.COMMA)){
+                        this._readWhitespace();
+                        selector = this._selector();
+                        if (selector !== null){
+                            selectors.push(selector);
+                        } else {
+                            this._unexpectedToken(tokenStream.LT(1));
+                        }
+                    }
+                }
+
+                return selectors.length ? selectors : null;
+            },
+            _selector: function(){
+
+                var tokenStream = this._tokenStream,
+                    selector    = [],
+                    nextSelector = null,
+                    combinator  = null,
+                    ws          = null;
+                nextSelector = this._simple_selector_sequence();
+                if (nextSelector === null){
+                    return null;
+                }
+
+                selector.push(nextSelector);
+
+                do {
+                    combinator = this._combinator();
+
+                    if (combinator !== null){
+                        selector.push(combinator);
+                        nextSelector = this._simple_selector_sequence();
+                        if (nextSelector === null){
+                            this._unexpectedToken(tokenStream.LT(1));
+                        } else {
+                            selector.push(nextSelector);
+                        }
+                    } else {
+                        if (this._readWhitespace()){
+                            ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol);
+                            combinator = this._combinator();
+                            nextSelector = this._simple_selector_sequence();
+                            if (nextSelector === null){
+                                if (combinator !== null){
+                                    this._unexpectedToken(tokenStream.LT(1));
+                                }
+                            } else {
+
+                                if (combinator !== null){
+                                    selector.push(combinator);
+                                } else {
+                                    selector.push(ws);
+                                }
+
+                                selector.push(nextSelector);
+                            }
+                        } else {
+                            break;
+                        }
+
+                    }
+                } while(true);
+
+                return new Selector(selector, selector[0].line, selector[0].col);
+            },
+            _simple_selector_sequence: function(){
+
+                var tokenStream = this._tokenStream,
+                    elementName = null,
+                    modifiers   = [],
+                    selectorText= "",
+                    components  = [
+                        function(){
+                            return tokenStream.match(Tokens.HASH) ?
+                                    new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) :
+                                    null;
+                        },
+                        this._class,
+                        this._attrib,
+                        this._pseudo,
+                        this._negation
+                    ],
+                    i           = 0,
+                    len         = components.length,
+                    component   = null,
+                    found       = false,
+                    line,
+                    col;
+                line = tokenStream.LT(1).startLine;
+                col = tokenStream.LT(1).startCol;
+
+                elementName = this._type_selector();
+                if (!elementName){
+                    elementName = this._universal();
+                }
+
+                if (elementName !== null){
+                    selectorText += elementName;
+                }
+
+                while(true){
+                    if (tokenStream.peek() === Tokens.S){
+                        break;
+                    }
+                    while(i < len && component === null){
+                        component = components[i++].call(this);
+                    }
+
+                    if (component === null){
+                        if (selectorText === ""){
+                            return null;
+                        } else {
+                            break;
+                        }
+                    } else {
+                        i = 0;
+                        modifiers.push(component);
+                        selectorText += component.toString();
+                        component = null;
+                    }
+                }
+
+
+                return selectorText !== "" ?
+                        new SelectorPart(elementName, modifiers, selectorText, line, col) :
+                        null;
+            },
+            _type_selector: function(){
+
+                var tokenStream = this._tokenStream,
+                    ns          = this._namespace_prefix(),
+                    elementName = this._element_name();
+
+                if (!elementName){
+                    if (ns){
+                        tokenStream.unget();
+                        if (ns.length > 1){
+                            tokenStream.unget();
+                        }
+                    }
+
+                    return null;
+                } else {
+                    if (ns){
+                        elementName.text = ns + elementName.text;
+                        elementName.col -= ns.length;
+                    }
+                    return elementName;
+                }
+            },
+            _class: function(){
+
+                var tokenStream = this._tokenStream,
+                    token;
+
+                if (tokenStream.match(Tokens.DOT)){
+                    tokenStream.mustMatch(Tokens.IDENT);
+                    token = tokenStream.token();
+                    return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1);
+                } else {
+                    return null;
+                }
+
+            },
+            _element_name: function(){
+
+                var tokenStream = this._tokenStream,
+                    token;
+
+                if (tokenStream.match(Tokens.IDENT)){
+                    token = tokenStream.token();
+                    return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol);
+
+                } else {
+                    return null;
+                }
+            },
+            _namespace_prefix: function(){
+                var tokenStream = this._tokenStream,
+                    value       = "";
+                if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){
+
+                    if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){
+                        value += tokenStream.token().value;
+                    }
+
+                    tokenStream.mustMatch(Tokens.PIPE);
+                    value += "|";
+
+                }
+
+                return value.length ? value : null;
+            },
+            _universal: function(){
+                var tokenStream = this._tokenStream,
+                    value       = "",
+                    ns;
+
+                ns = this._namespace_prefix();
+                if(ns){
+                    value += ns;
+                }
+
+                if(tokenStream.match(Tokens.STAR)){
+                    value += "*";
+                }
+
+                return value.length ? value : null;
+
+           },
+            _attrib: function(){
+
+                var tokenStream = this._tokenStream,
+                    value       = null,
+                    ns,
+                    token;
+
+                if (tokenStream.match(Tokens.LBRACKET)){
+                    token = tokenStream.token();
+                    value = token.value;
+                    value += this._readWhitespace();
+
+                    ns = this._namespace_prefix();
+
+                    if (ns){
+                        value += ns;
+                    }
+
+                    tokenStream.mustMatch(Tokens.IDENT);
+                    value += tokenStream.token().value;
+                    value += this._readWhitespace();
+
+                    if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH,
+                            Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){
+
+                        value += tokenStream.token().value;
+                        value += this._readWhitespace();
+
+                        tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);
+                        value += tokenStream.token().value;
+                        value += this._readWhitespace();
+                    }
+
+                    tokenStream.mustMatch(Tokens.RBRACKET);
+
+                    return new SelectorSubPart(value + "]", "attribute", token.startLine, token.startCol);
+                } else {
+                    return null;
+                }
+            },
+            _pseudo: function(){
+
+                var tokenStream = this._tokenStream,
+                    pseudo      = null,
+                    colons      = ":",
+                    line,
+                    col;
+
+                if (tokenStream.match(Tokens.COLON)){
+
+                    if (tokenStream.match(Tokens.COLON)){
+                        colons += ":";
+                    }
+
+                    if (tokenStream.match(Tokens.IDENT)){
+                        pseudo = tokenStream.token().value;
+                        line = tokenStream.token().startLine;
+                        col = tokenStream.token().startCol - colons.length;
+                    } else if (tokenStream.peek() == Tokens.FUNCTION){
+                        line = tokenStream.LT(1).startLine;
+                        col = tokenStream.LT(1).startCol - colons.length;
+                        pseudo = this._functional_pseudo();
+                    }
+
+                    if (pseudo){
+                        pseudo = new SelectorSubPart(colons + pseudo, "pseudo", line, col);
+                    }
+                }
+
+                return pseudo;
+            },
+            _functional_pseudo: function(){
+
+                var tokenStream = this._tokenStream,
+                    value = null;
+
+                if(tokenStream.match(Tokens.FUNCTION)){
+                    value = tokenStream.token().value;
+                    value += this._readWhitespace();
+                    value += this._expression();
+                    tokenStream.mustMatch(Tokens.RPAREN);
+                    value += ")";
+                }
+
+                return value;
+            },
+            _expression: function(){
+
+                var tokenStream = this._tokenStream,
+                    value       = "";
+
+                while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION,
+                        Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH,
+                        Tokens.FREQ, Tokens.ANGLE, Tokens.TIME,
+                        Tokens.RESOLUTION])){
+
+                    value += tokenStream.token().value;
+                    value += this._readWhitespace();
+                }
+
+                return value.length ? value : null;
+
+            },
+            _negation: function(){
+
+                var tokenStream = this._tokenStream,
+                    line,
+                    col,
+                    value       = "",
+                    arg,
+                    subpart     = null;
+
+                if (tokenStream.match(Tokens.NOT)){
+                    value = tokenStream.token().value;
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+                    value += this._readWhitespace();
+                    arg = this._negation_arg();
+                    value += arg;
+                    value += this._readWhitespace();
+                    tokenStream.match(Tokens.RPAREN);
+                    value += tokenStream.token().value;
+
+                    subpart = new SelectorSubPart(value, "not", line, col);
+                    subpart.args.push(arg);
+                }
+
+                return subpart;
+            },
+            _negation_arg: function(){
+
+                var tokenStream = this._tokenStream,
+                    args        = [
+                        this._type_selector,
+                        this._universal,
+                        function(){
+                            return tokenStream.match(Tokens.HASH) ?
+                                    new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) :
+                                    null;
+                        },
+                        this._class,
+                        this._attrib,
+                        this._pseudo
+                    ],
+                    arg         = null,
+                    i           = 0,
+                    len         = args.length,
+                    elementName,
+                    line,
+                    col,
+                    part;
+
+                line = tokenStream.LT(1).startLine;
+                col = tokenStream.LT(1).startCol;
+
+                while(i < len && arg === null){
+
+                    arg = args[i].call(this);
+                    i++;
+                }
+                if (arg === null){
+                    this._unexpectedToken(tokenStream.LT(1));
+                }
+                if (arg.type == "elementName"){
+                    part = new SelectorPart(arg, [], arg.toString(), line, col);
+                } else {
+                    part = new SelectorPart(null, [arg], arg.toString(), line, col);
+                }
+
+                return part;
+            },
+
+            _declaration: function(){
+
+                var tokenStream = this._tokenStream,
+                    property    = null,
+                    expr        = null,
+                    prio        = null,
+                    error       = null,
+                    invalid     = null,
+                    propertyName= "";
+
+                property = this._property();
+                if (property !== null){
+
+                    tokenStream.mustMatch(Tokens.COLON);
+                    this._readWhitespace();
+
+                    expr = this._expr();
+                    if (!expr || expr.length === 0){
+                        this._unexpectedToken(tokenStream.LT(1));
+                    }
+
+                    prio = this._prio();
+                    propertyName = property.toString();
+                    if (this.options.starHack && property.hack == "*" ||
+                            this.options.underscoreHack && property.hack == "_") {
+
+                        propertyName = property.text;
+                    }
+
+                    try {
+                        this._validateProperty(propertyName, expr);
+                    } catch (ex) {
+                        invalid = ex;
+                    }
+
+                    this.fire({
+                        type:       "property",
+                        property:   property,
+                        value:      expr,
+                        important:  prio,
+                        line:       property.line,
+                        col:        property.col,
+                        invalid:    invalid
+                    });
+
+                    return true;
+                } else {
+                    return false;
+                }
+            },
+
+            _prio: function(){
+
+                var tokenStream = this._tokenStream,
+                    result      = tokenStream.match(Tokens.IMPORTANT_SYM);
+
+                this._readWhitespace();
+                return result;
+            },
+
+            _expr: function(){
+
+                var tokenStream = this._tokenStream,
+                    values      = [],
+                    value       = null,
+                    operator    = null;
+
+                value = this._term();
+                if (value !== null){
+
+                    values.push(value);
+
+                    do {
+                        operator = this._operator();
+                        if (operator){
+                            values.push(operator);
+                        } /*else {
+							values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));
+							valueParts = [];
+						}*/
+
+                        value = this._term();
+
+                        if (value === null){
+                            break;
+                        } else {
+                            values.push(value);
+                        }
+                    } while(true);
+                }
+
+                return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null;
+            },
+
+            _term: function(){
+
+                var tokenStream = this._tokenStream,
+                    unary       = null,
+                    value       = null,
+                    token,
+                    line,
+                    col;
+                unary = this._unary_operator();
+                if (unary !== null){
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+                }
+                if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){
+
+                    value = this._ie_function();
+                    if (unary === null){
+                        line = tokenStream.token().startLine;
+                        col = tokenStream.token().startCol;
+                    }
+                } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH,
+                        Tokens.ANGLE, Tokens.TIME,
+                        Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){
+
+                    value = tokenStream.token().value;
+                    if (unary === null){
+                        line = tokenStream.token().startLine;
+                        col = tokenStream.token().startCol;
+                    }
+                    this._readWhitespace();
+                } else {
+                    token = this._hexcolor();
+                    if (token === null){
+                        if (unary === null){
+                            line = tokenStream.LT(1).startLine;
+                            col = tokenStream.LT(1).startCol;
+                        }
+                        if (value === null){
+                            if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){
+                                value = this._ie_function();
+                            } else {
+                                value = this._function();
+                            }
+                        }
+
+                    } else {
+                        value = token.value;
+                        if (unary === null){
+                            line = token.startLine;
+                            col = token.startCol;
+                        }
+                    }
+
+                }
+
+                return value !== null ?
+                        new PropertyValuePart(unary !== null ? unary + value : value, line, col) :
+                        null;
+
+            },
+
+            _function: function(){
+
+                var tokenStream = this._tokenStream,
+                    functionText = null,
+                    expr        = null,
+                    lt;
+
+                if (tokenStream.match(Tokens.FUNCTION)){
+                    functionText = tokenStream.token().value;
+                    this._readWhitespace();
+                    expr = this._expr();
+                    functionText += expr;
+                    if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){
+                        do {
+
+                            if (this._readWhitespace()){
+                                functionText += tokenStream.token().value;
+                            }
+                            if (tokenStream.LA(0) == Tokens.COMMA){
+                                functionText += tokenStream.token().value;
+                            }
+
+                            tokenStream.match(Tokens.IDENT);
+                            functionText += tokenStream.token().value;
+
+                            tokenStream.match(Tokens.EQUALS);
+                            functionText += tokenStream.token().value;
+                            lt = tokenStream.peek();
+                            while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){
+                                tokenStream.get();
+                                functionText += tokenStream.token().value;
+                                lt = tokenStream.peek();
+                            }
+                        } while(tokenStream.match([Tokens.COMMA, Tokens.S]));
+                    }
+
+                    tokenStream.match(Tokens.RPAREN);
+                    functionText += ")";
+                    this._readWhitespace();
+                }
+
+                return functionText;
+            },
+
+            _ie_function: function(){
+
+                var tokenStream = this._tokenStream,
+                    functionText = null,
+                    expr        = null,
+                    lt;
+                if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){
+                    functionText = tokenStream.token().value;
+
+                    do {
+
+                        if (this._readWhitespace()){
+                            functionText += tokenStream.token().value;
+                        }
+                        if (tokenStream.LA(0) == Tokens.COMMA){
+                            functionText += tokenStream.token().value;
+                        }
+
+                        tokenStream.match(Tokens.IDENT);
+                        functionText += tokenStream.token().value;
+
+                        tokenStream.match(Tokens.EQUALS);
+                        functionText += tokenStream.token().value;
+                        lt = tokenStream.peek();
+                        while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){
+                            tokenStream.get();
+                            functionText += tokenStream.token().value;
+                            lt = tokenStream.peek();
+                        }
+                    } while(tokenStream.match([Tokens.COMMA, Tokens.S]));
+
+                    tokenStream.match(Tokens.RPAREN);
+                    functionText += ")";
+                    this._readWhitespace();
+                }
+
+                return functionText;
+            },
+
+            _hexcolor: function(){
+
+                var tokenStream = this._tokenStream,
+                    token = null,
+                    color;
+
+                if(tokenStream.match(Tokens.HASH)){
+
+                    token = tokenStream.token();
+                    color = token.value;
+                    if (!/#[a-f0-9]{3,6}/i.test(color)){
+                        throw new SyntaxError("Expected a hex color but found '" + color + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);
+                    }
+                    this._readWhitespace();
+                }
+
+                return token;
+            },
+
+            _keyframes: function(){
+                var tokenStream = this._tokenStream,
+                    token,
+                    tt,
+                    name,
+                    prefix = "";
+
+                tokenStream.mustMatch(Tokens.KEYFRAMES_SYM);
+                token = tokenStream.token();
+                if (/^@\-([^\-]+)\-/.test(token.value)) {
+                    prefix = RegExp.$1;
+                }
+
+                this._readWhitespace();
+                name = this._keyframe_name();
+
+                this._readWhitespace();
+                tokenStream.mustMatch(Tokens.LBRACE);
+
+                this.fire({
+                    type:   "startkeyframes",
+                    name:   name,
+                    prefix: prefix,
+                    line:   token.startLine,
+                    col:    token.startCol
+                });
+
+                this._readWhitespace();
+                tt = tokenStream.peek();
+                while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) {
+                    this._keyframe_rule();
+                    this._readWhitespace();
+                    tt = tokenStream.peek();
+                }
+
+                this.fire({
+                    type:   "endkeyframes",
+                    name:   name,
+                    prefix: prefix,
+                    line:   token.startLine,
+                    col:    token.startCol
+                });
+
+                this._readWhitespace();
+                tokenStream.mustMatch(Tokens.RBRACE);
+
+            },
+
+            _keyframe_name: function(){
+                var tokenStream = this._tokenStream,
+                    token;
+
+                tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);
+                return SyntaxUnit.fromToken(tokenStream.token());
+            },
+
+            _keyframe_rule: function(){
+                var tokenStream = this._tokenStream,
+                    token,
+                    keyList = this._key_list();
+
+                this.fire({
+                    type:   "startkeyframerule",
+                    keys:   keyList,
+                    line:   keyList[0].line,
+                    col:    keyList[0].col
+                });
+
+                this._readDeclarations(true);
+
+                this.fire({
+                    type:   "endkeyframerule",
+                    keys:   keyList,
+                    line:   keyList[0].line,
+                    col:    keyList[0].col
+                });
+
+            },
+
+            _key_list: function(){
+                var tokenStream = this._tokenStream,
+                    token,
+                    key,
+                    keyList = [];
+                keyList.push(this._key());
+
+                this._readWhitespace();
+
+                while(tokenStream.match(Tokens.COMMA)){
+                    this._readWhitespace();
+                    keyList.push(this._key());
+                    this._readWhitespace();
+                }
+
+                return keyList;
+            },
+
+            _key: function(){
+
+                var tokenStream = this._tokenStream,
+                    token;
+
+                if (tokenStream.match(Tokens.PERCENTAGE)){
+                    return SyntaxUnit.fromToken(tokenStream.token());
+                } else if (tokenStream.match(Tokens.IDENT)){
+                    token = tokenStream.token();
+
+                    if (/from|to/i.test(token.value)){
+                        return SyntaxUnit.fromToken(token);
+                    }
+
+                    tokenStream.unget();
+                }
+                this._unexpectedToken(tokenStream.LT(1));
+            },
+            _skipCruft: function(){
+                while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){
+                }
+            },
+            _readDeclarations: function(checkStart, readMargins){
+                var tokenStream = this._tokenStream,
+                    tt;
+
+
+                this._readWhitespace();
+
+                if (checkStart){
+                    tokenStream.mustMatch(Tokens.LBRACE);
+                }
+
+                this._readWhitespace();
+
+                try {
+
+                    while(true){
+
+                        if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){
+                        } else if (this._declaration()){
+                            if (!tokenStream.match(Tokens.SEMICOLON)){
+                                break;
+                            }
+                        } else {
+                            break;
+                        }
+                        this._readWhitespace();
+                    }
+
+                    tokenStream.mustMatch(Tokens.RBRACE);
+                    this._readWhitespace();
+
+                } catch (ex) {
+                    if (ex instanceof SyntaxError && !this.options.strict){
+                        this.fire({
+                            type:       "error",
+                            error:      ex,
+                            message:    ex.message,
+                            line:       ex.line,
+                            col:        ex.col
+                        });
+                        tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]);
+                        if (tt == Tokens.SEMICOLON){
+                            this._readDeclarations(false, readMargins);
+                        } else if (tt != Tokens.RBRACE){
+                            throw ex;
+                        }
+
+                    } else {
+                        throw ex;
+                    }
+                }
+
+            },
+            _readWhitespace: function(){
+
+                var tokenStream = this._tokenStream,
+                    ws = "";
+
+                while(tokenStream.match(Tokens.S)){
+                    ws += tokenStream.token().value;
+                }
+
+                return ws;
+            },
+            _unexpectedToken: function(token){
+                throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);
+            },
+            _verifyEnd: function(){
+                if (this._tokenStream.LA(1) != Tokens.EOF){
+                    this._unexpectedToken(this._tokenStream.LT(1));
+                }
+            },
+            _validateProperty: function(property, value){
+                Validation.validate(property, value);
+            },
+
+            parse: function(input){
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._stylesheet();
+            },
+
+            parseStyleSheet: function(input){
+                return this.parse(input);
+            },
+
+            parseMediaQuery: function(input){
+                this._tokenStream = new TokenStream(input, Tokens);
+                var result = this._media_query();
+                this._verifyEnd();
+                return result;
+            },
+            parsePropertyValue: function(input){
+
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._readWhitespace();
+
+                var result = this._expr();
+                this._readWhitespace();
+                this._verifyEnd();
+                return result;
+            },
+            parseRule: function(input){
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._readWhitespace();
+
+                var result = this._ruleset();
+                this._readWhitespace();
+                this._verifyEnd();
+                return result;
+            },
+            parseSelector: function(input){
+
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._readWhitespace();
+
+                var result = this._selector();
+                this._readWhitespace();
+                this._verifyEnd();
+                return result;
+            },
+            parseStyleAttribute: function(input){
+                input += "}"; // for error recovery in _readDeclarations()
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._readDeclarations();
+            }
+        };
+    for (prop in additions){
+        if (additions.hasOwnProperty(prop)){
+            proto[prop] = additions[prop];
+        }
+    }
+
+    return proto;
+}();
+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: true },
+    "animation-direction"           : { multi: "normal | alternate", comma: true },
+    "animation-duration"            : { multi: "<time>", comma: true },
+    "animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "animation-name"                : { multi: "none | <ident>", comma: true },
+    "animation-play-state"          : { multi: "running | paused", comma: true },
+    "animation-timing-function"     : 1,
+    "-moz-animation-delay"               : { multi: "<time>", comma: true },
+    "-moz-animation-direction"           : { multi: "normal | alternate", comma: true },
+    "-moz-animation-duration"            : { multi: "<time>", comma: true },
+    "-moz-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "-moz-animation-name"                : { multi: "none | <ident>", comma: true },
+    "-moz-animation-play-state"          : { multi: "running | paused", comma: true },
+
+    "-ms-animation-delay"               : { multi: "<time>", comma: true },
+    "-ms-animation-direction"           : { multi: "normal | alternate", comma: true },
+    "-ms-animation-duration"            : { multi: "<time>", comma: true },
+    "-ms-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "-ms-animation-name"                : { multi: "none | <ident>", comma: true },
+    "-ms-animation-play-state"          : { multi: "running | paused", comma: true },
+
+    "-webkit-animation-delay"               : { multi: "<time>", comma: true },
+    "-webkit-animation-direction"           : { multi: "normal | alternate", comma: true },
+    "-webkit-animation-duration"            : { multi: "<time>", comma: true },
+    "-webkit-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "-webkit-animation-name"                : { multi: "none | <ident>", comma: true },
+    "-webkit-animation-play-state"          : { multi: "running | paused", comma: true },
+
+    "-o-animation-delay"               : { multi: "<time>", comma: true },
+    "-o-animation-direction"           : { multi: "normal | alternate", comma: true },
+    "-o-animation-duration"            : { multi: "<time>", comma: true },
+    "-o-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "-o-animation-name"                : { multi: "none | <ident>", comma: true },
+    "-o-animation-play-state"          : { multi: "running | paused", comma: true },
+
+    "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 (expression) {
+        var simple      = "<angle> | leftwards | rightwards | inherit",
+            direction   = "left-side | far-left | left | center-left | center | center-right | right | far-right | right-side",
+            behind      = false,
+            valid       = false,
+            part;
+
+        if (!ValidationTypes.isAny(expression, simple)) {
+            if (ValidationTypes.isAny(expression, "behind")) {
+                behind = true;
+                valid = true;
+            }
+
+            if (ValidationTypes.isAny(expression, direction)) {
+                valid = true;
+                if (!behind) {
+                    ValidationTypes.isAny(expression, "behind");
+                }
+            }
+        }
+
+        if (expression.hasNext()) {
+            part = expression.next();
+            if (valid) {
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected (<'azimuth'>) but found '" + part + "'.", part.line, part.col);
+            }
+        }
+    },
+    "backface-visibility"           : "visible | hidden",
+    "background"                    : 1,
+    "background-attachment"         : { multi: "<attachment>", comma: true },
+    "background-clip"               : { multi: "<box>", comma: true },
+    "background-color"              : "<color> | inherit",
+    "background-image"              : { multi: "<bg-image>", comma: true },
+    "background-origin"             : { multi: "<box>", comma: true },
+    "background-position"           : { multi: "<bg-position>", comma: true },
+    "background-repeat"             : { multi: "<repeat-style>" },
+    "background-size"               : { multi: "<bg-size>", comma: true },
+    "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(expression) {
+
+        var valid   = false,
+            numeric = "<number> | <percentage>",
+            fill    = false,
+            count   = 0,
+            max     = 4,
+            part;
+
+        if (ValidationTypes.isAny(expression, "fill")) {
+            fill = true;
+            valid = true;
+        }
+
+        while (expression.hasNext() && count < max) {
+            valid = ValidationTypes.isAny(expression, numeric);
+            if (!valid) {
+                break;
+            }
+            count++;
+        }
+
+
+        if (!fill) {
+            ValidationTypes.isAny(expression, "fill");
+        } else {
+            valid = true;
+        }
+
+        if (expression.hasNext()) {
+            part = expression.next();
+            if (valid) {
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected ([<number> | <percentage>]{1,4} && fill?) but found '" + part + "'.", part.line, part.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(expression) {
+
+        var valid   = false,
+            numeric = "<length> | <percentage>",
+            slash   = false,
+            fill    = false,
+            count   = 0,
+            max     = 8,
+            part;
+
+        while (expression.hasNext() && count < max) {
+            valid = ValidationTypes.isAny(expression, numeric);
+            if (!valid) {
+
+                if (expression.peek() == "/" && count > 1 && !slash) {
+                    slash = true;
+                    max = count + 5;
+                    expression.next();
+                } else {
+                    break;
+                }
+            }
+            count++;
+        }
+
+        if (expression.hasNext()) {
+            part = expression.next();
+            if (valid) {
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected (<'border-radius'>) but found '" + part + "'.", part.line, part.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",        //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/
+    "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 (expression) {
+        var result      = false,
+            part;
+
+        if (!ValidationTypes.isAny(expression, "none")) {
+            Validation.multiProperty("<shadow>", expression, true, Infinity);
+        } else {
+            if (expression.hasNext()) {
+                part = expression.next();
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.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",                      //http://www.w3.org/TR/css3-multicol/
+    "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"
+};
+function PropertyName(text, hack, line, col){
+
+    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE);
+    this.hack = hack;
+
+}
+
+PropertyName.prototype = new SyntaxUnit();
+PropertyName.prototype.constructor = PropertyName;
+PropertyName.prototype.toString = function(){
+    return (this.hack ? this.hack : "") + this.text;
+};
+function PropertyValue(parts, line, col){
+
+    SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE);
+    this.parts = parts;
+
+}
+
+PropertyValue.prototype = new SyntaxUnit();
+PropertyValue.prototype.constructor = PropertyValue;
+function PropertyValueIterator(value){
+    this._i = 0;
+    this._parts = value.parts;
+    this._marks = [];
+    this.value = value;
+
+}
+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(count){
+    return this.hasNext() ? this._parts[this._i + (count || 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(){
+    if (this._marks.length){
+        this._i = this._marks.pop();
+    }
+};
+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)){  //dimension
+        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";
+                break;
+
+        }
+
+    } else if (/^([+\-]?[\d\.]+)%$/i.test(text)){  //percentage
+        this.type = "percentage";
+        this.value = +RegExp.$1;
+    } else if (/^([+\-]?[\d\.]+)%$/i.test(text)){  //percentage
+        this.type = "percentage";
+        this.value = +RegExp.$1;
+    } else if (/^([+\-]?\d+)$/i.test(text)){  //integer
+        this.type = "integer";
+        this.value = +RegExp.$1;
+    } else if (/^([+\-]?[\d\.]+)$/i.test(text)){  //number
+        this.type = "number";
+        this.value = +RegExp.$1;
+
+    } else if (/^#([a-f0-9]{3,6})/i.test(text)){  //hexcolor
+        this.type = "color";
+        temp = RegExp.$1;
+        if (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);
+        } else {
+            this.red    = parseInt(temp.substring(0,2),16);
+            this.green  = parseInt(temp.substring(2,4),16);
+            this.blue   = parseInt(temp.substring(4,6),16);
+        }
+    } else if (/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(text)){ //rgb() color with absolute numbers
+        this.type   = "color";
+        this.red    = +RegExp.$1;
+        this.green  = +RegExp.$2;
+        this.blue   = +RegExp.$3;
+    } else if (/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //rgb() color with percentages
+        this.type   = "color";
+        this.red    = +RegExp.$1 * 255 / 100;
+        this.green  = +RegExp.$2 * 255 / 100;
+        this.blue   = +RegExp.$3 * 255 / 100;
+    } else if (/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with absolute numbers
+        this.type   = "color";
+        this.red    = +RegExp.$1;
+        this.green  = +RegExp.$2;
+        this.blue   = +RegExp.$3;
+        this.alpha  = +RegExp.$4;
+    } else if (/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with percentages
+        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;
+    } else if (/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //hsl()
+        this.type   = "color";
+        this.hue    = +RegExp.$1;
+        this.saturation = +RegExp.$2 / 100;
+        this.lightness  = +RegExp.$3 / 100;
+    } else if (/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //hsla() color with percentages
+        this.type   = "color";
+        this.hue    = +RegExp.$1;
+        this.saturation = +RegExp.$2 / 100;
+        this.lightness  = +RegExp.$3 / 100;
+        this.alpha  = +RegExp.$4;
+    } else if (/^url\(["']?([^\)"']+)["']?\)/i.test(text)){ //URI
+        this.type   = "uri";
+        this.uri    = RegExp.$1;
+    } else if (/^([^\(]+)\(/i.test(text)){
+        this.type   = "function";
+        this.name   = RegExp.$1;
+        this.value  = text;
+    } else if (/^["'][^"']*["']/.test(text)){    //string
+        this.type   = "string";
+        this.value  = eval(text);
+    } else if (Colors[text.toLowerCase()]){  //named color
+        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);
+    } else if (/^[\,\/]$/.test(text)){
+        this.type   = "operator";
+        this.value  = text;
+    } else if (/^[a-z\-\u0080-\uFFFF][a-z0-9\-\u0080-\uFFFF]*$/i.test(text)){
+        this.type   = "identifier";
+        this.value  = text;
+    }
+
+}
+
+PropertyValuePart.prototype = new SyntaxUnit();
+PropertyValuePart.prototype.constructor = PropertyValuePart;
+PropertyValuePart.fromToken = function(token){
+    return new PropertyValuePart(token.value, token.startLine, token.startCol);
+};
+var Pseudos = {
+    ":first-letter": 1,
+    ":first-line":   1,
+    ":before":       1,
+    ":after":        1
+};
+
+Pseudos.ELEMENT = 1;
+Pseudos.CLASS = 2;
+
+Pseudos.isElement = function(pseudo){
+    return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT;
+};
+function Selector(parts, line, col){
+
+    SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE);
+    this.parts = parts;
+    this.specificity = Specificity.calculate(this);
+
+}
+
+Selector.prototype = new SyntaxUnit();
+Selector.prototype.constructor = Selector;
+function SelectorPart(elementName, modifiers, text, line, col){
+
+    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE);
+    this.elementName = elementName;
+    this.modifiers = modifiers;
+
+}
+
+SelectorPart.prototype = new SyntaxUnit();
+SelectorPart.prototype.constructor = SelectorPart;
+function SelectorSubPart(text, type, line, col){
+
+    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE);
+    this.type = type;
+    this.args = [];
+
+}
+
+SelectorSubPart.prototype = new SyntaxUnit();
+SelectorSubPart.prototype.constructor = SelectorSubPart;
+function Specificity(a, b, c, d){
+    this.a = a;
+    this.b = b;
+    this.c = c;
+    this.d = d;
+}
+
+Specificity.prototype = {
+    constructor: Specificity,
+    compare: function(other){
+        var comps = ["a", "b", "c", "d"],
+            i, len;
+
+        for (i=0, len=comps.length; i < len; i++){
+            if (this[comps[i]] < other[comps[i]]){
+                return -1;
+            } else if (this[comps[i]] > other[comps[i]]){
+                return 1;
+            }
+        }
+
+        return 0;
+    },
+    valueOf: function(){
+        return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d;
+    },
+    toString: function(){
+        return this.a + "," + this.b + "," + this.c + "," + this.d;
+    }
+
+};
+Specificity.calculate = function(selector){
+
+    var i, len,
+        part,
+        b=0, c=0, d=0;
+
+    function updateValues(part){
+
+        var i, j, len, num,
+            elementName = part.elementName ? part.elementName.text : "",
+            modifier;
+
+        if (elementName && elementName.charAt(elementName.length-1) != "*") {
+            d++;
+        }
+
+        for (i=0, len=part.modifiers.length; i < len; i++){
+            modifier = part.modifiers[i];
+            switch(modifier.type){
+                case "class":
+                case "attribute":
+                    c++;
+                    break;
+
+                case "id":
+                    b++;
+                    break;
+
+                case "pseudo":
+                    if (Pseudos.isElement(modifier.text)){
+                        d++;
+                    } else {
+                        c++;
+                    }
+                    break;
+
+                case "not":
+                    for (j=0, num=modifier.args.length; j < num; j++){
+                        updateValues(modifier.args[j]);
+                    }
+            }
+         }
+    }
+
+    for (i=0, len=selector.parts.length; i < len; i++){
+        part = selector.parts[i];
+
+        if (part instanceof SelectorPart){
+            updateValues(part);
+        }
+    }
+
+    return new Specificity(0, b, c, d);
+};
+
+var h = /^[0-9a-fA-F]$/,
+    nonascii = /^[\u0080-\uFFFF]$/,
+    nl = /\n|\r\n|\r|\f/;
+
+
+function isHexDigit(c){
+    return c !== null && h.test(c);
+}
+
+function isDigit(c){
+    return c !== null && /\d/.test(c);
+}
+
+function isWhitespace(c){
+    return c !== null && /\s/.test(c);
+}
+
+function isNewLine(c){
+    return c !== null && nl.test(c);
+}
+
+function isNameStart(c){
+    return c !== null && (/[a-z_\u0080-\uFFFF\\]/i.test(c));
+}
+
+function isNameChar(c){
+    return c !== null && (isNameStart(c) || /[0-9\-\\]/.test(c));
+}
+
+function isIdentStart(c){
+    return c !== null && (isNameStart(c) || /\-\\/.test(c));
+}
+
+function mix(receiver, supplier){
+	for (var prop in supplier){
+		if (supplier.hasOwnProperty(prop)){
+			receiver[prop] = supplier[prop];
+		}
+	}
+	return receiver;
+}
+function TokenStream(input){
+	TokenStreamBase.call(this, input, Tokens);
+}
+
+TokenStream.prototype = mix(new TokenStreamBase(), {
+    _getToken: function(channel){
+
+        var c,
+            reader = this._reader,
+            token   = null,
+            startLine   = reader.getLine(),
+            startCol    = reader.getCol();
+
+        c = reader.read();
+
+
+        while(c){
+            switch(c){
+                case "/":
+
+                    if(reader.peek() == "*"){
+                        token = this.commentToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+                case "|":
+                case "~":
+                case "^":
+                case "$":
+                case "*":
+                    if(reader.peek() == "="){
+                        token = this.comparisonToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+                case "\"":
+                case "'":
+                    token = this.stringToken(c, startLine, startCol);
+                    break;
+                case "#":
+                    if (isNameChar(reader.peek())){
+                        token = this.hashToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+                case ".":
+                    if (isDigit(reader.peek())){
+                        token = this.numberToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+                case "-":
+                    if (reader.peek() == "-"){  //could be closing HTML-style comment
+                        token = this.htmlCommentEndToken(c, startLine, startCol);
+                    } else if (isNameStart(reader.peek())){
+                        token = this.identOrFunctionToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+                case "!":
+                    token = this.importantToken(c, startLine, startCol);
+                    break;
+                case "@":
+                    token = this.atRuleToken(c, startLine, startCol);
+                    break;
+                case ":":
+                    token = this.notToken(c, startLine, startCol);
+                    break;
+                case "<":
+                    token = this.htmlCommentStartToken(c, startLine, startCol);
+                    break;
+                case "U":
+                case "u":
+                    if (reader.peek() == "+"){
+                        token = this.unicodeRangeToken(c, startLine, startCol);
+                        break;
+                    }
+                default:
+                    if (isDigit(c)){
+                        token = this.numberToken(c, startLine, startCol);
+                    } else
+                    if (isWhitespace(c)){
+                        token = this.whitespaceToken(c, startLine, startCol);
+                    } else
+                    if (isIdentStart(c)){
+                        token = this.identOrFunctionToken(c, startLine, startCol);
+                    } else
+                    {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+
+
+
+
+
+
+            }
+            break;
+        }
+
+        if (!token && c === null){
+            token = this.createToken(Tokens.EOF,null,startLine,startCol);
+        }
+
+        return token;
+    },
+    createToken: function(tt, value, startLine, startCol, options){
+        var reader = this._reader;
+        options = options || {};
+
+        return {
+            value:      value,
+            type:       tt,
+            channel:    options.channel,
+            hide:       options.hide || false,
+            startLine:  startLine,
+            startCol:   startCol,
+            endLine:    reader.getLine(),
+            endCol:     reader.getCol()
+        };
+    },
+    atRuleToken: function(first, startLine, startCol){
+        var rule    = first,
+            reader  = this._reader,
+            tt      = Tokens.CHAR,
+            valid   = false,
+            ident,
+            c;
+        reader.mark();
+        ident = this.readName();
+        rule = first + ident;
+        tt = Tokens.type(rule.toLowerCase());
+        if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){
+            if (rule.length > 1){
+                tt = Tokens.UNKNOWN_SYM;
+            } else {
+                tt = Tokens.CHAR;
+                rule = first;
+                reader.reset();
+            }
+        }
+
+        return this.createToken(tt, rule, startLine, startCol);
+    },
+    charToken: function(c, startLine, startCol){
+        var tt = Tokens.type(c);
+
+        if (tt == -1){
+            tt = Tokens.CHAR;
+        }
+
+        return this.createToken(tt, c, startLine, startCol);
+    },
+    commentToken: function(first, startLine, startCol){
+        var reader  = this._reader,
+            comment = this.readComment(first);
+
+        return this.createToken(Tokens.COMMENT, comment, startLine, startCol);
+    },
+    comparisonToken: function(c, startLine, startCol){
+        var reader  = this._reader,
+            comparison  = c + reader.read(),
+            tt      = Tokens.type(comparison) || Tokens.CHAR;
+
+        return this.createToken(tt, comparison, startLine, startCol);
+    },
+    hashToken: function(first, startLine, startCol){
+        var reader  = this._reader,
+            name    = this.readName(first);
+
+        return this.createToken(Tokens.HASH, name, startLine, startCol);
+    },
+    htmlCommentStartToken: function(first, startLine, startCol){
+        var reader      = this._reader,
+            text        = first;
+
+        reader.mark();
+        text += reader.readCount(3);
+
+        if (text == "<!--"){
+            return this.createToken(Tokens.CDO, text, startLine, startCol);
+        } else {
+            reader.reset();
+            return this.charToken(first, startLine, startCol);
+        }
+    },
+    htmlCommentEndToken: function(first, startLine, startCol){
+        var reader      = this._reader,
+            text        = first;
+
+        reader.mark();
+        text += reader.readCount(2);
+
+        if (text == "-->"){
+            return this.createToken(Tokens.CDC, text, startLine, startCol);
+        } else {
+            reader.reset();
+            return this.charToken(first, startLine, startCol);
+        }
+    },
+    identOrFunctionToken: function(first, startLine, startCol){
+        var reader  = this._reader,
+            ident   = this.readName(first),
+            tt      = Tokens.IDENT;
+        if (reader.peek() == "("){
+            ident += reader.read();
+            if (ident.toLowerCase() == "url("){
+                tt = Tokens.URI;
+                ident = this.readURI(ident);
+                if (ident.toLowerCase() == "url("){
+                    tt = Tokens.FUNCTION;
+                }
+            } else {
+                tt = Tokens.FUNCTION;
+            }
+        } else if (reader.peek() == ":"){  //might be an IE function
+            if (ident.toLowerCase() == "progid"){
+                ident += reader.readTo("(");
+                tt = Tokens.IE_FUNCTION;
+            }
+        }
+
+        return this.createToken(tt, ident, startLine, startCol);
+    },
+    importantToken: function(first, startLine, startCol){
+        var reader      = this._reader,
+            important   = first,
+            tt          = Tokens.CHAR,
+            temp,
+            c;
+
+        reader.mark();
+        c = reader.read();
+
+        while(c){
+            if (c == "/"){
+                if (reader.peek() != "*"){
+                    break;
+                } else {
+                    temp = this.readComment(c);
+                    if (temp === ""){    //broken!
+                        break;
+                    }
+                }
+            } else if (isWhitespace(c)){
+                important += c + this.readWhitespace();
+            } else if (/i/i.test(c)){
+                temp = reader.readCount(8);
+                if (/mportant/i.test(temp)){
+                    important += c + temp;
+                    tt = Tokens.IMPORTANT_SYM;
+
+                }
+                break;  //we're done
+            } else {
+                break;
+            }
+
+            c = reader.read();
+        }
+
+        if (tt == Tokens.CHAR){
+            reader.reset();
+            return this.charToken(first, startLine, startCol);
+        } else {
+            return this.createToken(tt, important, startLine, startCol);
+        }
+
+
+    },
+    notToken: function(first, startLine, startCol){
+        var reader      = this._reader,
+            text        = first;
+
+        reader.mark();
+        text += reader.readCount(4);
+
+        if (text.toLowerCase() == ":not("){
+            return this.createToken(Tokens.NOT, text, startLine, startCol);
+        } else {
+            reader.reset();
+            return this.charToken(first, startLine, startCol);
+        }
+    },
+    numberToken: function(first, startLine, startCol){
+        var reader  = this._reader,
+            value   = this.readNumber(first),
+            ident,
+            tt      = Tokens.NUMBER,
+            c       = reader.peek();
+
+        if (isIdentStart(c)){
+            ident = this.readName(reader.read());
+            value += ident;
+
+            if (/^em$|^ex$|^px$|^gd$|^rem$|^vw$|^vh$|^vm$|^ch$|^cm$|^mm$|^in$|^pt$|^pc$/i.test(ident)){
+                tt = Tokens.LENGTH;
+            } else if (/^deg|^rad$|^grad$/i.test(ident)){
+                tt = Tokens.ANGLE;
+            } else if (/^ms$|^s$/i.test(ident)){
+                tt = Tokens.TIME;
+            } else if (/^hz$|^khz$/i.test(ident)){
+                tt = Tokens.FREQ;
+            } else if (/^dpi$|^dpcm$/i.test(ident)){
+                tt = Tokens.RESOLUTION;
+            } else {
+                tt = Tokens.DIMENSION;
+            }
+
+        } else if (c == "%"){
+            value += reader.read();
+            tt = Tokens.PERCENTAGE;
+        }
+
+        return this.createToken(tt, value, startLine, startCol);
+    },
+    stringToken: function(first, startLine, startCol){
+        var delim   = first,
+            string  = first,
+            reader  = this._reader,
+            prev    = first,
+            tt      = Tokens.STRING,
+            c       = reader.read();
+
+        while(c){
+            string += c;
+            if (c == delim && prev != "\\"){
+                break;
+            }
+            if (isNewLine(reader.peek()) && c != "\\"){
+                tt = Tokens.INVALID;
+                break;
+            }
+            prev = c;
+            c = reader.read();
+        }
+        if (c === null){
+            tt = Tokens.INVALID;
+        }
+
+        return this.createToken(tt, string, startLine, startCol);
+    },
+
+    unicodeRangeToken: function(first, startLine, startCol){
+        var reader  = this._reader,
+            value   = first,
+            temp,
+            tt      = Tokens.CHAR;
+        if (reader.peek() == "+"){
+            reader.mark();
+            value += reader.read();
+            value += this.readUnicodeRangePart(true);
+            if (value.length == 2){
+                reader.reset();
+            } else {
+
+                tt = Tokens.UNICODE_RANGE;
+                if (value.indexOf("?") == -1){
+
+                    if (reader.peek() == "-"){
+                        reader.mark();
+                        temp = reader.read();
+                        temp += this.readUnicodeRangePart(false);
+                        if (temp.length == 1){
+                            reader.reset();
+                        } else {
+                            value += temp;
+                        }
+                    }
+
+                }
+            }
+        }
+
+        return this.createToken(tt, value, startLine, startCol);
+    },
+    whitespaceToken: function(first, startLine, startCol){
+        var reader  = this._reader,
+            value   = first + this.readWhitespace();
+        return this.createToken(Tokens.S, value, startLine, startCol);
+    },
+
+    readUnicodeRangePart: function(allowQuestionMark){
+        var reader  = this._reader,
+            part = "",
+            c       = reader.peek();
+        while(isHexDigit(c) && part.length < 6){
+            reader.read();
+            part += c;
+            c = reader.peek();
+        }
+        if (allowQuestionMark){
+            while(c == "?" && part.length < 6){
+                reader.read();
+                part += c;
+                c = reader.peek();
+            }
+        }
+
+        return part;
+    },
+
+    readWhitespace: function(){
+        var reader  = this._reader,
+            whitespace = "",
+            c       = reader.peek();
+
+        while(isWhitespace(c)){
+            reader.read();
+            whitespace += c;
+            c = reader.peek();
+        }
+
+        return whitespace;
+    },
+    readNumber: function(first){
+        var reader  = this._reader,
+            number  = first,
+            hasDot  = (first == "."),
+            c       = reader.peek();
+
+
+        while(c){
+            if (isDigit(c)){
+                number += reader.read();
+            } else if (c == "."){
+                if (hasDot){
+                    break;
+                } else {
+                    hasDot = true;
+                    number += reader.read();
+                }
+            } else {
+                break;
+            }
+
+            c = reader.peek();
+        }
+
+        return number;
+    },
+    readString: function(){
+        var reader  = this._reader,
+            delim   = reader.read(),
+            string  = delim,
+            prev    = delim,
+            c       = reader.peek();
+
+        while(c){
+            c = reader.read();
+            string += c;
+            if (c == delim && prev != "\\"){
+                break;
+            }
+            if (isNewLine(reader.peek()) && c != "\\"){
+                string = "";
+                break;
+            }
+            prev = c;
+            c = reader.peek();
+        }
+        if (c === null){
+            string = "";
+        }
+
+        return string;
+    },
+    readURI: function(first){
+        var reader  = this._reader,
+            uri     = first,
+            inner   = "",
+            c       = reader.peek();
+
+        reader.mark();
+        while(c && isWhitespace(c)){
+            reader.read();
+            c = reader.peek();
+        }
+        if (c == "'" || c == "\""){
+            inner = this.readString();
+        } else {
+            inner = this.readURL();
+        }
+
+        c = reader.peek();
+        while(c && isWhitespace(c)){
+            reader.read();
+            c = reader.peek();
+        }
+        if (inner === "" || c != ")"){
+            uri = first;
+            reader.reset();
+        } else {
+            uri += inner + reader.read();
+        }
+
+        return uri;
+    },
+    readURL: function(){
+        var reader  = this._reader,
+            url     = "",
+            c       = reader.peek();
+        while (/^[!#$%&\\*-~]$/.test(c)){
+            url += reader.read();
+            c = reader.peek();
+        }
+
+        return url;
+
+    },
+    readName: function(first){
+        var reader  = this._reader,
+            ident   = first || "",
+            c       = reader.peek();
+
+        while(true){
+            if (c == "\\"){
+                ident += this.readEscape(reader.read());
+                c = reader.peek();
+            } else if(c && isNameChar(c)){
+                ident += reader.read();
+                c = reader.peek();
+            } else {
+                break;
+            }
+        }
+
+        return ident;
+    },
+
+    readEscape: function(first){
+        var reader  = this._reader,
+            cssEscape = first || "",
+            i       = 0,
+            c       = reader.peek();
+
+        if (isHexDigit(c)){
+            do {
+                cssEscape += reader.read();
+                c = reader.peek();
+            } while(c && isHexDigit(c) && ++i < 6);
+        }
+
+        if (cssEscape.length == 3 && /\s/.test(c) ||
+            cssEscape.length == 7 || cssEscape.length == 1){
+                reader.read();
+        } else {
+            c = "";
+        }
+
+        return cssEscape + c;
+    },
+
+    readComment: function(first){
+        var reader  = this._reader,
+            comment = first || "",
+            c       = reader.read();
+
+        if (c == "*"){
+            while(c){
+                comment += c;
+                if (comment.length > 2 && c == "*" && reader.peek() == "/"){
+                    comment += reader.read();
+                    break;
+                }
+
+                c = reader.read();
+            }
+
+            return comment;
+        } else {
+            return "";
+        }
+
+    }
+});
+
+
+var Tokens  = [
+    { name: "CDO"},
+    { name: "CDC"},
+    { name: "S", whitespace: true/*, channel: "ws"*/},
+    { name: "COMMENT", comment: true, hide: true, 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 nameMap = [],
+        typeMap = {};
+
+    Tokens.UNKNOWN = -1;
+    Tokens.unshift({name:"EOF"});
+    for (var i=0, len = Tokens.length; i < len; i++){
+        nameMap.push(Tokens[i].name);
+        Tokens[Tokens[i].name] = i;
+        if (Tokens[i].text){
+            if (Tokens[i].text instanceof Array){
+                for (var j=0; j < Tokens[i].text.length; j++){
+                    typeMap[Tokens[i].text[j]] = i;
+                }
+            } else {
+                typeMap[Tokens[i].text] = i;
+            }
+        }
+    }
+
+    Tokens.name = function(tt){
+        return nameMap[tt];
+    };
+
+    Tokens.type = function(c){
+        return typeMap[c] || -1;
+    };
+
+})();
+var Validation = {
+
+    validate: function(property, value){
+        var name        = property.toString().toLowerCase(),
+            parts       = value.parts,
+            expression  = new PropertyValueIterator(value),
+            spec        = Properties[name],
+            part,
+            valid,
+            j, count,
+            msg,
+            types,
+            last,
+            literals,
+            max, multi, group;
+
+        if (!spec) {
+            if (name.indexOf("-") !== 0){    //vendor prefixed are ok
+                throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col);
+            }
+        } else if (typeof spec != "number"){
+            if (typeof spec == "string"){
+                if (spec.indexOf("||") > -1) {
+                    this.groupProperty(spec, expression);
+                } else {
+                    this.singleProperty(spec, expression, 1);
+                }
+
+            } else if (spec.multi) {
+                this.multiProperty(spec.multi, expression, spec.comma, spec.max || Infinity);
+            } else if (typeof spec == "function") {
+                spec(expression);
+            }
+
+        }
+
+    },
+
+    singleProperty: function(types, expression, max, partial) {
+
+        var result      = false,
+            value       = expression.value,
+            count       = 0,
+            part;
+
+        while (expression.hasNext() && count < max) {
+            result = ValidationTypes.isAny(expression, types);
+            if (!result) {
+                break;
+            }
+            count++;
+        }
+
+        if (!result) {
+            if (expression.hasNext() && !expression.isFirst()) {
+                part = expression.peek();
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                 throw new ValidationError("Expected (" + types + ") but found '" + value + "'.", value.line, value.col);
+            }
+        } else if (expression.hasNext()) {
+            part = expression.next();
+            throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+        }
+
+    },
+
+    multiProperty: function (types, expression, comma, max) {
+
+        var result      = false,
+            value       = expression.value,
+            count       = 0,
+            sep         = false,
+            part;
+
+        while(expression.hasNext() && !result && count < max) {
+            if (ValidationTypes.isAny(expression, types)) {
+                count++;
+                if (!expression.hasNext()) {
+                    result = true;
+
+                } else if (comma) {
+                    if (expression.peek() == ",") {
+                        part = expression.next();
+                    } else {
+                        break;
+                    }
+                }
+            } else {
+                break;
+
+            }
+        }
+
+        if (!result) {
+            if (expression.hasNext() && !expression.isFirst()) {
+                part = expression.peek();
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                part = expression.previous();
+                if (comma && part == ",") {
+                    throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+                } else {
+                    throw new ValidationError("Expected (" + types + ") but found '" + value + "'.", value.line, value.col);
+                }
+            }
+
+        } else if (expression.hasNext()) {
+            part = expression.next();
+            throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+        }
+
+    },
+
+    groupProperty: function (types, expression, comma) {
+
+        var result      = false,
+            value       = expression.value,
+            typeCount   = types.split("||").length,
+            groups      = { count: 0 },
+            partial     = false,
+            name,
+            part;
+
+        while(expression.hasNext() && !result) {
+            name = ValidationTypes.isAnyOfGroup(expression, types);
+            if (name) {
+                if (groups[name]) {
+                    break;
+                } else {
+                    groups[name] = 1;
+                    groups.count++;
+                    partial = true;
+
+                    if (groups.count == typeCount || !expression.hasNext()) {
+                        result = true;
+                    }
+                }
+            } else {
+                break;
+            }
+        }
+
+        if (!result) {
+            if (partial && expression.hasNext()) {
+                    part = expression.peek();
+                    throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected (" + types + ") but found '" + value + "'.", value.line, value.col);
+            }
+        } else if (expression.hasNext()) {
+            part = expression.next();
+            throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+        }
+    }
+
+
+
+};
+function ValidationError(message, line, col){
+    this.col = col;
+    this.line = line;
+    this.message = message;
+
+}
+ValidationError.prototype = new Error();
+var ValidationTypes = {
+
+    isLiteral: function (part, literals) {
+        var text = part.text.toString().toLowerCase(),
+            args = literals.split(" | "),
+            i, len, found = false;
+
+        for (i=0,len=args.length; i < len && !found; i++){
+            if (text == args[i].toLowerCase()){
+                found = true;
+            }
+        }
+
+        return found;
+    },
+
+    isSimple: function(type) {
+        return !!this.simple[type];
+    },
+
+    isComplex: function(type) {
+        return !!this.complex[type];
+    },
+    isAny: function (expression, types) {
+        var args = types.split(" | "),
+            i, len, found = false;
+
+        for (i=0,len=args.length; i < len && !found && expression.hasNext(); i++){
+            found = this.isType(expression, args[i]);
+        }
+
+        return found;
+    },
+    isAnyOfGroup: function(expression, types) {
+        var args = types.split(" || "),
+            i, len, found = false;
+
+        for (i=0,len=args.length; i < len && !found; i++){
+            found = this.isType(expression, args[i]);
+        }
+
+        return found ? args[i-1] : false;
+    },
+    isType: function (expression, type) {
+        var part = expression.peek(),
+            result = false;
+
+        if (type.charAt(0) != "<") {
+            result = this.isLiteral(part, type);
+            if (result) {
+                expression.next();
+            }
+        } else if (this.simple[type]) {
+            result = this.simple[type](part);
+            if (result) {
+                expression.next();
+            }
+        } else {
+            result = this.complex[type](expression);
+        }
+
+        return result;
+    },
+
+
+
+    simple: {
+
+        "<absolute-size>": function(part){
+            return ValidationTypes.isLiteral(part, "xx-small | x-small | small | medium | large | x-large | xx-large");
+        },
+
+        "<attachment>": function(part){
+            return ValidationTypes.isLiteral(part, "scroll | fixed | local");
+        },
+
+        "<attr>": function(part){
+            return part.type == "function" && part.name == "attr";
+        },
+
+        "<bg-image>": function(part){
+            return this["<image>"](part) || this["<gradient>"](part) ||  part == "none";
+        },
+
+        "<gradient>": function(part) {
+            return part.type == "function" && /^(?:\-(?:ms|moz|o|webkit)\-)?(?:repeating\-)?(?:radial\-|linear\-)?gradient/i.test(part);
+        },
+
+        "<box>": function(part){
+            return ValidationTypes.isLiteral(part, "padding-box | border-box | content-box");
+        },
+
+        "<content>": function(part){
+            return part.type == "function" && part.name == "content";
+        },
+
+        "<relative-size>": function(part){
+            return ValidationTypes.isLiteral(part, "smaller | larger");
+        },
+        "<ident>": function(part){
+            return part.type == "identifier";
+        },
+
+        "<length>": function(part){
+            return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0";
+        },
+
+        "<color>": function(part){
+            return part.type == "color" || part == "transparent";
+        },
+
+        "<number>": function(part){
+            return part.type == "number" || this["<integer>"](part);
+        },
+
+        "<integer>": function(part){
+            return part.type == "integer";
+        },
+
+        "<line>": function(part){
+            return part.type == "integer";
+        },
+
+        "<angle>": function(part){
+            return part.type == "angle";
+        },
+
+        "<uri>": function(part){
+            return part.type == "uri";
+        },
+
+        "<image>": function(part){
+            return this["<uri>"](part);
+        },
+
+        "<percentage>": function(part){
+            return part.type == "percentage" || part == "0";
+        },
+
+        "<border-width>": function(part){
+            return this["<length>"](part) || ValidationTypes.isLiteral(part, "thin | medium | thick");
+        },
+
+        "<border-style>": function(part){
+            return ValidationTypes.isLiteral(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset");
+        },
+
+        "<margin-width>": function(part){
+            return this["<length>"](part) || this["<percentage>"](part) || ValidationTypes.isLiteral(part, "auto");
+        },
+
+        "<padding-width>": function(part){
+            return this["<length>"](part) || this["<percentage>"](part);
+        },
+
+        "<shape>": function(part){
+            return part.type == "function" && (part.name == "rect" || part.name == "inset-rect");
+        },
+
+        "<time>": function(part) {
+            return part.type == "time";
+        }
+    },
+
+    complex: {
+
+        "<bg-position>": function(expression){
+            var types   = this,
+                result  = false,
+                numeric = "<percentage> | <length>",
+                xDir    = "left | center | right",
+                yDir    = "top | center | bottom",
+                part,
+                i, len;
+
+            if (ValidationTypes.isAny(expression, "top | bottom")) {
+                result = true;
+            } else {
+                if (ValidationTypes.isAny(expression, numeric)){
+                    if (expression.hasNext()){
+                        result = ValidationTypes.isAny(expression, numeric + " | " + yDir);
+                    }
+                } else if (ValidationTypes.isAny(expression, xDir)){
+                    if (expression.hasNext()){
+                        if (ValidationTypes.isAny(expression, yDir)){
+                            result = true;
+
+                            ValidationTypes.isAny(expression, numeric);
+
+                        } else if (ValidationTypes.isAny(expression, numeric)){
+                            if (ValidationTypes.isAny(expression, yDir)){
+                                ValidationTypes.isAny(expression, numeric);
+                            }
+
+                            result = true;
+                        }
+                    }
+                }
+            }
+
+
+            return result;
+        },
+
+        "<bg-size>": function(expression){
+            var types   = this,
+                result  = false,
+                numeric = "<percentage> | <length> | auto",
+                part,
+                i, len;
+
+            if (ValidationTypes.isAny(expression, "cover | contain")) {
+                result = true;
+            } else if (ValidationTypes.isAny(expression, numeric)) {
+                result = true;
+                ValidationTypes.isAny(expression, numeric);
+            }
+
+            return result;
+        },
+
+        "<repeat-style>": function(expression){
+            var result  = false,
+                values  = "repeat | space | round | no-repeat",
+                part;
+
+            if (expression.hasNext()){
+                part = expression.next();
+
+                if (ValidationTypes.isLiteral(part, "repeat-x | repeat-y")) {
+                    result = true;
+                } else if (ValidationTypes.isLiteral(part, values)) {
+                    result = true;
+
+                    if (expression.hasNext() && ValidationTypes.isLiteral(expression.peek(), values)) {
+                        expression.next();
+                    }
+                }
+            }
+
+            return result;
+
+        },
+
+        "<shadow>": function(expression) {
+            var result  = false,
+                count   = 0,
+                inset   = false,
+                color   = false,
+                part;
+
+            if (expression.hasNext()) {
+
+                if (ValidationTypes.isAny(expression, "inset")){
+                    inset = true;
+                }
+
+                if (ValidationTypes.isAny(expression, "<color>")) {
+                    color = true;
+                }
+
+                while (ValidationTypes.isAny(expression, "<length>") && count < 4) {
+                    count++;
+                }
+
+
+                if (expression.hasNext()) {
+                    if (!color) {
+                        ValidationTypes.isAny(expression, "<color>");
+                    }
+
+                    if (!inset) {
+                        ValidationTypes.isAny(expression, "inset");
+                    }
+
+                }
+
+                result = (count >= 2 && count <= 4);
+
+            }
+
+            return result;
+        },
+
+        "<x-one-radius>": function(expression) {
+            var result  = false,
+                count   = 0,
+                numeric = "<length> | <percentage>",
+                part;
+
+            if (ValidationTypes.isAny(expression, numeric)){
+                result = true;
+
+                ValidationTypes.isAny(expression, numeric);
+            }
+
+            return result;
+        }
+    }
+};
+
+
+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 rules      = [],
+        formatters = [],
+        api        = new parserlib.util.EventTarget();
+
+    api.version = "0.9.9";
+    api.addRule = function(rule){
+        rules.push(rule);
+        rules[rule.id] = rule;
+    };
+    api.clearRules = function(){
+        rules = [];
+    };
+    api.getRules = function(){
+        return [].concat(rules).sort(function(a,b){
+            return a.id > b.id ? 1 : 0;
+        });
+    };
+    api.getRuleset = function() {
+        var ruleset = {},
+            i = 0,
+            len = rules.length;
+
+        while (i < len){
+            ruleset[rules[i++].id] = 1;    //by default, everything is a warning
+        }
+
+        return ruleset;
+    };
+    api.addFormatter = function(formatter) {
+        formatters[formatter.id] = formatter;
+    };
+    api.getFormatter = function(formatId){
+        return formatters[formatId];
+    };
+    api.format = function(results, filename, formatId, options) {
+        var formatter = this.getFormatter(formatId),
+            result = null;
+
+        if (formatter){
+            result = formatter.startFormat();
+            result += formatter.formatResults(results, filename, options || {});
+            result += formatter.endFormat();
+        }
+
+        return result;
+    };
+    api.hasFormat = function(formatId){
+        return formatters.hasOwnProperty(formatId);
+    };
+    api.verify = function(text, ruleset){
+
+        var i       = 0,
+            len     = rules.length,
+            reporter,
+            lines,
+            report,
+            parser = new parserlib.css.Parser({ starHack: true, ieFilters: true,
+                                                underscoreHack: true, strict: false });
+        lines = text.replace(/\n\r?/g, "$split$").split('$split$');
+
+        if (!ruleset){
+            ruleset = this.getRuleset();
+        }
+
+        reporter = new Reporter(lines, ruleset);
+
+        ruleset.errors = 2;       //always report parsing errors as errors
+        for (i in ruleset){
+            if(ruleset.hasOwnProperty(i)){
+                if (rules[i]){
+                    rules[i].init(parser, reporter);
+                }
+            }
+        }
+        try {
+            parser.parse(text);
+        } catch (ex) {
+            reporter.error("Fatal error, cannot continue: " + ex.message, ex.line, ex.col, {});
+        }
+
+        report = {
+            messages    : reporter.messages,
+            stats       : reporter.stats
+        };
+        report.messages.sort(function (a, b){
+            if (a.rollup && !b.rollup){
+                return 1;
+            } else if (!a.rollup && b.rollup){
+                return -1;
+            } else {
+                return a.line - b.line;
+            }
+        });
+
+        return report;
+    };
+
+    return api;
+
+})();
+function Reporter(lines, ruleset){
+    this.messages = [];
+    this.stats = [];
+    this.lines = lines;
+    this.ruleset = ruleset;
+}
+
+Reporter.prototype = {
+    constructor: Reporter,
+    error: function(message, line, col, rule){
+        this.messages.push({
+            type    : "error",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule || {}
+        });
+    },
+    warn: function(message, line, col, rule){
+        this.report(message, line, col, rule);
+    },
+    report: function(message, line, col, rule){
+        this.messages.push({
+            type    : this.ruleset[rule.id] == 2 ? "error" : "warning",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule
+        });
+    },
+    info: function(message, line, col, rule){
+        this.messages.push({
+            type    : "info",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule
+        });
+    },
+    rollupError: function(message, rule){
+        this.messages.push({
+            type    : "error",
+            rollup  : true,
+            message : message,
+            rule    : rule
+        });
+    },
+    rollupWarn: function(message, rule){
+        this.messages.push({
+            type    : "warning",
+            rollup  : true,
+            message : message,
+            rule    : rule
+        });
+    },
+    stat: function(name, value){
+        this.stats[name] = value;
+    }
+};
+CSSLint._Reporter = Reporter;
+CSSLint.Util = {
+    mix: function(receiver, supplier){
+        var prop;
+
+        for (prop in supplier){
+            if (supplier.hasOwnProperty(prop)){
+                receiver[prop] = supplier[prop];
+            }
+        }
+
+        return prop;
+    },
+    indexOf: function(values, value){
+        if (values.indexOf){
+            return values.indexOf(value);
+        } else {
+            for (var i=0, len=values.length; i < len; i++){
+                if (values[i] === value){
+                    return i;
+                }
+            }
+            return -1;
+        }
+    },
+    forEach: function(values, func) {
+        if (values.forEach){
+            return values.forEach(func);
+        } else {
+            for (var i=0, len=values.length; i < len; i++){
+                func(values[i], i, values);
+            }
+        }
+    }
+};
+CSSLint.addRule({
+    id: "adjoining-classes",
+    name: "Disallow adjoining classes",
+    desc: "Don't use adjoining classes.",
+    browsers: "IE6",
+    init: function(parser, reporter){
+        var rule = this;
+        parser.addListener("startrule", function(event){
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                classCount,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+                for (j=0; j < selector.parts.length; j++){
+                    part = selector.parts[j];
+                    if (part.type == parser.SELECTOR_PART_TYPE){
+                        classCount = 0;
+                        for (k=0; k < part.modifiers.length; k++){
+                            modifier = part.modifiers[k];
+                            if (modifier.type == "class"){
+                                classCount++;
+                            }
+                            if (classCount > 1){
+                                reporter.report("Don't use adjoining classes.", part.line, part.col, rule);
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+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(parser, reporter){
+        var rule = this,
+            widthProperties = {
+                border: 1,
+                "border-left": 1,
+                "border-right": 1,
+                padding: 1,
+                "padding-left": 1,
+                "padding-right": 1
+            },
+            heightProperties = {
+                border: 1,
+                "border-bottom": 1,
+                "border-top": 1,
+                padding: 1,
+                "padding-bottom": 1,
+                "padding-top": 1
+            },
+            properties,
+            boxSizing = false;
+
+        function startRule(){
+            properties = {};
+            boxSizing = false;
+        }
+
+        function endRule(){
+            var prop, value;
+
+            if (!boxSizing) {
+                if (properties.height){
+                    for (prop in heightProperties){
+                        if (heightProperties.hasOwnProperty(prop) && properties[prop]){
+                            value = properties[prop].value;
+                            if (!(prop == "padding" && value.parts.length === 2 && value.parts[0].value === 0)){
+                                reporter.report("Using height with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
+                            }
+                        }
+                    }
+                }
+
+                if (properties.width){
+                    for (prop in widthProperties){
+                        if (widthProperties.hasOwnProperty(prop) && properties[prop]){
+                            value = properties[prop].value;
+
+                            if (!(prop == "padding" && value.parts.length === 2 && value.parts[1].value === 0)){
+                                reporter.report("Using width with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase();
+
+            if (heightProperties[name] || widthProperties[name]){
+                if (!/^0\S*$/.test(event.value) && !(name == "border" && event.value == "none")){
+                    properties[name] = { line: event.property.line, col: event.property.col, value: event.value };
+                }
+            } else {
+                if (/^(width|height)/i.test(name) && /^(length|percentage)/.test(event.value.parts[0].type)){
+                    properties[name] = 1;
+                } else if (name == "box-sizing") {
+                    boxSizing = true;
+                }
+            }
+
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+    }
+
+});
+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(parser, reporter){
+        var rule = this;
+
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase();
+
+            if (name == "box-sizing"){
+                reporter.report("The box-sizing property isn't supported in IE6 and IE7.", event.line, event.col, rule);
+            }
+        });
+    }
+
+});
+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 (parser, reporter) {
+        var rule = this,
+            compatiblePrefixes,
+            properties,
+            prop,
+            variations,
+            prefixed,
+            i,
+            len,
+            inKeyFrame = false,
+            arrayPush = Array.prototype.push,
+            applyTo = [];
+        compatiblePrefixes = {
+            "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 (prop in compatiblePrefixes) {
+            if (compatiblePrefixes.hasOwnProperty(prop)) {
+                variations = [];
+                prefixed = compatiblePrefixes[prop].split(' ');
+                for (i = 0, len = prefixed.length; i < len; i++) {
+                    variations.push('-' + prefixed[i] + '-' + prop);
+                }
+                compatiblePrefixes[prop] = variations;
+                arrayPush.apply(applyTo, variations);
+            }
+        }
+
+        parser.addListener("startrule", function () {
+            properties = [];
+        });
+
+        parser.addListener("startkeyframes", function (event) {
+            inKeyFrame = event.prefix || true;
+        });
+
+        parser.addListener("endkeyframes", function (event) {
+            inKeyFrame = false;
+        });
+
+        parser.addListener("property", function (event) {
+            var name = event.property;
+            if (CSSLint.Util.indexOf(applyTo, name.text) > -1) {
+                if (!inKeyFrame || typeof inKeyFrame != "string" ||
+                        name.text.indexOf("-" + inKeyFrame + "-") !== 0) {
+                    properties.push(name);
+                }
+            }
+        });
+
+        parser.addListener("endrule", function (event) {
+            if (!properties.length) {
+                return;
+            }
+
+            var propertyGroups = {},
+                i,
+                len,
+                name,
+                prop,
+                variations,
+                value,
+                full,
+                actual,
+                item,
+                propertiesSpecified;
+
+            for (i = 0, len = properties.length; i < len; i++) {
+                name = properties[i];
+
+                for (prop in compatiblePrefixes) {
+                    if (compatiblePrefixes.hasOwnProperty(prop)) {
+                        variations = compatiblePrefixes[prop];
+                        if (CSSLint.Util.indexOf(variations, name.text) > -1) {
+                            if (!propertyGroups[prop]) {
+                                propertyGroups[prop] = {
+                                    full : variations.slice(0),
+                                    actual : [],
+                                    actualNodes: []
+                                };
+                            }
+                            if (CSSLint.Util.indexOf(propertyGroups[prop].actual, name.text) === -1) {
+                                propertyGroups[prop].actual.push(name.text);
+                                propertyGroups[prop].actualNodes.push(name);
+                            }
+                        }
+                    }
+                }
+            }
+
+            for (prop in propertyGroups) {
+                if (propertyGroups.hasOwnProperty(prop)) {
+                    value = propertyGroups[prop];
+                    full = value.full;
+                    actual = value.actual;
+
+                    if (full.length > actual.length) {
+                        for (i = 0, len = full.length; i < len; i++) {
+                            item = full[i];
+                            if (CSSLint.Util.indexOf(actual, item) === -1) {
+                                propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length == 2) ? actual.join(" and ") : actual.join(", ");
+                                reporter.report("The property " + item + " is compatible with " + propertiesSpecified + " and should be included as well.", value.actualNodes[0].line, value.actualNodes[0].col, rule);
+                            }
+                        }
+
+                    }
+                }
+            }
+        });
+    }
+});
+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(parser, reporter){
+        var rule = this;
+
+        var propertiesToCheck = {
+                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
+            },
+            properties;
+
+        function reportProperty(name, display, msg){
+            if (properties[name]){
+                if (typeof propertiesToCheck[name] != "string" || properties[name].value.toLowerCase() != propertiesToCheck[name]){
+                    reporter.report(msg || name + " can't be used with display: " + display + ".", properties[name].line, properties[name].col, rule);
+                }
+            }
+        }
+
+        function startRule(){
+            properties = {};
+        }
+
+        function endRule(){
+
+            var display = properties.display ? properties.display.value : null;
+            if (display){
+                switch(display){
+
+                    case "inline":
+                        reportProperty("height", display);
+                        reportProperty("width", display);
+                        reportProperty("margin", display);
+                        reportProperty("margin-top", display);
+                        reportProperty("margin-bottom", display);
+                        reportProperty("float", display, "display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).");
+                        break;
+
+                    case "block":
+                        reportProperty("vertical-align", display);
+                        break;
+
+                    case "inline-block":
+                        reportProperty("float", display);
+                        break;
+
+                    default:
+                        if (display.indexOf("table-") === 0){
+                            reportProperty("margin", display);
+                            reportProperty("margin-left", display);
+                            reportProperty("margin-right", display);
+                            reportProperty("margin-top", display);
+                            reportProperty("margin-bottom", display);
+                            reportProperty("float", display);
+                        }
+                }
+            }
+
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startpage", startRule);
+
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase();
+
+            if (propertiesToCheck[name]){
+                properties[name] = { value: event.value.text, line: event.property.line, col: event.property.col };
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endpage", endRule);
+
+    }
+
+});
+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(parser, reporter){
+        var rule = this,
+            stack = {};
+
+        parser.addListener("property", function(event){
+            var name = event.property.text,
+                value = event.value,
+                i, len;
+
+            if (name.match(/background/i)) {
+                for (i=0, len=value.parts.length; i < len; i++) {
+                    if (value.parts[i].type == 'uri') {
+                        if (typeof stack[value.parts[i].uri] === 'undefined') {
+                            stack[value.parts[i].uri] = event;
+                        }
+                        else {
+                            reporter.report("Background image '" + value.parts[i].uri + "' was used multiple times, first declared at line " + stack[value.parts[i].uri].line + ", col " + stack[value.parts[i].uri].col + ".", event.line, event.col, rule);
+                        }
+                    }
+                }
+            }
+        });
+    }
+});
+CSSLint.addRule({
+    id: "duplicate-properties",
+    name: "Disallow duplicate properties",
+    desc: "Duplicate properties must appear one after the other.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this,
+            properties,
+            lastProperty;
+
+        function startRule(event){
+            properties = {};
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+
+        parser.addListener("property", function(event){
+            var property = event.property,
+                name = property.text.toLowerCase();
+
+            if (properties[name] && (lastProperty != name || properties[name] == event.value.text)){
+                reporter.report("Duplicate property '" + event.property + "' found.", event.line, event.col, rule);
+            }
+
+            properties[name] = event.value.text;
+            lastProperty = name;
+
+        });
+
+
+    }
+
+});
+CSSLint.addRule({
+    id: "empty-rules",
+    name: "Disallow empty rules",
+    desc: "Rules without any properties specified should be removed.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this,
+            count = 0;
+
+        parser.addListener("startrule", function(){
+            count=0;
+        });
+
+        parser.addListener("property", function(){
+            count++;
+        });
+
+        parser.addListener("endrule", function(event){
+            var selectors = event.selectors;
+            if (count === 0){
+                reporter.report("Rule is empty.", selectors[0].line, selectors[0].col, rule);
+            }
+        });
+    }
+
+});
+CSSLint.addRule({
+    id: "errors",
+    name: "Parsing Errors",
+    desc: "This rule looks for recoverable syntax errors.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this;
+
+        parser.addListener("error", function(event){
+            reporter.error(event.message, event.line, event.col, rule);
+        });
+
+    }
+
+});
+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(parser, reporter){
+        var rule = this,
+            lastProperty,
+            propertiesToCheck = {
+                color: 1,
+                background: 1,
+                "background-color": 1
+            },
+            properties;
+
+        function startRule(event){
+            properties = {};
+            lastProperty = null;
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+
+        parser.addListener("property", function(event){
+            var property = event.property,
+                name = property.text.toLowerCase(),
+                parts = event.value.parts,
+                i = 0,
+                colorType = "",
+                len = parts.length;
+
+            if(propertiesToCheck[name]){
+                while(i < len){
+                    if (parts[i].type == "color"){
+                        if ("alpha" in parts[i] || "hue" in parts[i]){
+
+                            if (/([^\)]+)\(/.test(parts[i])){
+                                colorType = RegExp.$1.toUpperCase();
+                            }
+
+                            if (!lastProperty || (lastProperty.property.text.toLowerCase() != name || lastProperty.colorType != "compat")){
+                                reporter.report("Fallback " + name + " (hex or RGB) should precede " + colorType + " " + name + ".", event.line, event.col, rule);
+                            }
+                        } else {
+                            event.colorType = "compat";
+                        }
+                    }
+
+                    i++;
+                }
+            }
+
+            lastProperty = event;
+        });
+
+    }
+
+});
+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(parser, reporter){
+        var rule = this;
+        var count = 0;
+        parser.addListener("property", function(event){
+            if (event.property.text.toLowerCase() == "float" &&
+                    event.value.text.toLowerCase() != "none"){
+                count++;
+            }
+        });
+        parser.addListener("endstylesheet", function(){
+            reporter.stat("floats", count);
+            if (count >= 10){
+                reporter.rollupWarn("Too many floats (" + count + "), you're probably using them for layout. Consider using a grid system instead.", rule);
+            }
+        });
+    }
+
+});
+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(parser, reporter){
+        var rule = this,
+            count = 0;
+
+
+        parser.addListener("startfontface", function(){
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function(){
+            if (count > 5){
+                reporter.rollupWarn("Too many @font-face declarations (" + count + ").", rule);
+            }
+        });
+    }
+
+});
+CSSLint.addRule({
+    id: "font-sizes",
+    name: "Disallow too many font sizes",
+    desc: "Checks the number of font-size declarations.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this,
+            count = 0;
+        parser.addListener("property", function(event){
+            if (event.property == "font-size"){
+                count++;
+            }
+        });
+        parser.addListener("endstylesheet", function(){
+            reporter.stat("font-sizes", count);
+            if (count >= 10){
+                reporter.rollupWarn("Too many font-size declarations (" + count + "), abstraction needed.", rule);
+            }
+        });
+    }
+
+});
+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(parser, reporter){
+        var rule = this,
+            gradients;
+
+        parser.addListener("startrule", function(){
+            gradients = {
+                moz: 0,
+                webkit: 0,
+                oldWebkit: 0,
+                ms: 0,
+                o: 0
+            };
+        });
+
+        parser.addListener("property", function(event){
+
+            if (/\-(moz|ms|o|webkit)(?:\-(?:linear|radial))\-gradient/i.test(event.value)){
+                gradients[RegExp.$1] = 1;
+            } else if (/\-webkit\-gradient/i.test(event.value)){
+                gradients.oldWebkit = 1;
+            }
+
+        });
+
+        parser.addListener("endrule", function(event){
+            var missing = [];
+
+            if (!gradients.moz){
+                missing.push("Firefox 3.6+");
+            }
+
+            if (!gradients.webkit){
+                missing.push("Webkit (Safari 5+, Chrome)");
+            }
+
+            if (!gradients.oldWebkit){
+                missing.push("Old Webkit (Safari 4+, Chrome)");
+            }
+
+            if (!gradients.ms){
+                missing.push("Internet Explorer 10+");
+            }
+
+            if (!gradients.o){
+                missing.push("Opera 11.1+");
+            }
+
+            if (missing.length && missing.length < 5){
+                reporter.report("Missing vendor-prefixed CSS gradients for " + missing.join(", ") + ".", event.selectors[0].line, event.selectors[0].col, rule);
+            }
+
+        });
+
+    }
+
+});
+CSSLint.addRule({
+    id: "ids",
+    name: "Disallow IDs in selectors",
+    desc: "Selectors should not contain IDs.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this;
+        parser.addListener("startrule", function(event){
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                idCount,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+                idCount = 0;
+
+                for (j=0; j < selector.parts.length; j++){
+                    part = selector.parts[j];
+                    if (part.type == parser.SELECTOR_PART_TYPE){
+                        for (k=0; k < part.modifiers.length; k++){
+                            modifier = part.modifiers[k];
+                            if (modifier.type == "id"){
+                                idCount++;
+                            }
+                        }
+                    }
+                }
+
+                if (idCount == 1){
+                    reporter.report("Don't use IDs in selectors.", selector.line, selector.col, rule);
+                } else if (idCount > 1){
+                    reporter.report(idCount + " IDs in the selector, really?", selector.line, selector.col, rule);
+                }
+            }
+
+        });
+    }
+
+});
+CSSLint.addRule({
+    id: "import",
+    name: "Disallow @import",
+    desc: "Don't use @import, use <link> instead.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this;
+
+        parser.addListener("import", function(event){
+            reporter.report("@import prevents parallel downloads, use <link> instead.", event.line, event.col, rule);
+        });
+
+    }
+
+});
+CSSLint.addRule({
+    id: "important",
+    name: "Disallow !important",
+    desc: "Be careful when using !important declaration",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this,
+            count = 0;
+        parser.addListener("property", function(event){
+            if (event.important === true){
+                count++;
+                reporter.report("Be careful when using !important declaration", event.line, event.col, rule);
+            }
+        });
+        parser.addListener("endstylesheet", function(){
+            reporter.stat("important", count);
+            if (count >= 10){
+                reporter.rollupWarn("Too many !important declarations (" + count + "), try to use less than 10 to avoid specificity issues.", rule);
+            }
+        });
+    }
+
+});
+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(parser, reporter){
+        var rule = this;
+
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase();
+            if (event.invalid) {
+                reporter.report(event.invalid.message, event.line, event.col, rule);
+            }
+
+        });
+    }
+
+});
+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(parser, reporter){
+        var rule = this,
+            lastRule;
+
+        function startRule(event){
+            if (event.selectors){
+                lastRule = {
+                    line: event.line,
+                    col: event.col,
+                    selectors: event.selectors,
+                    propCount: 0,
+                    outline: false
+                };
+            } else {
+                lastRule = null;
+            }
+        }
+
+        function endRule(event){
+            if (lastRule){
+                if (lastRule.outline){
+                    if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") == -1){
+                        reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule);
+                    } else if (lastRule.propCount == 1) {
+                        reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule);
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase(),
+                value = event.value;
+
+            if (lastRule){
+                lastRule.propCount++;
+                if (name == "outline" && (value == "none" || value == "0")){
+                    lastRule.outline = true;
+                }
+            }
+
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+
+    }
+
+});
+CSSLint.addRule({
+    id: "overqualified-elements",
+    name: "Disallow overqualified elements",
+    desc: "Don't use IDs with elements (a#foo).",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this,
+            classes = {};
+
+        parser.addListener("startrule", function(event){
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+
+                for (j=0; j < selector.parts.length; j++){
+                    part = selector.parts[j];
+                    if (part.type == parser.SELECTOR_PART_TYPE){
+                        for (k=0; k < part.modifiers.length; k++){
+                            modifier = part.modifiers[k];
+                            if (part.elementName && modifier.type == "id"){
+                                reporter.report("Element (" + part + ") is overqualified, just use " + modifier + " without element name.", part.line, part.col, rule);
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+CSSLint.addRule({
+    id: "qualified-headings",
+    name: "Disallow qualified headings",
+    desc: "Headings should not be qualified (namespaced).",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this;
+
+        parser.addListener("startrule", function(event){
+            var selectors = event.selectors,
+                selector,
+                part,
+                i, j;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+
+                for (j=0; j < selector.parts.length; j++){
+                    part = selector.parts[j];
+                    if (part.type == parser.SELECTOR_PART_TYPE){
+                        if (part.elementName && /h[1-6]/.test(part.elementName.toString()) && j > 0){
+                            reporter.report("Heading (" + part.elementName + ") should not be qualified.", part.line, part.col, rule);
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+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(parser, reporter){
+        var rule = this;
+
+        parser.addListener("startrule", function(event){
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+                for (j=0; j < selector.parts.length; j++){
+                    part = selector.parts[j];
+                    if (part.type == parser.SELECTOR_PART_TYPE){
+                        for (k=0; k < part.modifiers.length; k++){
+                            modifier = part.modifiers[k];
+                            if (modifier.type == "attribute"){
+                                if (/([\~\|\^\$\*]=)/.test(modifier)){
+                                    reporter.report("Attribute selectors with " + RegExp.$1 + " are slow!", modifier.line, modifier.col, rule);
+                                }
+                            }
+
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+CSSLint.addRule({
+    id: "rules-count",
+    name: "Rules Count",
+    desc: "Track how many rules there are.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this,
+            count = 0;
+        parser.addListener("startrule", function(){
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function(){
+            reporter.stat("rule-count", count);
+        });
+    }
+
+});
+CSSLint.addRule({
+    id: "shorthand",
+    name: "Require shorthand properties",
+    desc: "Use shorthand properties where possible.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this,
+            prop, i, len,
+            propertiesToCheck = {},
+            properties,
+            mapping = {
+                "margin": [
+                    "margin-top",
+                    "margin-bottom",
+                    "margin-left",
+                    "margin-right"
+                ],
+                "padding": [
+                    "padding-top",
+                    "padding-bottom",
+                    "padding-left",
+                    "padding-right"
+                ]
+            };
+        for (prop in mapping){
+            if (mapping.hasOwnProperty(prop)){
+                for (i=0, len=mapping[prop].length; i < len; i++){
+                    propertiesToCheck[mapping[prop][i]] = prop;
+                }
+            }
+        }
+
+        function startRule(event){
+            properties = {};
+        }
+        function endRule(event){
+
+            var prop, i, len, total;
+            for (prop in mapping){
+                if (mapping.hasOwnProperty(prop)){
+                    total=0;
+
+                    for (i=0, len=mapping[prop].length; i < len; i++){
+                        total += properties[mapping[prop][i]] ? 1 : 0;
+                    }
+
+                    if (total == mapping[prop].length){
+                        reporter.report("The properties " + mapping[prop].join(", ") + " can be replaced by " + prop + ".", event.line, event.col, rule);
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("property", function(event){
+            var name = event.property.toString().toLowerCase(),
+                value = event.value.parts[0].value;
+
+            if (propertiesToCheck[name]){
+                properties[name] = 1;
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+
+    }
+
+});
+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(parser, reporter){
+        var rule = this;
+        parser.addListener("property", function(event){
+            var property = event.property;
+
+            if (property.hack == "*") {
+                reporter.report("Property with star prefix found.", event.property.line, event.property.col, rule);
+            }
+        });
+    }
+});
+CSSLint.addRule({
+    id: "text-indent",
+    name: "Disallow negative text-indent",
+    desc: "Checks for text indent less than -99px",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this,
+            textIndent,
+            direction;
+
+
+        function startRule(event){
+            textIndent = false;
+            direction = "inherit";
+        }
+        function endRule(event){
+            if (textIndent && direction != "ltr"){
+                reporter.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.", textIndent.line, textIndent.col, rule);
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("property", function(event){
+            var name = event.property.toString().toLowerCase(),
+                value = event.value;
+
+            if (name == "text-indent" && value.parts[0].value < -99){
+                textIndent = event.property;
+            } else if (name == "direction" && value == "ltr"){
+                direction = "ltr";
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+
+    }
+
+});
+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(parser, reporter){
+        var rule = this;
+        parser.addListener("property", function(event){
+            var property = event.property;
+
+            if (property.hack == "_") {
+                reporter.report("Property with underscore prefix found.", event.property.line, event.property.col, rule);
+            }
+        });
+    }
+});
+CSSLint.addRule({
+    id: "unique-headings",
+    name: "Headings should only be defined once",
+    desc: "Headings should be defined only once.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this;
+
+        var headings =  {
+                h1: 0,
+                h2: 0,
+                h3: 0,
+                h4: 0,
+                h5: 0,
+                h6: 0
+            };
+
+        parser.addListener("startrule", function(event){
+            var selectors = event.selectors,
+                selector,
+                part,
+                pseudo,
+                i, j;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+                part = selector.parts[selector.parts.length-1];
+
+                if (part.elementName && /(h[1-6])/i.test(part.elementName.toString())){
+
+                    for (j=0; j < part.modifiers.length; j++){
+                        if (part.modifiers[j].type == "pseudo"){
+                            pseudo = true;
+                            break;
+                        }
+                    }
+
+                    if (!pseudo){
+                        headings[RegExp.$1]++;
+                        if (headings[RegExp.$1] > 1) {
+                            reporter.report("Heading (" + part.elementName + ") has already been defined.", part.line, part.col, rule);
+                        }
+                    }
+                }
+            }
+        });
+
+        parser.addListener("endstylesheet", function(event){
+            var prop,
+                messages = [];
+
+            for (prop in headings){
+                if (headings.hasOwnProperty(prop)){
+                    if (headings[prop] > 1){
+                        messages.push(headings[prop] + " " + prop + "s");
+                    }
+                }
+            }
+
+            if (messages.length){
+                reporter.rollupWarn("You have " + messages.join(", ") + " defined in this stylesheet.", rule);
+            }
+        });
+    }
+
+});
+CSSLint.addRule({
+    id: "universal-selector",
+    name: "Disallow universal selector",
+    desc: "The universal selector (*) is known to be slow.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this;
+
+        parser.addListener("startrule", function(event){
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+
+                part = selector.parts[selector.parts.length-1];
+                if (part.elementName == "*"){
+                    reporter.report(rule.desc, part.line, part.col, rule);
+                }
+            }
+        });
+    }
+
+});
+CSSLint.addRule({
+    id: "unqualified-attributes",
+    name: "Disallow unqualified attribute selectors",
+    desc: "Unqualified attribute selectors are known to be slow.",
+    browsers: "All",
+    init: function(parser, reporter){
+        var rule = this;
+
+        parser.addListener("startrule", function(event){
+
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+
+                part = selector.parts[selector.parts.length-1];
+                if (part.type == parser.SELECTOR_PART_TYPE){
+                    for (k=0; k < part.modifiers.length; k++){
+                        modifier = part.modifiers[k];
+                        if (modifier.type == "attribute" && (!part.elementName || part.elementName == "*")){
+                            reporter.report(rule.desc, part.line, part.col, rule);
+                        }
+                    }
+                }
+
+            }
+        });
+    }
+
+});
+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(parser, reporter){
+        var rule = this,
+            properties,
+            num,
+            propertiesToCheck = {
+                "-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"
+            };
+        function startRule(){
+            properties = {};
+            num=1;
+        }
+        function endRule(event){
+            var prop,
+                i, len,
+                standard,
+                needed,
+                actual,
+                needsStandard = [];
+
+            for (prop in properties){
+                if (propertiesToCheck[prop]){
+                    needsStandard.push({ actual: prop, needed: propertiesToCheck[prop]});
+                }
+            }
+
+            for (i=0, len=needsStandard.length; i < len; i++){
+                needed = needsStandard[i].needed;
+                actual = needsStandard[i].actual;
+
+                if (!properties[needed]){
+                    reporter.report("Missing standard property '" + needed + "' to go along with '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
+                } else {
+                    if (properties[needed][0].pos < properties[actual][0].pos){
+                        reporter.report("Standard property '" + needed + "' should come after vendor-prefixed property '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
+                    }
+                }
+            }
+
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase();
+
+            if (!properties[name]){
+                properties[name] = [];
+            }
+
+            properties[name].push({ name: event.property, value : event.value, pos:num++ });
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+    }
+
+});
+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(parser, reporter){
+        var rule = this;
+        parser.addListener("property", function(event){
+            var parts = event.value.parts,
+                i = 0,
+                len = parts.length;
+
+            while(i < len){
+                if ((parts[i].units || parts[i].type == "percentage") && parts[i].value === 0 && parts[i].type != "time"){
+                    reporter.report("Values of 0 shouldn't have units specified.", parts[i].line, parts[i].col, rule);
+                }
+                i++;
+            }
+
+        });
+
+    }
+
+});
+
+CSSLint.addRule({
+	id: "custom-background-class",
+	name: "Remember .custom-background",
+	desc: "Remind users to use the .custom-background class on the body selector.",
+	browsers: "All",
+	init: function(parser, reporter){
+		var rule = this,
+		    pending = false,
+			report_warning = false;
+
+		parser.addListener("property", function(event){
+			if (pending && event.property.toString().toLowerCase().indexOf('background') === 0)
+				report_warning = true;
+		});
+
+		parser.addListener("startrule", function (event) {
+			var selectors = event.selectors,
+			    selector,
+			    part,
+			    i, j;
+
+			for (i=0; i < selectors.length; i++){
+				selector = selectors[i];
+
+				for (j=0; j < selector.parts.length; j++){
+					part = selector.parts[j];
+
+					if (part.type == parser.SELECTOR_PART_TYPE){
+						if (part.elementName && part.elementName.toString() == 'body' && part.modifiers.length == 0) {
+							pending = true;
+						}
+					}
+				}
+			}
+		});
+
+		parser.addListener("endrule", function (event) {
+			if (report_warning)
+				reporter.report("If you want to override any custom background styles, be sure to add '.custom-background' to your 'body' selector.", event.line, event.col, rule);
+
+			report_warning = false;
+			pending = false;
+		});
+	}
+});
+
+exports.CSSLint = CSSLint;
+
+
+});

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
index 65b01d6..2fb4619 100644
--- a/plugins/jetpack/modules/custom-css/custom-css/js/safecss-ace.js
+++ b/plugins/jetpack/modules/custom-css/custom-css/js/safecss-ace.js
@@ -1,9 +1,11 @@
 (function(global, $){
 	// shared scope insied IIFE in case it's needed.
 	var editor;
-	var syncCSS = function() {
-		$("#safecss").val( editor.getSession().getValue() );
+
+	var syncCSS = function () {
+		$( "#safecss" ).val( editor.getSession().getValue() );
 	};
+
 	var loadAce = function() {
 		// Set up ACE editor
 		ace.config.set( 'modePath', safecssAceSrcPath );
@@ -19,27 +21,30 @@
 		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 :(
+
+		var preprocessorField = $( '#custom_css_preprocessor' );
+		function setCSSMode( preprocessor ) {
+			switch ( preprocessor ) {
+				case 'less':
+					var mode = ace.require( 'ace/mode/less' ).Mode;
+				break;
+				case 'sass':
+					var mode = ace.require( 'ace/mode/scss' ).Mode;
+				break;
+				default:
+					var mode = ace.require( 'ace/mode/css' ).Mode;
+				break;
 			}
+
+			editor.getSession().setMode( new mode() );
+		}
+
+		setCSSMode( preprocessorField.val() );
+		preprocessorField.on( 'change', function () {
+			setCSSMode( $( this ).val() );
 		} );
-		*/
 
 		// When submitting, make sure to include the updated CSS
 		// The Ace editor unfortunately doesn't handle this for us
@@ -54,16 +59,12 @@
 	}
 	// syntaxy goodness.
 	else {
-		$( '#safecss-ace, #safecss-container' ).css( 'height', 
+		$( '#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);
-
-
+	$( '#preview' ).on( 'click', syncCSS );
+})(this, jQuery);
\ No newline at end of file

diff --git a/plugins/jetpack/modules/custom-css/custom-css/preprocessors.php b/plugins/jetpack/modules/custom-css/custom-css/preprocessors.php
index eef6ab4..e107b53 100644
--- a/plugins/jetpack/modules/custom-css/custom-css/preprocessors.php
+++ b/plugins/jetpack/modules/custom-css/custom-css/preprocessors.php
@@ -33,7 +33,7 @@ function jetpack_register_css_preprocessors( $preprocessors ) {
 add_filter( 'jetpack_custom_css_preprocessors', 'jetpack_register_css_preprocessors' );
 
 function jetpack_less_css_preprocess( $less ) {
-	require( dirname( __FILE__ ) . '/preprocessors/lessc.inc.php' );
+	require_once( dirname( __FILE__ ) . '/preprocessors/lessc.inc.php' );
 
 	$compiler = new lessc();
 

diff --git a/plugins/jetpack/modules/enhanced-distribution.php b/plugins/jetpack/modules/enhanced-distribution.php
index b2a8015..daad2eb 100644
--- a/plugins/jetpack/modules/enhanced-distribution.php
+++ b/plugins/jetpack/modules/enhanced-distribution.php
@@ -4,6 +4,7 @@
  * Module Description: Share your public posts and comments to search engines and other services in real-time.
  * Sort Order: 100
  * First Introduced: 1.2
+ * Requires Connection: Yes
  */
 
 Jetpack_Sync::sync_posts( __FILE__ );

diff --git a/plugins/jetpack/modules/featured-content/featured-content.php b/plugins/jetpack/modules/featured-content/featured-content.php
index 9cd511e..ac39490 100644
--- a/plugins/jetpack/modules/featured-content/featured-content.php
+++ b/plugins/jetpack/modules/featured-content/featured-content.php
@@ -41,7 +41,7 @@ class Featured_Content {
 	 * All custom functionality will be hooked into the "init" action.
 	 */
 	public static function setup() {
-		add_action( 'init', array( __class__, 'init' ) );
+		add_action( 'init', array( __class__, 'init' ), 30 );
 	}
 
 	/**
@@ -413,12 +413,14 @@ class Featured_Content {
 		if ( isset( $input['tag-id'] ) )
 			$output['tag-id'] = absint( $input['tag-id'] );
 
-		if ( isset( $input['tag-name'] ) ) {
+		if ( isset( $input['tag-name'] ) && ! empty( $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;
+		} else {
+			unset( $output['tag-id'] );
 		}
 
 		if ( isset( $input['quantity'] ) )

diff --git a/plugins/jetpack/modules/gravatar-hovercards.php b/plugins/jetpack/modules/gravatar-hovercards.php
index 9edd15a..980317c 100644
--- a/plugins/jetpack/modules/gravatar-hovercards.php
+++ b/plugins/jetpack/modules/gravatar-hovercards.php
@@ -4,6 +4,7 @@
  * Module Description: Show a pop-up business card of your users' gravatar profiles in comments.
  * Sort Order: 8
  * First Introduced: 1.1
+ * Requires Connection: No
  */
 
 define( 'GROFILES__CACHE_BUSTER', gmdate( 'YM' ) . 'aa' ); // Break CDN cache, increment when gravatar.com/js/gprofiles.js changes
@@ -13,11 +14,11 @@ function grofiles_hovercards_init() {
 	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' );
-	add_action( 'load-edit-comments.php',      'grofiles_admin_cards' );	
-	add_action( 'load-options-discussion.php', 'grofiles_admin_cards_forced' );	
+	add_action( 'load-edit-comments.php',      'grofiles_admin_cards' );
+	add_action( 'load-options-discussion.php', 'grofiles_admin_cards_forced' );
 
 	Jetpack::enable_module_configurable( __FILE__ );
 	Jetpack::module_configuration_load( __FILE__, 'gravatar_hovercards_configuration_load' );
@@ -52,7 +53,7 @@ function grofiles_setting_callback() {
 	global $current_user;
 
 	$checked = 'disabled' == get_option( 'gravatar_disable_hovercards' ) ? '' : 'checked="checked" ';
- 
+
  	echo "<label id='gravatar-hovercard-options'><input {$checked}name='gravatar_disable_hovercards' id='gravatar_disable_hovercards' type='checkbox' value='enabled' class='code' /> " . __( "View people's profiles when you mouse over their Gravatars", 'jetpack' ) . "</label>";
 ?>
 <style type="text/css">
@@ -167,7 +168,7 @@ function grofiles_get_avatar( $avatar, $author ) {
  */
 function grofiles_attach_cards() {
 	global $blog_id;
-	
+
 	if ( 'disabled' == get_option( 'gravatar_disable_hovercards' ) )
 		return;
 

diff --git a/plugins/jetpack/modules/holiday-snow.php b/plugins/jetpack/modules/holiday-snow.php
index 93e3f9c..51bf3ed 100644
--- a/plugins/jetpack/modules/holiday-snow.php
+++ b/plugins/jetpack/modules/holiday-snow.php
@@ -5,6 +5,7 @@
  * 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 ??
+ * Requires Connection: No
  */
 
 class Jetpack_Holiday_Snow_Settings {

diff --git a/plugins/jetpack/modules/infinite-scroll.php b/plugins/jetpack/modules/infinite-scroll.php
index 857ac6e..2a94bf4 100644
--- a/plugins/jetpack/modules/infinite-scroll.php
+++ b/plugins/jetpack/modules/infinite-scroll.php
@@ -4,6 +4,7 @@
  * 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
+ * Requires Connection: No
  */
 
 /**

diff --git a/plugins/jetpack/modules/infinite-scroll/infinity.css b/plugins/jetpack/modules/infinite-scroll/infinity.css
index dd39179..0a09f24 100644
--- a/plugins/jetpack/modules/infinite-scroll/infinity.css
+++ b/plugins/jetpack/modules/infinite-scroll/infinity.css
@@ -2,15 +2,11 @@
 -------------------------------------------------------------- */
 
 .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 {
@@ -58,6 +54,7 @@
 	border-color: rgba( 0, 0, 0, 0.1 );
 	border-style: solid;
 	border-width: 1px 0 0;
+	-moz-box-sizing: border-box;
 	box-sizing: border-box;
 	margin: 0 auto;
 	overflow: hidden;

diff --git a/plugins/jetpack/modules/infinite-scroll/infinity.js b/plugins/jetpack/modules/infinite-scroll/infinity.js
index 7a76d8f..5109915 100644
--- a/plugins/jetpack/modules/infinite-scroll/infinity.js
+++ b/plugins/jetpack/modules/infinite-scroll/infinity.js
@@ -79,14 +79,13 @@ Scroller = function( settings ) {
 
 /**
  * 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();
 
+	threshold = Math.round( threshold * 0.75 );
+
 	return bottom > threshold;
 };
 
@@ -457,7 +456,7 @@ Scroller.prototype.updateURL = function( page ) {
  */
 $( document ).ready( function() {
 	// Check for our variables
-	if ( ! infiniteScroll )
+	if ( 'object' != typeof infiniteScroll ) 
 		return;
 
 	// Set ajaxurl (for brevity)
@@ -487,4 +486,4 @@ $( document ).ready( function() {
 });
 
 
-})(jQuery); // Close closure
\ No newline at end of file
+})(jQuery); // Close closure

diff --git a/plugins/jetpack/modules/infinite-scroll/infinity.php b/plugins/jetpack/modules/infinite-scroll/infinity.php
index ad57f1b..20ff5ef 100644
--- a/plugins/jetpack/modules/infinite-scroll/infinity.php
+++ b/plugins/jetpack/modules/infinite-scroll/infinity.php
@@ -17,17 +17,20 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
  */
 class The_Neverending_Home_Page {
 	/**
+	 * Register actions and filters, plus parse IS settings
 	 *
+	 * @uses add_action, add_filter, self::get_settings
+	 * @return null
 	 */
 	function __construct() {
-		add_filter( 'pre_get_posts',                  array( $this, 'posts_per_page_query' ) );
+		add_action( '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' ) );
+		add_action( 'wp_footer',                      array( $this, 'footer' ) );
 
 		// Plugin compatibility
 		add_filter( 'grunion_contact_form_redirect_url', array( $this, 'filter_grunion_redirect_url' ) );
@@ -55,14 +58,15 @@ class The_Neverending_Home_Page {
 			$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
+				'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
+				'footer_callback' => false, // function to be called to render the IS footer, in place of the default
+				'posts_per_page'  => false // int | false to set based on IS type
 			);
 
 			// Validate settings passed through add_theme_support()
@@ -93,8 +97,7 @@ class The_Neverending_Home_Page {
 							case 'wrapper' :
 								if ( 'wrapper' == $key && is_bool( $value ) ) {
 									$settings[ $key ] = $value;
-								}
-								else {
+								} else {
 									$value = preg_replace( $css_pattern, '', $value );
 
 									if ( ! empty( $value ) )
@@ -115,8 +118,7 @@ class The_Neverending_Home_Page {
 							case 'footer' :
 								if ( is_bool( $value ) ) {
 									$settings[ $key ] = $value;
-								}
-								elseif ( is_string( $value ) ) {
+								} elseif ( is_string( $value ) ) {
 									$value = preg_replace( $css_pattern, '', $value );
 
 									if ( ! empty( $value ) )
@@ -125,6 +127,14 @@ class The_Neverending_Home_Page {
 
 								break;
 
+							case 'footer_callback' :
+								if ( is_callable( $value ) )
+									$settings[ $key ] = $value;
+								else
+									$settings[ $key ] = false;
+
+								break;
+
 							case 'posts_per_page' :
 								if ( is_numeric( $value ) )
 									$settings[ $key ] = (int) $value;
@@ -137,9 +147,9 @@ class The_Neverending_Home_Page {
 								break;
 						}
 					}
-				}
-				// Checks below are for backwards compatibility
-				elseif ( is_string( $_settings[0] ) ) {
+				} elseif ( is_string( $_settings[0] ) ) {
+					// Checks below are for backwards compatibility
+
 					// Container to append new posts to
 					$settings['container'] = preg_replace( $css_pattern, '', $_settings[0] );
 
@@ -157,8 +167,7 @@ class The_Neverending_Home_Page {
 			// 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'] ) ) {
+			} elseif ( is_array( $settings['footer_widgets'] ) ) {
 				$sidebar_ids = $settings['footer_widgets'];
 				$settings['footer_widgets'] = false;
 
@@ -171,8 +180,7 @@ class The_Neverending_Home_Page {
 
 				unset( $sidebar_ids );
 				unset( $sidebar_id );
-			}
-			elseif ( is_string( $settings['footer_widgets'] ) ) {
+			} elseif ( is_string( $settings['footer_widgets'] ) ) {
 				$settings['footer_widgets'] = (bool) is_active_sidebar( $settings['footer_widgets'] );
 			}
 
@@ -205,6 +213,18 @@ class The_Neverending_Home_Page {
 	}
 
 	/**
+	 * Retrieve the query used with Infinite Scroll
+	 *
+	 * @global $wp_the_query
+	 * @uses apply_filters
+	 * @return object
+	 */
+	static function wp_query() {
+		global $wp_the_query;
+		return apply_filters( 'infinite_scroll_query_object', $wp_the_query );
+	}
+
+	/**
 	 * Has infinite scroll been triggered?
 	 */
 	static function got_infinity() {
@@ -284,7 +304,7 @@ class The_Neverending_Home_Page {
 		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' );
+		wp_enqueue_script( 'the-neverending-homepage', plugins_url( 'infinity.js', __FILE__ ), array( 'jquery' ), '20130523' );
 
 		// Add our default styles.
 		wp_enqueue_style( 'the-neverending-homepage', plugins_url( 'infinity.css', __FILE__ ), array(), '20120612' );
@@ -322,7 +342,7 @@ class The_Neverending_Home_Page {
 	 * @return string 'Y-m-d H:i:s' or null
 	 */
 	function set_last_post_time( $date = false ) {
-		global $posts;
+		$posts = self::wp_query()->posts;
 		$count = count( $posts );
 
 		if ( ! empty( $date ) && preg_match( '|\d{4}\-\d{2}\-\d{2}|', $_GET['date'] ) ) {
@@ -339,8 +359,7 @@ class The_Neverending_Home_Page {
 		// 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 ) ) {
+		} elseif ( 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;
 		}
@@ -353,8 +372,11 @@ class The_Neverending_Home_Page {
 	 * will always return results prior to (descending sort)
 	 * or before (ascending sort) the last post date.
 	 *
+	 * @global $wpdb
 	 * @param string $where
 	 * @param object $query
+	 * @uses apply_filters
+	 * @uses self::set_last_post_time
 	 * @filter posts_where
 	 * @return string
 	 */
@@ -364,7 +386,9 @@ class The_Neverending_Home_Page {
 		$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() );
+		$clause = $wpdb->prepare( " AND {$wpdb->posts}.post_date_gmt {$operator} %s", self::set_last_post_time() );
+
+		$where .= apply_filters( 'infinite_scroll_posts_where', $clause, $query, $operator, self::set_last_post_time() );
 
 		return $where;
 	}
@@ -372,15 +396,12 @@ class The_Neverending_Home_Page {
 	/**
 	 * 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
+	 * @uses is_admin, 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() )
+		if ( ! is_admin() && self::archive_supports_infinity() && $query->is_main_query() )
 			$query->set( 'posts_per_page', self::get_settings()->posts_per_page );
 	}
 
@@ -438,12 +459,13 @@ class The_Neverending_Home_Page {
 	/**
 	 * Prints the relevant infinite scroll settings in JS.
 	 *
+	 * @global $wp_rewrite
 	 * @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;
+		global $wp_rewrite;
 
 		// Base JS settings
 		$js_settings = array(
@@ -459,7 +481,7 @@ class The_Neverending_Home_Page {
 			'scripts'          => array(),
 			'styles'           => array(),
 			'google_analytics' => false,
-			'offset'           => $wp_query->get( 'paged' ),
+			'offset'           => self::wp_query()->get( 'paged' ),
 			'history'          => array(
 				'host'                 => preg_replace( '#^http(s)?://#i', '', untrailingslashit( get_option( 'home' ) ) ),
 				'path'                 => self::get_request_path(),
@@ -518,8 +540,7 @@ class The_Neverending_Home_Page {
 				$path = '/' . $path;
 
 			$path = user_trailingslashit( $path );
-		}
-		else {
+		} else {
 			// Clean up raw $_GET input
 			$path = array_map( 'sanitize_text_field', $_GET );
 			$path = array_filter( $path );
@@ -606,7 +627,7 @@ class The_Neverending_Home_Page {
 					else
 						$ver = $wp_scripts->registered[ $handle ]->ver ? $wp_scripts->registered[ $handle ]->ver : $wp_scripts->default_version;
 
-					if ( isset($wp_scripts->args[ $handle ] ) )
+					if ( isset( $wp_scripts->args[ $handle ] ) )
 						$ver = $ver ? $ver . '&amp;' . $wp_scripts->args[$handle] : $wp_scripts->args[$handle];
 
 					// Full script source with version info
@@ -721,17 +742,19 @@ class The_Neverending_Home_Page {
 	 *
 	 * @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
+	 * @uses current_theme_supports, get_option, self::wp_query, 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' );
+		$post__not_in = self::wp_query()->get( 'post__not_in' );
+		if ( ! empty( $post__not_in ) )
+			$sticky = array_unique( array_merge( $sticky, $post__not_in ) );
 
 		if ( ! empty( $_GET['date'] ) )
 			self::set_last_post_time( $_GET['date'] );
@@ -742,7 +765,7 @@ class The_Neverending_Home_Page {
 
 		$order = in_array( $_GET['order'], array( 'ASC', 'DESC' ) ) ? $_GET['order'] : 'DESC';
 
-		$query_args = array_merge( $wp_the_query->query_vars, array(
+		$query_args = array_merge( self::wp_query()->query_vars, array(
 			'paged'          => $page,
 			'post_status'    => $post_status,
 			'posts_per_page' => self::get_settings()->posts_per_page,
@@ -751,7 +774,7 @@ class The_Neverending_Home_Page {
 		) );
 
 		// By default, don't query for a specific page of a paged post object.
-		// This argument comes from merging $wp_the_query.
+		// This argument can come from merging self::wp_query() into $query_args above.
 		// Since IS is only used on archives, we should always display the first page of any paged content.
 		unset( $query_args['page'] );
 
@@ -760,7 +783,7 @@ class The_Neverending_Home_Page {
 		// 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 );
+		$GLOBALS['wp_the_query'] = $GLOBALS['wp_query'] = new WP_Query( $query_args );
 
 		remove_filter( 'posts_where', array( $this, 'query_time_filter' ), 10, 2 );
 
@@ -794,8 +817,7 @@ class The_Neverending_Home_Page {
 				unset( $results['html'] );
 				do_action( 'infinite_scroll_empty' );
 				$results['type'] = 'empty';
-			}
-			elseif ( $this->has_wrapper() ) {
+			} 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 );
@@ -825,7 +847,7 @@ class The_Neverending_Home_Page {
 			$results['type'] = 'empty';
 		}
 
-		echo json_encode( apply_filters( 'infinite_scroll_results', $results, $query_args, $wp_query ) );
+		echo json_encode( apply_filters( 'infinite_scroll_results', $results, $query_args, self::wp_query() ) );
 		die;
 	}
 
@@ -847,17 +869,19 @@ class The_Neverending_Home_Page {
 	/**
 	 * Allow plugins to filter what archives Infinite Scroll supports
 	 *
-	 * @uses apply_filters, current_theme_supports, is_home, is_archive, self::get_settings
+	 * @uses current_theme_supports, is_home, is_archive, apply_filters, 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() );
+		$supported = current_theme_supports( 'infinite-scroll' ) && ( is_home() || is_archive() );
+
+		return (bool) apply_filters( 'infinite_scroll_archive_supported', $supported, 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
+	 * @uses self::get_settings, self::set_last_post_time, self::archive_supports_infinity, self::default_footer
 	 * @return string or null
 	 */
 	function footer() {
@@ -873,6 +897,20 @@ class The_Neverending_Home_Page {
 		if ( 'scroll' != self::get_settings()->type || ! self::archive_supports_infinity() )
 			return;
 
+		// Display a footer, either user-specified or a default
+		if ( false !== self::get_settings()->footer_callback && is_callable( self::get_settings()->footer_callback ) )
+			call_user_func( self::get_settings()->footer_callback, self::get_settings() );
+		else
+			self::default_footer();
+	}
+
+	/**
+	 * Render default IS footer
+	 *
+	 * @uses __, wp_get_theme, get_current_theme, apply_filters, home_url, esc_attr, get_bloginfo, bloginfo
+	 * @return string
+	 */
+	private function default_footer() {
 		$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 );

diff --git a/plugins/jetpack/modules/json-api.php b/plugins/jetpack/modules/json-api.php
index fb1473f..e072231 100644
--- a/plugins/jetpack/modules/json-api.php
+++ b/plugins/jetpack/modules/json-api.php
@@ -4,6 +4,7 @@
  * Module Description: Allow applications to securely access your content through the cloud.
  * Sort Order: 100
  * First Introduced: 1.9
+ * Requires Connection: Yes
  */
 
 function jetpack_json_api_toggle() {

diff --git a/plugins/jetpack/modules/latex.php b/plugins/jetpack/modules/latex.php
index 76066cd..eb58f79 100644
--- a/plugins/jetpack/modules/latex.php
+++ b/plugins/jetpack/modules/latex.php
@@ -4,6 +4,7 @@
  * 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
+ * Requires Connection: Yes
  */
 
 /**

diff --git a/plugins/jetpack/modules/likes.php b/plugins/jetpack/modules/likes.php
index 753d4ab..ab8b7b7 100644
--- a/plugins/jetpack/modules/likes.php
+++ b/plugins/jetpack/modules/likes.php
@@ -4,11 +4,12 @@
  * 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
+ * Requires Connection: Yes
  */
 class Jetpack_Likes {
-	var $version = '20130226';
+	var $version = '20130620a';
 
-	function &init() {
+	public static function init() {
 		static $instance = NULL;
 
 		if ( ! $instance ) {
@@ -22,13 +23,14 @@ class Jetpack_Likes {
 		$this->in_jetpack = ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ? false : true;
 
 		add_action( 'init', array( &$this, 'action_init' ) );
+		add_action( 'admin_init', array( $this, 'admin_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' ) );
+			Jetpack::module_configuration_load( __FILE__, array( $this, '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' ) );
@@ -53,12 +55,17 @@ class Jetpack_Likes {
 				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' ) );
 			}
+
+			Jetpack_Sync::sync_options( __FILE__, 'social_notifications_like' );
+
 		} 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_init', array( $this, 'admin_discussion_likes_settings_init' ) ); // Likes notifications
+
 		add_action( 'admin_bar_menu', array( $this, 'admin_bar_likes' ), 60 );
 
 		add_action( 'save_post', array( $this, 'meta_box_save' ) );
@@ -195,6 +202,65 @@ class Jetpack_Likes {
 	}
 
 	/**
+	  * Options to be added to the discussion page (see also admin_settings_init, etc below for Sharing settings page)
+	  */
+
+	function admin_discussion_likes_settings_init() {
+		// Add a temporary section, until we can move the setting out of there and with the rest of the email notification settings
+		add_settings_section( 'likes-notifications', __( 'Likes Notifications', 'jetpack' ), array( $this, 'admin_discussion_likes_settings_section' ), 'discussion' );
+		add_settings_field( 'social-notifications', __( 'Email me whenever', 'jetpack' ), array( $this, 'admin_discussion_likes_settings_field' ), 'discussion', 'likes-notifications' );
+		// Register the setting
+		register_setting( 'discussion', 'social_notifications_like', array( $this, 'admin_discussion_likes_settings_validate' ) );
+	}
+
+	function admin_discussion_likes_settings_section() {
+		// Atypical usage here.  We emit jquery to move likes notification checkbox to be with the rest of the email notification settings
+?>
+	<script type="text/javascript">
+	jQuery( function( $ )  {
+		var table = $( '#social_notifications_like' ).parents( 'table:first' ),
+			header = table.prevAll( 'h3:first' ),
+			newParent = $( '#moderation_notify' ).parent( 'label' ).parent();
+
+		if ( !table.size() || !header.size() || !newParent.size() ) {
+			return;
+		}
+
+		newParent.append( '<br/>' ).append( table.end().parent( 'label' ).siblings().andSelf() );
+		header.remove();
+		table.remove();
+	} );
+	</script>
+<?php
+	}
+
+	function admin_likes_get_option( $option ) {
+		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+			$option_setting = get_blog_option( get_current_blog_id(), $option );
+		} else {
+			$option_setting = get_option( $option );
+		}
+
+		return intval( 'on' == $option_setting );
+	}
+
+	function admin_discussion_likes_settings_field() {
+		$like = $this->admin_likes_get_option( 'social_notifications_like' );
+?>
+		<label><input type="checkbox" id="social_notifications_like" name="social_notifications_like" value="1" <?php checked( $like ); ?> /> <?php esc_html_e( 'Someone likes one of my posts', 'jetpack' ); ?></label>
+<?php
+	}
+
+	function admin_discussion_likes_settings_validate( $input ) {
+		// If it's not set (was unchecked during form submission) or was set to off (during option update), return 'off'.
+		if ( !$input || 'off' == $input )
+			return 'off';
+
+		// Otherwise, return 'on'.
+		return 'on';
+	}
+
+	/**
 	 * The actual options block to be inserted into the sharing page.
 	 */
 	function admin_settings_init() { ?>
@@ -403,6 +469,15 @@ class Jetpack_Likes {
 		</form> <?php
 	}
 
+	function admin_init() {
+		add_filter( 'manage_posts_columns', array( $this, 'add_like_count_column' ) );
+		add_filter( 'manage_pages_columns', array( $this, 'add_like_count_column' ) );
+		add_action( 'manage_posts_custom_column', array( $this, 'likes_edit_column' ), 10, 2 );
+		add_action( 'manage_pages_custom_column', array( $this, 'likes_edit_column' ), 10, 2 );
+		add_action( 'admin_print_styles-edit.php', array( $this, 'load_admin_css' ) );
+		add_action( "admin_print_scripts-edit.php", array( $this, 'enqueue_admin_scripts' ) );
+	}
+
 	function action_init() {
 		if ( is_admin() )
 			return;
@@ -416,22 +491,95 @@ class Jetpack_Likes {
 
 		// 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_script( 'jetpack_resize', plugins_url( '_inc/jquery.jetpack-resize.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_script( 'jetpack_resize', '/wp-content/js/jquery/jquery.jetpack-resize.js', array( 'jquery' ), JETPACK__VERSION, false );
 			wp_enqueue_style( 'jetpack_likes', plugins_url( 'jetpack-likes.css', __FILE__ ), array(), JETPACK__VERSION );
 		}
 	}
 
+	/**
+	* Load the CSS needed for the wp-admin area.
+	*/
+	function load_admin_css() { ?>
+		<style type="text/css">
+			.fixed .column-likes { width: 5em; padding-top: 8px; text-align: center !important; }
+			.fixed .column-stats { width: 5em; }
+			.fixed .column-likes .post-com-count { background-image: none; }
+			.fixed .column-likes .comment-count { background-color: #888; }
+			.fixed .column-likes .comment-count:hover { background-color: #D54E21; }
+			.admin-color-mp6 .fixed .column-likes .post-com-count::after { border: none !important; }
+			.admin-color-mp6 .fixed .column-likes .comment-count { background-color: #bbb; }
+			.admin-color-mp6 .fixed .column-likes .comment-count:hover { background-color: #2ea2cc; }
+			.admin-color-mp6 .fixed .column-likes .vers img { display: none; }
+			.admin-color-mp6 .fixed .column-likes .vers:before {font:20px/1 dashicons;content: '\f155';-webkit-font-smoothing:antialiased;}
+		</style> <?php
+	}
+
+	/**
+	* Load the JS required for loading the like counts.
+	*/
+	function enqueue_admin_scripts() {
+		if ( empty( $_GET['post_type'] ) || 'post' == $_GET['post_type'] || 'page' == $_GET['post_type'] ) {
+			if ( $this->in_jetpack )
+				wp_enqueue_script( 'likes-post-count', plugins_url( 'modules/likes/post-count.js', dirname( __FILE__ ) ), array( 'jquery' ), JETPACK__VERSION );
+			else
+				wp_enqueue_script( 'likes-post-count', plugins_url( 'likes/post-count.js', dirname( __FILE__ ) ), array( 'jquery' ), JETPACK__VERSION );
+		}
+	}
+
+	/**
+	* Add "Likes" column data to the post edit table in wp-admin.
+	*
+	* @param string $column_name
+	* @param int $post_id
+	*/
+	function likes_edit_column( $column_name, $post_id ) {
+		if ( 'likes' == $column_name ) {
+
+			if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+				$blog_id = get_current_blog_id();
+			} else {
+				$jetpack = Jetpack::init();
+				$blog_id = $jetpack->get_option( 'id' );
+			}
+
+			$permalink = get_permalink( get_the_ID() ); ?>
+			<a title="" data-post-id="<?php echo (int) $post_id; ?>" class="post-com-count post-like-count" id="post-like-count-<?php echo (int) $post_id; ?>" data-blog-id="<?php echo (int) $blog_id; ?>" href="<?php echo esc_url( $permalink ); ?>#like-<?php echo (int) $post_id; ?>">
+				<span class="comment-count">0</span>
+			</a>
+			<?php
+		}
+	}
+
+	/**
+	* Add a "Likes" column header to the post edit table in wp-admin.
+	*
+	* @param array $columns
+	* @return array
+	*/
+	function add_like_count_column( $columns ) {
+		$date = $columns['date'];
+		unset( $columns['date'] );
+
+		$columns['likes'] = '<span class="vers"><img title="' . esc_attr__( 'Likes', 'jetpack' ) . '" alt="' . esc_attr__( 'Likes', 'jetpack' ) . '" src="//s0.wordpress.com/i/like-grey-icon.png" /></span>';
+		$columns['date'] = $date;
+
+		return $columns;
+	}
+
 	function post_likes( $content ) {
 		global $post;
 
@@ -456,9 +604,15 @@ class Jetpack_Likes {
 
 		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 );
+		/**
+		* if the same post appears more then once on a page the page goes crazy
+		* we need a slightly more unique id / name for the widget wrapper.
+		*/
+		$uniqid = uniqid();
+
+		$src = sprintf( '%1$s://widgets.wp.com/likes/#blog_id=%2$d&amp;post_id=%3$d&amp;origin=%1$s://%4$s&amp;obj_id=%2$d-%3$d-%5$s', $protocol, $blog_id, $post->ID, $domain, $uniqid );
+		$name = sprintf( 'like-post-frame-%1$d-%2$d-%3$s', $blog_id, $post->ID, $uniqid );
+		$wrapper = sprintf( 'like-post-wrapper-%1$d-%2$d-%3$s', $blog_id, $post->ID, $uniqid );
 
 		$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>';
@@ -493,7 +647,7 @@ class Jetpack_Likes {
 
 		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 );
+		$src = sprintf( '%1$s://widgets.wp.com/likes/#blog_id=%2$d&amp;comment_id=%3$d&amp;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 );
 
@@ -532,10 +686,10 @@ class Jetpack_Likes {
 		}
 
 		add_filter( 'wp_footer', array( $this, 'likes_master' ) );
+		
+		$src = sprintf( '%1$s://widgets.wp.com/likes/#blog_id=%2$d&amp;post_id=%3$d&amp;origin=%1$s://%4$s', $protocol, $blog_id, $post->ID, $domain );
 
-		$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>";
+		$html = "<iframe class='admin-bar-likes-widget jetpack-likes-widget' scrolling='no' frameBorder='0' name='admin-bar-likes-widget' src='$src'></iframe>";
 
 		$node = array(
 				'id'   => 'admin-bar-likes-widget',
@@ -552,12 +706,12 @@ class Jetpack_Likes {
 		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 );
+		$locale = ( '' == get_locale() || 'en' == get_locale() ) ? '' : '&amp;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&amp;mp6=%4$d', $protocol, $this->version, $locale, apply_filters( 'mp6_enabled', 0 ) );
 
-		$likersText = wp_kses( __( '<span>%d</span> bloggers like this:', 'jetpack' ), array( 'span' => array() ) );
+        $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>
+		<iframe src='<?php echo $src; ?>' scrolling='no' 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[
@@ -578,7 +732,7 @@ class Jetpack_Likes {
 					target: target,
 					type: 'likesMessage',
 					data: message,
-					origin: '*'					
+					origin: '*'
 				} );
 			}
 
@@ -628,9 +782,9 @@ class Jetpack_Likes {
 
 						var requests = [];
 						jQuery( '.jetpack-likes-widget-wrapper' ).each( function( i ) {
-							var regex = /like-(post|comment)-wrapper-(\d+)-(\d+)/;
+							var regex = /like-(post|comment)-wrapper-(\d+)-(\d+)-(\w+)/;
 							var match = regex.exec( this.id );
-							if ( ! match || match.length != 4 )
+							if ( ! match || match.length != 5 )
 								return;
 
 							var info = {
@@ -644,6 +798,8 @@ class Jetpack_Likes {
 								info.comment_id = match[3];
 							}
 
+							info.obj_id = match[4];
+
 							requests.push( info );
 						});
 
@@ -658,8 +814,9 @@ class Jetpack_Likes {
 				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'] );
+						jQuery( '#' + event.id + ' .post-likes-widget' ).fadeIn( 'fast', function() {
+							JetpackLikespostMessage( { event: 'likeWidgetDisplayed', blog_id: event.blog_id, post_id: event.post_id, obj_id: event.obj_id }, window.frames['likes-master'] );
+						});
 					});
 				}
 
@@ -747,8 +904,11 @@ class Jetpack_Likes {
 				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>" );
-
+				if ( $wrapper.hasClass( 'slim-likes-widget' ) ) {
+					$wrapper.find( '.post-likes-widget-placeholder' ).after( "<iframe class='post-likes-widget jetpack-likes-widget' name='" + $wrapper.data( 'name' ) + "' height='22px' width='68px' frameBorder='0' scrolling='no' src='" + $wrapper.data( 'src' ) + "'></iframe>" );
+				} else {
+					$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' );
 
@@ -757,9 +917,14 @@ class Jetpack_Likes {
 					$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' ] );
+
+					if ( $wrapper.hasClass( 'slim-likes-widget' ) ) {
+						$wrapper.find( 'iframe' ).Jetpack( 'resizeable' );
+					}
 				});
+				setTimeout( JetpackLikesWidgetQueueHandler, 250 );
 			}
-			setInterval( JetpackLikesWidgetQueueHandler, 250 );
+			JetpackLikesWidgetQueueHandler();
 		//]]>
 		</script>
 <?php
@@ -828,6 +993,9 @@ class Jetpack_Likes {
 				$enabled = $this->is_enabled_sitewide();
 			}
 
+			if ( post_password_required() )
+				$enabled = false;
+
 			/** Other Checks ******************************************************/
 
 			// Do not show on excerpts

diff --git a/plugins/jetpack/modules/likes/style.css b/plugins/jetpack/modules/likes/style.css
index 3885cac..ee34f43 100644
--- a/plugins/jetpack/modules/likes/style.css
+++ b/plugins/jetpack/modules/likes/style.css
@@ -15,6 +15,14 @@ div.jetpack-likes-widget-wrapper {
 	width: 100%;
 }
 
+div.jetpack-likes-widget-wrapper .sd-link-color {
+	font-size: 12px;
+}
+
+div.jetpack-likes-widget-wrapper.slim-likes-widget {
+	width: 1px; /* initial default */
+}
+
 #likes-other-gravatars {
 	display: none;
 	position: absolute;
@@ -28,6 +36,10 @@ div.jetpack-likes-widget-wrapper {
 	z-index: 1000;
 }
 
+#likes-other-gravatars * {
+	line-height: normal;
+}
+
 #likes-other-gravatars .likes-text {
 	color: white;
 	font-size: 14px;
@@ -144,7 +156,7 @@ h3.sd-title {
 .post-likes-widget-placeholder .button span:before {
 	color: #97A8CC;
 	font-family: "Noticons";
-	content: '\2605';
+	content: '\f408';
 	font-size: 16px;
 	line-height: 0;
 	text-shadow: 0 1px 0 #fff;
@@ -164,6 +176,11 @@ h3.sd-title {
 	float: right;
 }
 
+.slim-likes-widget .post-likes-widget {
+	width: auto;
+	float: none;
+}
+
 /* Like Special cases (display on it's own) */
 
 div.sharedaddy.sd-like-enabled .sd-like h3 {

diff --git a/plugins/jetpack/modules/minileven.php b/plugins/jetpack/modules/minileven.php
index e2047e5..89a97d4 100644
--- a/plugins/jetpack/modules/minileven.php
+++ b/plugins/jetpack/modules/minileven.php
@@ -5,6 +5,7 @@
  * Module Description: Automatically optimize your site for mobile devices.
  * Sort Order: 11
  * First Introduced: 1.8
+ * Requires Connection: No
  */
 
 function jetpack_load_minileven() {

diff --git a/plugins/jetpack/modules/minileven/minileven.php b/plugins/jetpack/modules/minileven/minileven.php
index ae2ab01..aa9551c 100644
--- a/plugins/jetpack/modules/minileven/minileven.php
+++ b/plugins/jetpack/modules/minileven/minileven.php
@@ -306,6 +306,23 @@ function jetpack_mobile_css_settings() {
 
 add_action( 'custom_css_submitbox_misc_actions', 'jetpack_mobile_css_settings' );
 
+function jetpack_mobile_customizer_controls( $wp_customize ) {
+	$wp_customize->add_setting( 'wp_mobile_custom_css' , array(
+		'default' => true,
+		'transport' => 'postMessage',
+		'type' => 'option'
+	) );
+
+	$wp_customize->add_control( 'jetpack_mobile_css_control', array(
+		'type' => 'checkbox',
+		'label' => __( 'Include this CSS in the Mobile Theme', 'jetpack' ),
+		'section' => 'jetpack_custom_css',
+		'settings' => 'wp_mobile_custom_css',
+	) );
+}
+
+add_action( 'jetpack_custom_css_customizer_controls', 'jetpack_mobile_customizer_controls' );
+
 function jetpack_mobile_save_css_settings() {
 	update_option( 'wp_mobile_custom_css', isset( $_POST['mobile_css'] ) && ! empty( $_POST['mobile_css'] ) );
 }

diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/content-gallery.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/content-gallery.php
index cf69f25..8db8861 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/content-gallery.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/content-gallery.php
@@ -10,10 +10,10 @@
 
 <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
 	<header class="entry-header">
-		<hgroup>
+		<div class="entry-heading">
 			<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>
+		</div>
 	</header><!-- .entry-header -->
 
 	<div class="entry-content">

diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/content.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/content.php
index 9ab0351..7d035c2 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/content.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/content.php
@@ -8,11 +8,16 @@
 
 	<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
 		<header class="entry-header">
+			<?php if ( '1' == get_option( 'wp_mobile_featured_images' ) && is_home() || is_search() || is_archive() ) : ?>
+				<div class="entry-thumbnail">
+					<a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="<?php the_ID(); ?>" class="minileven-featured-thumbnail"><?php the_post_thumbnail(); ?></a>
+				</div><!-- .entry-thumbnail -->
+			<?php endif; ?>
 			<?php if ( is_sticky() ) : ?>
-				<hgroup>
+				<div class="entry-heading">
 					<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>
+				<div>
 			<?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; ?>
@@ -30,8 +35,8 @@
 		</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 if ( '1' == get_option( 'wp_mobile_excerpt' ) && ( is_home() || is_search() || is_archive() ) ) : ?>
+			<?php echo minileven_excerpt( 300 ); ?>
 		<?php else : ?>
 			<?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'jetpack' ) ); ?>
 		<?php endif; ?>

diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/footer.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/footer.php
index b739fe4..d57b617 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/footer.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/footer.php
@@ -28,8 +28,6 @@
 	</div>
 </footer><!-- #colophon -->
 
-
-
 <?php wp_footer(); ?>
 
 </body>

diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/functions.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/functions.php
index d13cb23..6bd7ee0 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/functions.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/functions.php
@@ -83,6 +83,37 @@ function minileven_scripts() {
 }
 add_action( 'wp_enqueue_scripts', 'minileven_scripts' );
 
+function minileven_fonts() {
+
+	/*	translators: If there are characters in your language that are not supported
+		by Open Sans, translate this to 'off'. Do not translate into your own language. */
+
+	if ( 'off' !== _x( 'on', 'Open Sans font: on or off', 'minileven' ) ) {
+
+		$opensans_subsets = 'latin,latin-ext';
+
+		/* translators: To add an additional Open Sans character subset specific to your language, translate
+		this to 'greek', 'cyrillic' or 'vietnamese'. Do not translate into your own language. */
+		$opensans_subset = _x( 'no-subset', 'Open Sans font: add new subset (greek, cyrillic, vietnamese)', 'minileven' );
+
+		if ( 'cyrillic' == $opensans_subset )
+			$opensans_subsets .= ',cyrillic,cyrillic-ext';
+		elseif ( 'greek' == $opensans_subset )
+			$opensans_subsets .= ',greek,greek-ext';
+		elseif ( 'vietnamese' == $opensans_subset )
+			$opensans_subsets .= ',vietnamese';
+
+		$protocol = is_ssl() ? 'https' : 'http';
+
+		$opensans_query_args = array(
+			'family' => 'Open+Sans:200,200italic,300,300italic,400,400italic,600,600italic,700,700italic',
+			'subset' => $opensans_subsets,
+		);
+		wp_register_style( 'minileven-open-sans', add_query_arg( $opensans_query_args, "$protocol://fonts.googleapis.com/css" ), array(), null );
+	}
+}
+add_action( 'init', 'minileven_fonts' );
+
 /**
  * Register our sidebars and widgetized areas.
  * @since Minileven 1.0
@@ -104,17 +135,16 @@ function minileven_posts_per_page() {
 }
 add_filter('pre_option_posts_per_page', 'minileven_posts_per_page');
 
-/* This function determines the actual theme the user is using. */
+/**
+ * Determine the currently active theme.
+ */
 function minileven_actual_current_theme() {
-	if ( function_exists( 'jetpack_mobile_template' ) )
-		remove_action( 'option_template', 'jetpack_mobile_template' );
-
-	$template = get_option( 'template' );
+	$removed = remove_action( 'option_stylesheet', 'jetpack_mobile_stylesheet' );
+	$stylesheet = get_option( 'stylesheet' );
+	if ( $removed )
+		add_action( 'option_stylesheet', 'jetpack_mobile_stylesheet' );
 
-	if ( function_exists( 'jetpack_mobile_template' ) )
-		add_action( 'option_template', 'jetpack_mobile_template' );
-
-	return $template;
+	return $stylesheet;
 }
 
 /* This function grabs the location of the custom menus from the current theme. If no menu is set in a location
@@ -149,4 +179,10 @@ function minileven_get_background() {
 /**
  * Implement the Custom Header functions
  */
-require( get_template_directory() . '/inc/custom-header.php' );
\ No newline at end of file
+require( get_template_directory() . '/inc/custom-header.php' );
+
+/**
+ * If the user has set a static front page, show all posts on the front page, instead of a static page.
+ */
+if ( '1' == get_option( 'wp_mobile_static_front_page' ) )
+	add_filter( 'pre_option_page_on_front', '__return_zero' );
\ 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
index 7c5f9a6..1b7cad9 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/header.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/header.php
@@ -18,25 +18,21 @@
 
 <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 -->
+			<nav id="access" class="site-navigation main-navigation" role="navigation">
+				<h3 class="menu-toggle"><?php _e( 'Menu', 'jetpack' ); ?></h3>
+
 				<?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 ) );
+						wp_nav_menu( array( 'theme_location' => 'primary', 'container_class' => '', 'menu_class' => 'nav-menu', 'menu' => $menu_id ) );
 					else: // if the $location variable is false, wp_page_menu() is shown instead.
-						wp_nav_menu( array( 'theme_location' => 'primary' ) );
+						wp_nav_menu( array( 'theme_location' => 'primary', 'container_class' => '', 'menu_class' => 'nav-menu' ) );
 					endif;
 				?>
 			</nav><!-- #access -->
@@ -44,6 +40,8 @@
 				<?php get_search_form(); ?>
 			</div><!-- .search-form-->
 		</div><!-- .menu-search-->
-	</header><!-- #branding -->
 
-	<div id="main">
\ No newline at end of file
+	<?php minileven_header(); ?>
+
+	<div id="page" class="hfeed">
+		<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
index be8402b..30f5719 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/image.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/image.php
@@ -85,7 +85,7 @@ get_header(); ?>
 
 				<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-previous"><?php previous_image_link( false, __( '&laquo; Previous' , 'jetpack' ) ); ?></span>
 					<span class="nav-next"><?php next_image_link( false, __( 'Next &raquo; ' , 'jetpack' ) ); ?></span>
 				</nav><!-- #nav-single -->
 

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
index 8a7a21e..dc8758b 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/custom-header.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/custom-header.php
@@ -31,20 +31,25 @@ 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.
+	if ( 'blank' != $header_text || false != $header_image ) : ?>
+
+		<header id="branding" role="banner">
+			<?php if ( 'blank' != $header_text ) : ?>
+					<div class="site-branding">
+						<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>
+					</div>
+			<?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. ?>
+		</header><!-- #branding -->
+<?php endif; // end check for both header text and header image
 }
 
 /* This function displays the custom background image or color, and custom text color */
@@ -82,7 +87,8 @@ function minileven_show_background_and_header_color() {
 				<?php echo trim( $style ); ?>
 			}
 		<?php } ?>
-		#page {
+		#page,
+		#branding {
 			margin: 0.6em 0.6em 0.8em;
 		}
 		#site-generator {

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
index 2fc5f6d..6a39839 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/template-tags.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/template-tags.php
@@ -62,8 +62,6 @@ function minileven_comment( $comment, $args, $depth ) {
 							)
 						);
 					?>
-
-					<?php edit_comment_link( __( 'Edit', 'jetpack' ), '<span class="edit-link">', '</span>' ); ?>
 				</div><!-- .comment-author .vcard -->
 
 				<?php if ( $comment->comment_approved == '0' ) : ?>
@@ -74,9 +72,8 @@ function minileven_comment( $comment, $args, $depth ) {
 			</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'] ) ) ); ?>
+				<?php comment_reply_link( array_merge( $args, array( 'reply_text' => __( 'Reply', 'jetpack' ), 'depth' => $depth, 'max_depth' => $args['max_depth'] ) ) ); ?>
 			</div><!-- .reply -->
 		</article><!-- #comment-## -->
 

diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/tweaks.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/tweaks.php
index 35a9672..8bbaf4d 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/tweaks.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/tweaks.php
@@ -9,21 +9,25 @@
  */
 
 /**
- * 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;
+* Sets the post excerpt length based on number of characters, without breaking words at the end
+*
+*/
+function minileven_excerpt( $count ) {
+	$excerpt = get_the_content();
+	$excerpt = strip_tags( $excerpt );
+	$excerpt = strip_shortcodes( $excerpt );
+	$excerpt = substr( $excerpt, 0, $count );
+	$excerpt = substr( $excerpt, 0, strripos( $excerpt, " " ) );
+	$excerpt = $excerpt . minileven_continue_reading_link();
+	return $excerpt;
 }
-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>';
+	return ' &hellip; <a href="'. esc_url( get_permalink() ) . '">' . __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'jetpack' ) . '</a>';
 }
 
 /**

diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/index.php b/plugins/jetpack/modules/minileven/theme/pub/minileven/index.php
index 71aa73b..9821b6d 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/index.php
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/index.php
@@ -70,4 +70,6 @@ get_header(); ?>
 			<?php minileven_content_nav( 'nav-below' ); ?>
 
 		</div><!-- #primary -->
+
+<?php get_sidebar(); ?>
 <?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
index f6e1d06..7eaf1e3 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/js/small-menu.js
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/js/small-menu.js
@@ -1,41 +1,33 @@
 /**
- * Handles toggling the main navigation menu for small screens.
+ * navigation.js
+ *
+ * Handles toggling the navigation menu for small screens.
  */
-jQuery( document ).ready( function( $ ) {
-	var $subsidiary = $( '#branding' ),
-	    timeout = false;
+( function() {
+	var nav = document.getElementById( 'access' ), button, menu;
+	if ( ! nav )
+		return;
+	button = nav.getElementsByTagName( 'h3' )[0];
+	menu   = nav.getElementsByTagName( 'ul' )[0];
+	if ( ! button )
+		return;
 
-	$.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' );
+	// Hide button if menu is missing or empty.
+	if ( ! menu || ! menu.childNodes.length ) {
+		button.style.display = 'none';
+		return;
+	}
 
-		$( '.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();
+	button.onclick = function() {
+		if ( -1 == menu.className.indexOf( 'nav-menu' ) )
+			menu.className = 'nav-menu';
 
-		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
+		if ( -1 != button.className.indexOf( 'toggled-on' ) ) {
+			button.className = button.className.replace( ' toggled-on', '' );
+			menu.className = menu.className.replace( ' toggled-on', '' );
+		} else {
+			button.className += ' toggled-on';
+			menu.className += ' toggled-on';
+		}
+	};
+} )();
\ 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
index 692a8f4..e70415b 100644
--- a/plugins/jetpack/modules/minileven/theme/pub/minileven/style.css
+++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/style.css
@@ -10,6 +10,27 @@ 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
 */
 
+.image-attachment .entry-caption p {
+	font-size: 0.769em;
+	letter-spacing: 0.1em;
+	line-height: 2.6;
+	margin: 0 0 2.6em;
+	text-transform: uppercase;
+}
+
+/* =Webfont, thanks to FontSquirrel.com for conversion!
+-------------------------------------------------------------- */
+@font-face {
+	font-family: 'Genericons';
+	src: url('inc/fonts/genericons-regular-webfont.eot');
+	src: url('inc/fonts/genericons-regular-webfont.eot?#iefix') format('embedded-opentype'),
+		 url('inc/fonts/genericons-regular-webfont.woff') format('woff'),
+		 url('inc/fonts/genericons-regular-webfont.ttf') format('truetype'),
+		 url('inc/fonts/genericons-regular-webfont.svg#genericonsregular') format('svg');
+	font-weight: normal;
+	font-style: normal;
+
+}
 
 /* =Reset default browser CSS. Based on work by Eric Meyer: http://meyerweb.com/eric/tools/css/reset/index.html
 -------------------------------------------------------------- */
@@ -47,7 +68,7 @@ a img {
 	border: 0;
 }
 article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
+footer, header, menu, nav, section {
 	display: block;
 }
 
@@ -56,16 +77,21 @@ footer, header, hgroup, menu, nav, section {
 ----------------------------------------------- */
 
 body, input, textarea {
-	color: #373737;
-	font: 13px "Helvetica Neue", Helvetica, Arial, sans-serif;
+	color: #404040;
+	font: 13px "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
 	line-height: 1.625;
 	word-wrap: break-word;
 }
 body {
-	background: #eee;
+	background: #f1f1f1;
+	font-weight: 400;
 }
-#page {
+#page,
+#branding {
 	background: #fff;
+	-moz-box-shadow: 0 1px 2px rgba( 0,0,0,0.075 );
+	-webkit-box-shadow: 0 1px 2px rgba( 0,0,0,0.075 );
+	box-shadow: 0 1px 2px rgba( 0,0,0,0.075 );
 }
 
 /* Headings */
@@ -111,7 +137,6 @@ cite, em, i {
 	font-style: italic;
 }
 blockquote {
-	font-family: Georgia, "Bitstream Charter", serif;
 	font-style: italic;
 	font-weight: normal;
 	margin: 0;
@@ -192,18 +217,34 @@ input[type=email] {
 input#s {
 	border-radius: 2px;
 	height: 1.692em;
-	line-height: 1.2em;
-	padding: 0.4em 0.6em;
+	line-height: 1.2;
+	padding: 0.4em 0.6em 0.29em;
+}
+input#s:focus {
+	padding-bottom: 0.3em;
 }
 input#searchsubmit {
 	display: none;
 }
+input#s:focus,
+input[type=text]:focus,
+input[type=email]:focus,
+textarea:focus {
+	font-size: 1.231em;
+}
 
 /* Links */
 a {
-	color: #00a4bc;
+	color: #278dbc;
 	text-decoration: none;
 }
+a:hover,
+.entry-title a:hover,
+.entry-meta .edit-link a:hover,
+.commentlist .edit-link a:hover,
+.entry-meta .comments-link a:hover {
+	color: #7dcae7;
+}
 /* Assistive text */
 .assistive-text {
 	clip: rect(1px, 1px, 1px, 1px);
@@ -219,12 +260,19 @@ a {
 	margin: 0 auto;
 	padding: 2.5%;
 }
+#branding {
+	margin: 0.6em auto 0;
+	padding: 2.5% 2.5% 1.5%;
+}
 
 #primary,
 #secondary {
 	margin: 0 auto;
 	width: auto;
 }
+#secondary {
+	margin-top: 0.8em;
+}
 
 /* Alignment */
 .aligncenter,
@@ -240,7 +288,6 @@ a {
 embed,
 iframe,
 object {
-	height: auto;
 	width: auto;
 }
 
@@ -248,7 +295,7 @@ object {
 /* =Header
 ----------------------------------------------- */
 
-#branding hgroup {
+#branding .site-branding {
 	margin-bottom: 1.3em;
 }
 #site-title,
@@ -259,7 +306,7 @@ object {
 	color: #111;
 	font-size: 1.846em;
 	font-weight: bold;
-	line-height: 1.3em;
+	line-height: 1.3;
 }
 #site-description {
 	color: #7a7a7a;
@@ -280,13 +327,12 @@ header img {
 ----------------------------------------------- */
 
 .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);
+	background: #1e8cbe;
+	-webkit-box-shadow: inset 0 -1px rgba(0, 86, 132, 0.8), 0 1px 3px rgba(0, 86, 132, 0.4);
+	-moz-box-shadow: inset 0 -1px 0 rgba(0, 86, 132, 0.8), 0 1px 3px rgba(0, 86, 132, 0.4);
+	box-shadow: inset 0 -1px 0 rgba(0, 86, 132, 0.8), 0 1px 3px rgba(0, 86, 132, 0.4);
 	clear: both;
-	margin-bottom: 1.3em;
+	height: 46px;
 	width: 100%;
 }
 .menu-search:after {
@@ -294,35 +340,44 @@ header img {
 	content: "";
 	display: block;
 }
+.menu-search,
+#access,
+.menu-toggle,
+#access .menu-label {
+	height: 46px;
+}
 
 /* Small menu */
 #access {
 	float: left;
-	width: 55%;
+	width: 60%;
 }
 .search-form {
 	float: right;
 	text-align: right;
-	width: 43%;
+	width: 39%;
 }
 .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;
+#access h3.toggled-on {
+	opacity: 0.8;
 }
-.main-small-navigation {
-	position: relative;
-	z-index: 99999;
+#access {
+ 	position: relative;
+ 	z-index: 99999;
+ }
+#access ul.nav-menu {
+	background: #fff;
+	-webkit-box-shadow: 0 0 2px rgba(0, 0, 0, 0.15), 0 3px 8px rgba(0, 0, 0, 0.1);
+	-moz-box-shadow: 0 0 2px rgba(0, 0, 0, 0.15), 0 3px 8px rgba(0, 0, 0, 0.1);
+	box-shadow: 0 0 2px rgba(0, 0, 0, 0.15), 0 3px 8px rgba(0, 0, 0, 0.1);
+	display: none;
+ 	position: absolute;
+		left: 0.5em;
+		top: 3em;
+ 	width: 100%;
+ 	z-index: 99999;
 }
 .main-small-navigation .menu {
 	background: #f9f9f9;
@@ -330,65 +385,74 @@ header img {
 	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;
+#access ul.nav-menu:before {
+	color: #fff;
+	content: '\f500';
+    display: inline-block;
+    font: 0.9em/1 'Genericons';
+    left: 49px;
+    position: absolute;
+    top: -11px;
+ }
+#access ul li {
+	border-bottom: 1px solid rgba( 0, 0, 0, 0.1 );
+	padding: 1em 0.8em;
+}
+#access ul li:last-of-type {
+ 	border: none;
+}
+#access ul ul li,
+#access ul ul ul li {
+ 	border: none;
+ 	padding-bottom: 0;
+}
+#access a {
 	display: block;
-	font-size: 0.923em;
-	font-weight: bold;
+	font-size: 1em;
 }
-.main-small-navigation ul {
+#access ul {
+	display: none;
 	list-style: none;
 	margin: 0;
 	padding: 0.5em 0;
 }
-.main-small-navigation .sub-menu {
+#access ul ul {
+	display: block;
+}
+#access .sub-menu {
 	margin: 0 0 0 15px;
 }
-#access .menu-label {
+#access .menu-toggle {
 	clear: none;
+	color: #fff;
 	font-size: 1.077em;
-	font-weight: bold;
-	line-height: 2.5em;
-	padding-left: 0.8em;
-	text-shadow: 0 1px 0 #fff;
+	line-height: 2.5;
+	padding: 0.3em 0 0 0.8em;
 }
-#access .menu-label:after {
-	color: #999;
-    content: "+";
+#access .menu-toggle:after {
+	content: '\f502';
     cursor: pointer;
-    font-size: 1em;
-    font-weight: bold;
-    margin-left: 0.5em;
-    width: 18px;
-    height: 18px;
-	text-shadow: 0 1px 0 #fff;
+    display: inline-block;
+    font: 0.7em/1 'Genericons';
+    margin-left: 0.8em;
+	margin-top: 1.7em;
+    position: absolute;
 }
-#access .toggled-on .menu-label:after {
-	content: "-";
+#access .toggled-on:after {
+	opacity: 0.8;
 }
-.main-small-navigation .menu {
-	display: none;
+#access ul.nav-menu.toggled-on {
+    display: inline-block;
 }
 .search-form #s {
-	background: #eee;
-	border: 1px solid #ddd;
+	background: #006d9d;
+	border: 1px solid #00587f;
+	border-width: 0 0 0 1px;
 	border-radius: 0;
-	color: #888;
-	font-size: 0.923em;
-	margin-right: 1%;
-	text-shadow: 0 1px 0 #fff;
+	color: rgba( 255, 255, 255, 0.6 );
+	font-size: 1em;
+	height: 30px;
+	margin-right: 0;
 	padding: 0.6em;
 	width: 80%;
 }
@@ -400,9 +464,10 @@ header img {
 .page-title {
 	color: #666;
 	font-size: 0.769em;
-	font-weight: 500;
+	font-weight: 300;
 	letter-spacing: 0.1em;
-	line-height: 2.6em;
+	line-height: 2.6;
+	margin-bottom: 1.2em;
 	text-transform: uppercase;
 }
 .page-title a {
@@ -419,7 +484,7 @@ header img {
 	position: relative;
 }
 .hentry {
-	border-bottom: 1px solid #ddd;
+	border-bottom: 1px solid #ececec;
 }
 .hentry:last-child,
 .no-results,
@@ -433,11 +498,8 @@ body.singular .hentry {
 }
 .entry-title {
 	clear: both;
-	color: #222;
-	font-size: 1.615em;
-	font-weight: bold;
-	line-height: 1.5em;
-	padding-bottom: .3em;
+	font-size: 1.538em;
+	line-height: 1.260;
 	word-wrap: break-word;
 }
 .featured-post .entry-title {
@@ -445,37 +507,97 @@ body.singular .hentry {
 }
 .entry-title,
 .entry-title a {
-	color: #222;
+	color: #333;
 	text-decoration: none;
 }
 .entry-meta {
 	color: #666;
 	clear: both;
 	font-size: 0.923em;
-	line-height: 1.385em;
+	font-weight: 300;
+	line-height: 1.385;
 	overflow: hidden;
 	padding: 0 0 0.6em 0;
 }
-.entry-meta a {
-	font-weight: bold;
+.entry-meta .entry-date,
+.entry-meta .entry-gallery {
+	display: block;
+	float: left;
+}
+.entry-meta .author-link {
+	display: block;
+	margin-top: 0.7em;
+}
+.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,
+.entry-meta .comments-link a,
+a.comment-reply-link {
+	color: #464646;
+}
+.entry-meta .edit-link a {
+	float: right;
+	text-decoration: none;
+	padding: 0 0.615em;
+}
+.entry-meta .comments-link a:before,
+.entry-meta .edit-link a:before {
+	display: inline-block;
+	-webkit-font-smoothing: antialiased;
+	font: normal 18px/1 'Genericons';
+	margin-right: 0.1em;
+	vertical-align: top;
+}
+.entry-meta .comments-link a:before {
+	content: '\f300';
+	font-family: Genericons;
+}
+.entry-meta .edit-link a:before,
+.commentlist .edit-link a:before {
+	content: '\f411';
+	font-family: Genericons;
+}
+.commentlist .edit-link a:before,
+.entry-meta .comments-link a:before,
+.entry-meta .edit-link a:before,
+a.comment-reply-link:before {
+	color: #7bcbe4;
 }
 .entry-content {
+	font-size: 1em;
+	line-height: 1.538;
+	margin: 1.286em 0;
 	padding: 0;
 }
 .entry-content h1,
 .entry-content h2,
 .comment-content h1,
-.comment-content h2 {
+.comment-content h2,
+.entry-content h3,
+.comment-content h3 {
 	color: #000;
-	font-weight: bold;
 	margin: 0 0 .8125em;
 }
+.entry-content h1,
+.comment-content h1 {
+	font-size: 1.5em;
+	line-height: 2.9;
+}
+.entry-content h2,
+.comment-content h2 {
+	font-size: 1.4em;
+	line-height: 2.6;
+}
 .entry-content h3,
 .comment-content h3 {
-	font-size: 0.769em;
-	letter-spacing: 0.1em;
-	line-height: 2.6em;
-	text-transform: uppercase;
+	font-size: 1.3em;
+	line-height: 2.3;
 }
 .entry-content table,
 .comment-content table {
@@ -489,7 +611,7 @@ body.singular .hentry {
 	font-size: 0.769em;
 	font-weight: 500;
 	letter-spacing: 0.1em;
-	line-height: 2.6em;
+	line-height: 2.6;
 	text-transform: uppercase;
 }
 .entry-content td,
@@ -519,44 +641,15 @@ dl.gallery-item {
 	margin: 0 0 1em;
 }
 .page-link a {
-	background: #eee;
-	color: #373737;
+	background: #278dbc;
+	color: #fff;
 	margin: 0;
-	padding: 0.154em 0.231em;
+	padding: 0.1em 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,
@@ -565,7 +658,7 @@ dl.gallery-item {
 	display: block;
 	height: auto;
 	margin: 0 auto;
-	max-width: 100%; /* Fluid images for posts, comments, and widgets */
+	max-width: 100% !important; /* Fluid images for posts, comments, and widgets */
 }
 #content .gallery-columns-3 .gallery-item img,
 #content .gallery-columns-4 .gallery-item img,
@@ -609,8 +702,7 @@ p img,
 }
 .wp-caption .wp-caption-text,
 .gallery-caption {
-	color: #666;
-	font-family: Georgia, serif;
+	color: #999;
 	font-size: 0.923em;
 }
 .wp-caption .wp-caption-text {
@@ -664,17 +756,24 @@ and remove the padding rules below.
 */
 .entry-header .entry-format {
 	color: #666;
-	font-size: 10px;
-	font-weight: 500;
+	font-size: 0.7em;
+	font-weight: 300;
 	letter-spacing: 0.1em;
-	line-height: 2.6em;
+	line-height: 2em;
 	position: absolute;
 	text-transform: uppercase;
 	top: -5px;
 }
-.entry-header hgroup .entry-title {
+.entry-header .entry-heading .entry-title {
 	padding-top: 0.8em;
 }
+.entry-header .entry-heading {
+	position: relative;
+}
+.entry-thumbnail {
+	margin-bottom: 0.7em;
+	text-align: center;
+}
 
 /* Singular content styles for Posts and Pages */
 .singular .hentry {
@@ -798,13 +897,6 @@ and remove the padding rules below.
 	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
@@ -815,7 +907,7 @@ and remove the padding rules below.
 }
 #nav-below,
 #nav-single {
-	margin: 0 auto 0.6em;
+	margin: 0 auto 1.9em;
 	overflow: hidden;
 	width: 100%;
 }
@@ -841,12 +933,11 @@ and remove the padding rules below.
 }
 .nav-previous a,
 .nav-next a {
-	background: #00a4bc;
+	background: #278dbc;
 	color: #fff;
 	display: block;
 	font-size: 1.231em;
-	font-weight: bold;
-	padding: 1.2em 0;
+	padding: 1em 0;
 	text-align: center;
 	width: 100%;
 }
@@ -868,29 +959,34 @@ and remove the padding rules below.
 	color: #666;
 	font-size: 0.923em;
 	padding: .6em 0.8em;
+	-moz-box-shadow: 0 1px 2px rgba( 0,0,0,0.075 );
+	-webkit-box-shadow: 0 1px 2px rgba( 0,0,0,0.075 );
+	box-shadow: 0 1px 2px rgba( 0,0,0,0.075 );
 }
 .widget {
 	border-bottom: 1px solid #ddd;
 	clear: both;
 	margin: 0;
-	padding: 1.625em 0;
+	overflow: hidden;
+	padding: 1em 0;
 }
 .widget:last-of-type {
 	border: 0;
 }
 .widget-title {
 	color: #666;
-	font-size: 0.833em;
-	letter-spacing: 0.1em;
+	font-size: 1.2em;
+	font-weight: bold;
 	line-height: 2em;
 	margin-bottom: 0.5em;
-	text-transform: uppercase;
 }
 .widget-title a {
 	color: #666;
 }
 .widget ul {
+	list-style: none;
 	margin-bottom: 0;
+	margin-left: 0;
 }
 .widget ul ul {
 	margin-left: 1.5em;
@@ -899,7 +995,7 @@ and remove the padding rules below.
 	color: #777;
 }
 .widget a {
-	font-weight: bold;
+	font-weight: normal;
 	text-decoration: none;
 }
 .widget a:hover,
@@ -924,7 +1020,7 @@ and remove the padding rules below.
 	top: -2px;
 }
 .widget_search #searchsubmit:active {
-	background: #00a4bc;
+	background: #278dbc;
 	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);
@@ -1025,7 +1121,7 @@ and remove the padding rules below.
 #flickr_badge_uber_wrapper a:link,
 #flickr_badge_uber_wrapper a:active,
 #flickr_badge_uber_wrapper a:visited {
-	color: #00a4bc !important;
+	color: #278dbc !important;
 }
 
 
@@ -1055,14 +1151,15 @@ and remove the padding rules below.
 }
 .commentlist {
 	list-style: none;
-	margin: 0 auto;
+	margin: 2em auto;
 	width: 100%;
 }
 .commentlist > li.comment {
-	background: #f6f6f6;
-	border: 1px solid #ddd;
-	border-width: 1px 0;
+	border: 1px solid rgba(0, 0, 0, 0.1);
+	border-width: 1px 0 0;
+	clear: both;
 	margin: 0 -2.5% 0.5em;
+	overflow: hidden;
 	padding: .8em;
 	position: relative;
 }
@@ -1090,26 +1187,28 @@ and remove the padding rules below.
 .commentlist .reblog p:first-child a {
 	font-weight: bold;
 }
-.commentlist .pingback,
+.commentlist .pingback {
+	border-top: 1px solid rgba( 0, 0, 0, 0.1 );
+	margin: 0 -2.5% 0.5em;
+}
 .commentlist .pingback p {
-	margin: 0 0 .8em;
+	color: #c0c0c0;
+	margin-bottom: 0;
+	padding: 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;
+	background: #f9f9f9;
+	border-top: 1px solid rgba( 0, 0, 0, 0.1 );
+	clear: both;
 	margin: 1.625em 0 0;
-	padding: 1.625em;
+	overflow: hidden;
+	padding: 1.625em 1.625em 0.5em;
 	position: relative;
 }
-.commentlist .children li.comment .fn {
-	display: block;
-}
 .comment-meta .fn {
 	font-style: normal;
 }
@@ -1118,21 +1217,17 @@ and remove the padding rules below.
 	margin-left: 4em;
 }
 .comment-meta {
-	color: #666;
 	font-size: 0.923em;
 }
 .comment-content {
-	padding-top: 0.2em;
+	margin-top: 1em;
 }
 .commentlist .children li.comment .comment-meta {
-	line-height: 1.625em;
+	line-height: 1.625;
 	margin-left: 3.462em;
 }
 .commentlist .children li.comment .comment-content {
-	margin: 1.625em 0 0;
-}
-.comment-meta a {
-	font-weight: bold;
+	margin: 1em 0 0 3.1em;
 }
 .comment-meta a:focus,
 .comment-meta a:active,
@@ -1140,8 +1235,6 @@ and remove the padding rules below.
 }
 .commentlist .avatar {
 	background: transparent;
-	-moz-border-radius: 3px;
-	border-radius: 3px;
 	display: block;
 	padding: 0;
 	position: absolute;
@@ -1158,46 +1251,31 @@ and remove the padding rules below.
 	position: absolute;
 	top: 2.2em;
 }
+.comment-actions {
+	float: right;
+	font-weight: 300;
+	margin-bottom: 1em;
+}
+a.comment-reply-link:before {
+	content: '\f412';
+	display: inline-block;
+	-webkit-font-smoothing: antialiased;
+	font: normal 13px/1 'Genericons';
+	margin: 0.2em 0.1em 0 0;
+	vertical-align: top;
+}
 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;
@@ -1219,10 +1297,8 @@ a.comment-reply-link > span {
 #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;
 }
@@ -1245,6 +1321,9 @@ a.comment-reply-link > span {
 	font-size: 0.8em;
 	color: #666;
 }
+#respond .logged-in-as {
+	margin-top: 1em;
+}
 #respond p {
 	margin: 0.769em 0 0;
 }
@@ -1252,30 +1331,61 @@ a.comment-reply-link > span {
 	margin: 0;
 }
 #respond input#submit {
-	background: #00a4bc;
+	background-color: #2ea2cc;
+	background-image: -moz-linear-gradient(top, #278dbc 0%, #0074a2 100%);
+	background-image: -webkit-linear-gradient(top, #278dbc 0%,#0074a2 100%);
+	background-image: -ms-linear-gradient(top, #278dbc 0%,#0074a2 100%);
+	background-image: -o-linear-gradient(top, #278dbc 0%,#0074a2 100%);
+	background-image: linear-gradient(top, #278dbc 0%,#0074a2 100%);
+
+	-moz-box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
+	-webkit-box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
+	-o-box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
+	-ms-box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
+	box-shadow: inset 0 1px 0 rgba(120,200,230,0.5);
 	border: none;
-	border-radius: 3px;
-	box-shadow: 0px 1px 2px rgba(0,0,0,0.3);
-	color: #fff;
+	-moz-border-radius: 2px 0 0 0;
+	-webkit-border-radius: 2px 0 0 0;
+	-o-border-radius: 2px 0 0 0;
+	-ms-border-radius: 2px 0 0 0;
+	border-radius: 2px;
+	color: rgba( 255, 255, 255, 0.9 );
 	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);
+	text-shadow: 0 -1px 0 rgba(0,116,162,0.8);
 }
-#respond input#submit:active {
-	background: #00879c;
+#respond input#submit:hover {
 	color: #fff;
+	text-shadow: 0 -1px 0 rgb(0,116,162);
+
+	background-image: -moz-linear-gradient(top, #2ea2cc 0%, #0074a2 100%);
+	background-image: -webkit-linear-gradient(top, #2ea2cc 0%,#0074a2 100%);
+	background-image: -o-linear-gradient(top, #2ea2cc 0%,#0074a2 100%);
+	background-image: -ms-linear-gradient(top, #2ea2cc 0%,#0074a2 100%);
+	background-image: linear-gradient(top, #2ea2cc 0%,#0074a2 100%);
+
+	-moz-box-shadow: inset 0 1px 0 #2ea2cc, inset 0 2px 0 rgba(120,200,230,0.7);
+	-webkit-box-shadow: inset 0 1px 0 #2ea2cc, inset 0 2px 0 rgba(120,200,230,0.7);
+	-o-box-shadow: inset 0 1px 0 #2ea2cc, inset 0 2px 0 rgba(120,200,230,0.7);
+	-ms-box-shadow: inset 0 1px 0 #2ea2cc, inset 0 2px 0 rgba(120,200,230,0.7);
+	box-shadow: inset 0 1px 0 #2ea2cc, inset 0 2px 0 rgba(120,200,230,0.7);
 }
-#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;
+#respond input#submit:active {
+	color:rgba(255,255,255,.9);
+	background-image: -moz-linear-gradient(top, #278dbc 0%, #0074a2 100%);
+	background-image: -webkit-linear-gradient(top, #278dbc 0%,#0074a2 100%);
+	background-image: -o-linear-gradient(top, #278dbc 0%,#0074a2 100%);
+	background-image: -ms-linear-gradient(top, #278dbc 0%,#0074a2 100%);
+	background-image: linear-gradient(top, #278dbc 0%,#0074a2 100%);
+
+	-moz-box-shadow: inset 0 1px 5px #005684, inset 0 -1px 0 #278dbc;
+	-webkit-box-shadow: inset 0 1px 5px #005684, inset 0 -1px 0 #278dbc;
+	-o-box-shadow: inset 0 1px 5px #005684, inset 0 -1px 0 #278dbc;
+	-ms-box-shadow: inset 0 1px 5px #005684, inset 0 -1px 0 #278dbc;
+	box-shadow: inset 0 1px 5px #005684, inset 0 -1px 0 #278dbc;
 }
 .commentlist #respond {
 	margin: 1.625em 0 0;
@@ -1285,30 +1395,23 @@ a.comment-reply-link > span {
 	margin: 6px 0;
 }
 #reply-title {
-	color: #373737;
 	font-size: 1.5em;
-	font-weight: bold;
-	line-height: 0.733em;
+	line-height: 0.733;
 }
 .comment #reply-title {
 	margin-top: 1em;
 }
 #cancel-comment-reply-link {
-	color: #888;
+	color: #bd3500;
 	display: block;
-	font-size: 0.923em;
-	font-weight: normal;
-	line-height: 2.2em;
+	font-size: 0.6em;
+	font-weight: 300;
+	line-height: 2.2;
+    margin-top: 0.4em;
 	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;
+	line-height: 2.2;
 }
 #respond input[type=text] {
 	display: block;
@@ -1330,7 +1433,7 @@ p.comment-form-comment {
 ----------------------------------------------- */
 
 #colophon {
-	background: #434343;
+	background: #f1f1f1;
 	clear: both;
 	margin-bottom: -2em;
 	padding-bottom: 1em;
@@ -1338,23 +1441,20 @@ p.comment-form-comment {
 
 /* Site Generator Line */
 #site-generator {
-	background: #434343;
 	border-top: 1px solid #ddd;
-	color: #fff;
 	font-size: 0.923em;
-	line-height: 2.2em;
+	line-height: 2.2;
 	padding: 2.2em 0.5em;
 	text-align: center;
 }
 #site-generator a {
-	color: #00a4bc;
-	font-weight: bold;
+	color: #278dbc;
 }
 #site-generator .sep {
 	color: transparent;
 	display: inline-block;
 	height: 16px;
-	line-height: 1.231em;
+	line-height: 1.231;
 	margin: 0 0.538em;
 	text-indent: 40px; /* Push the separator just out of the way */
 	width: 3.077em;
@@ -1364,6 +1464,9 @@ p.comment-form-comment {
 /* =WP.com
 ----------------------------------------------- */
 
+.entry-content .twitter-tweet-rendered  {
+	max-width: 100% !important; /* Override the Twitter embed fixed width */
+}
 .video-player {
 	max-width: 100% !important;
 }
@@ -1380,8 +1483,11 @@ p.comment-form-comment {
 	display: block;
 }
 #wpl-mustlogin {
-width: 240px !important;
-margin-left: -60px !important;
+	width: 240px !important;
+	margin-left: -60px !important;
+}
+img.latex {
+	display: inline;
 }
 
 /* WP.com comment form */
@@ -1415,6 +1521,35 @@ margin-left: -60px !important;
 	width: 99% !important;
 }
 
+/* Infinite Scroll */
+.infinite-wrap {
+    border-top: 1px solid #ececec;
+    padding-top: 1.5em !important;
+}
+.infinite-scroll .hentry:last-of-type,
+.infinite-scroll .hentry.last-before-infinite {
+    margin-bottom: 0;
+}
+.infinite-scroll #content {
+    padding-bottom: 0.1em;
+}
+#infinite-handle span:before {
+   display: none;
+}
+#infinite-handle span {
+    background: #278dbc;
+    border-radius: 2px;
+    border: none;
+    color: #fff;
+    cursor: pointer;
+    font-size: 14px;
+    font-weight: 400;
+    padding: 6px 26px;
+    text-align: center;
+}
+#infinite-handle span:hover {
+    background: #7dcae7;
+}
 
 /* Remove margins and padding on outer containers for super-tiny screens */
 @media only screen and (min-device-width: 100px) and (max-device-width: 300px) {
@@ -1427,7 +1562,8 @@ margin-left: -60px !important;
 	}
 	#page,
 	.widget-area,
-	#main {
+	#main,
+	#branding {
 		width: 100%;
 		margin: 0;
 	}

diff --git a/plugins/jetpack/modules/mobile-push.php b/plugins/jetpack/modules/mobile-push.php
index 8981348..b073348 100644
--- a/plugins/jetpack/modules/mobile-push.php
+++ b/plugins/jetpack/modules/mobile-push.php
@@ -1,9 +1,10 @@
 <?php
 /**
  * Module Name: Mobile Push Notifications
- * Module Description: Receive notifications on your Apple device.
+ * Module Description: Receive notifications on your mobile device.
  * Sort Order: 100
  * First Introduced: 1.9
+ * Requires Connection: Yes
  */
 
 Jetpack_Sync::sync_comments( __FILE__, array(

diff --git a/plugins/jetpack/modules/module-extras.php b/plugins/jetpack/modules/module-extras.php
index 5013f7c..22fdb92 100644
--- a/plugins/jetpack/modules/module-extras.php
+++ b/plugins/jetpack/modules/module-extras.php
@@ -56,3 +56,5 @@ add_filter( 'jetpack_can_activate_infinite-scroll', 'jetpack_can_activate_infini
 require_once( dirname( __FILE__ ) . '/holiday-snow.php' );
 
 require_once( dirname( __FILE__ ) . '/featured-content/featured-content.php' );
+
+require_once( dirname( __FILE__ ) . '/social-links.php' );

diff --git a/plugins/jetpack/modules/module-info.php b/plugins/jetpack/modules/module-info.php
index 218a9e8..cb5257f 100644
--- a/plugins/jetpack/modules/module-info.php
+++ b/plugins/jetpack/modules/module-info.php
@@ -613,7 +613,7 @@ function jetpack_mobile_push_notifications_more_info() { ?>
 
 	<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>
+	<p><?php echo sprintf( __( 'If you use <a href="%1$s">WordPress for iOS</a> or <a href="%2$s">WordPress for Android</a>, you’ll now be able to opt in to receive push notifications of new comments, which makes it easier than ever to keep up with your readers and moderate comments on the go.', 'jetpack' ), 'http://ios.wordpress.org/', 'http://android.wordpress.org/' ); ?></p>
 
 <?php
 }
@@ -776,3 +776,49 @@ function jetpack_likes_more_link() {
 }
 add_action( 'jetpack_learn_more_button_likes', 'jetpack_likes_more_link' );
 // Likes: STOP
+
+// Debug: START
+function jetpack_debug_more_info() { ?>
+
+	<h4><?php esc_html_e( 'Debug' , 'jetpack' ); ?></h4>
+
+	<p><?php esc_html_e( "A debugging platform for the Jetpack plugin. Find out why Jetpack isn't working for you and submit a help request direct from your Dashboard.", 'jetpack' ); ?></p>
+	<?php if ( Jetpack::is_module_active( 'debug' ) ) : ?>
+		<p><a href="<?php echo admin_url( 'admin.php?page=jetpack-debugger' ); ?>"><?php esc_html_e( "Click here to start debugging.", 'jetpack' ); ?></a></p>
+
+	<?php endif; ?>
+<?php
+}
+
+function jetpack_debug_more_link() {
+	echo '<a class="button-secondary more-info-link" href="http://jetpack.me/support/debug/">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+
+add_action( 'jetpack_module_more_info_debug', 'jetpack_debug_more_info' );
+add_action( 'jetpack_module_more_info_connected_debug', 'jetpack_debug_more_info' );
+add_action( 'jetpack_learn_more_button_debug', 'jetpack_debug_more_link' );
+// Debug: STOP
+
+// Omnisearch: START
+function jetpack_omnisearch_more_info() { ?>
+
+	<h4><?php esc_html_e( 'Omnisearch' , 'jetpack' ); ?></h4>
+
+	<p><?php esc_html_e( 'Search once, get results from everything! Currently supports searching posts, pages, comments, and plugins.', 'jetpack' ); ?></p>
+
+	<p><?php esc_html_e( 'Omnisearch plays nice with other plugins by letting other providers offer results as well.', 'jetpack' ); ?></p>
+
+	<?php if( class_exists( 'Jetpack_Omnisearch' ) && current_user_can( 'edit_posts' ) ): ?>
+		<?php echo Jetpack_Omnisearch::get_omnisearch_form(); ?>
+	<?php endif; ?>
+
+<?php
+}
+
+function jetpack_omnisearch_more_link() {
+	echo '<a class="button-secondary more-info-link" href="http://jetpack.me/support/omnisearch/">' . __( 'Learn More', 'jetpack' ) . '</a>';
+}
+
+add_action( 'jetpack_module_more_info_omnisearch',  'jetpack_omnisearch_more_info' );
+add_action( 'jetpack_learn_more_button_omnisearch', 'jetpack_omnisearch_more_link' );
+// Omnisearch: STOP

diff --git a/plugins/jetpack/modules/notes.php b/plugins/jetpack/modules/notes.php
index e33f7ff..6022138 100644
--- a/plugins/jetpack/modules/notes.php
+++ b/plugins/jetpack/modules/notes.php
@@ -4,6 +4,7 @@
  * 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
+ * Requires Connection: Yes
  */
 
 if ( !defined( 'JETPACK_NOTES__CACHE_BUSTER' ) ) define( 'JETPACK_NOTES__CACHE_BUSTER', JETPACK__VERSION . '-' . gmdate( 'oW' ) );
@@ -28,7 +29,7 @@ class Jetpack_Notifications {
 	 * Singleton
 	 * @static
 	 */
-	function &init() {
+	public static function init() {
 		static $instance = array();
 
 		if ( !$instance ) {
@@ -42,24 +43,6 @@ class 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) {
@@ -104,9 +87,29 @@ class Jetpack_Notifications {
 	}
 
 	function action_init() {
+		//syncing must wait until after init so
+		//post types that support comments
+		$filt_post_types = array();
+		$all_post_types = get_post_types();
+		foreach ( $all_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' ),
+		) );
+
 		if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
 			return;
-		
+
 		if ( !has_filter( 'show_admin_bar', '__return_true' ) && !is_user_logged_in() )
 			return;
 
@@ -119,41 +122,24 @@ class Jetpack_Notifications {
 	}
 
 	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( 'wpcom-notes-admin-bar', $this->wpcom_static_url( '/wp-content/mu-plugins/notes/admin-bar-v2.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( 'mustache', 'registered' ) ) {
+			wp_register_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' );
-			}
+		if ( !wp_script_is( 'underscore', 'registered' ) ) {
+			wp_register_script( 'underscore', $this->wpcom_static_url( '/wp-includes/js/underscore.min.js' ), null, JETPACK_NOTES__CACHE_BUSTER );
 		}
-		else {
-			wp_enqueue_script( 'backbone', $this->wpcom_static_url( '/wp-content/js/backbone.js' ), array( 'jquery', 'underscore' ), JETPACK_NOTES__CACHE_BUSTER );
+		if ( !wp_script_is( 'backbone', 'registered' ) ) {
+			wp_register_script( 'backbone', $this->wpcom_static_url( '/wp-includes/js/backbone.min.js' ), array( '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 );
+		wp_register_script( 'wpcom-notes-common', $this->wpcom_static_url( '/wp-content/mu-plugins/notes/notes-common-v2.js' ), array( 'jquery', 'underscore', 'backbone', 'mustache', 'jquery.spin' ), JETPACK_NOTES__CACHE_BUSTER );
+		wp_enqueue_script( 'wpcom-notes-admin-bar', $this->wpcom_static_url( '/wp-content/mu-plugins/notes/admin-bar-v2.js' ), array( 'wpcom-notes-common' ), JETPACK_NOTES__CACHE_BUSTER );
 	}
 
 	function admin_bar_menu() {
@@ -166,10 +152,10 @@ class Jetpack_Notifications {
 		$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 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>',
+				'html'  => '<div id="wpnt-notes-panel" style="display:none" lang="'. esc_attr( get_locale() ) . '" dir="' . ( is_rtl() ? 'rtl' : 'ltr' ) . '"><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',

diff --git a/plugins/jetpack/modules/photon.php b/plugins/jetpack/modules/photon.php
index 06db868..23fa614 100644
--- a/plugins/jetpack/modules/photon.php
+++ b/plugins/jetpack/modules/photon.php
@@ -4,6 +4,7 @@
  * Module Description: Give your site a boost by loading images from the WordPress.com content delivery network.
  * Sort Order: 15
  * First Introduced: 2.0
+ * Requires Connection: Yes
  */
 
 Jetpack_Photon::instance();
\ No newline at end of file

diff --git a/plugins/jetpack/modules/post-by-email.php b/plugins/jetpack/modules/post-by-email.php
index e8cd887..bbc58ff 100644
--- a/plugins/jetpack/modules/post-by-email.php
+++ b/plugins/jetpack/modules/post-by-email.php
@@ -5,6 +5,7 @@
  * Module Description: Publish posts to your blog directly from your personal email account.
  * First Introduced: 2.0
  * Sort Order: 4
+ * Requires Connection: Yes
  */
 
 add_action( 'jetpack_modules_loaded', array( 'Jetpack_Post_By_Email', 'init' ) );
@@ -25,7 +26,7 @@ Jetpack::enable_module_configurable( __FILE__ );
 Jetpack::module_configuration_load( __FILE__, array( 'Jetpack_Post_By_Email', 'configuration_redirect' ) );
 
 class Jetpack_Post_By_Email {
-	function &init() {
+	public static function init() {
 		static $instance = NULL;
 
 		if ( !$instance ) {
@@ -44,7 +45,7 @@ class Jetpack_Post_By_Email {
 		$jetpack->sync->register( 'noop' );
 	}
 
-	function configuration_redirect() {
+	static function configuration_redirect() {
 		wp_safe_redirect( get_edit_profile_url( get_current_user_id() ) . '#post-by-email' );
 		exit;
 	}

diff --git a/plugins/jetpack/modules/post-by-email/post-by-email.js b/plugins/jetpack/modules/post-by-email/post-by-email.js
index 7ba14bd..0f548e7 100644
--- a/plugins/jetpack/modules/post-by-email/post-by-email.js
+++ b/plugins/jetpack/modules/post-by-email/post-by-email.js
@@ -56,7 +56,7 @@ jetpack_post_by_email = {
 
 		jQuery.post( ajaxurl, data, jetpack_post_by_email.handle_regenerated );
 	},
-	
+
 	handle_regenerated: function( response ) {
 		var regenerated = false;
 		var error;

diff --git a/plugins/jetpack/modules/publicize.php b/plugins/jetpack/modules/publicize.php
index c9a37e5..c1265cb 100644
--- a/plugins/jetpack/modules/publicize.php
+++ b/plugins/jetpack/modules/publicize.php
@@ -4,6 +4,7 @@
  * Module Description: Connect your site to popular social networks and automatically share new posts with your friends.
  * Sort Order: 1
  * First Introduced: 2.0
+ * Requires Connection: Yes
  */
 
 class Jetpack_Publicize {

diff --git a/plugins/jetpack/modules/publicize/assets/publicize.css b/plugins/jetpack/modules/publicize/assets/publicize.css
index 4065cb0..64569ae 100644
--- a/plugins/jetpack/modules/publicize/assets/publicize.css
+++ b/plugins/jetpack/modules/publicize/assets/publicize.css
@@ -3,7 +3,7 @@ div#publicize-services-block {
 	clear: both;
 	margin-bottom: 25px;
 	background-color: #fff;
-	width: 100%;
+	padding: 25px 25px 5px 20px;
 }
 
 /* Add the logos for the Publicize services */
@@ -19,7 +19,6 @@ span.pub-logos {
 
 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; }
 
@@ -172,4 +171,4 @@ table#option-fb-fanpage td.details span.category {
 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
index bb1f8d4..4ae37fb 100644
--- a/plugins/jetpack/modules/publicize/assets/publicize.js
+++ b/plugins/jetpack/modules/publicize/assets/publicize.js
@@ -72,7 +72,7 @@ jQuery( function( $ ) {
 						tb_remove();
 						window.location = 'options-general.php?page=sharing';
 					} );
-					
+
 				} );
 			}
 

diff --git a/plugins/jetpack/modules/publicize/assets/rtl/publicize-rtl.css b/plugins/jetpack/modules/publicize/assets/rtl/publicize-rtl.css
index b56ab2f..0acaa42 100644
--- a/plugins/jetpack/modules/publicize/assets/rtl/publicize-rtl.css
+++ b/plugins/jetpack/modules/publicize/assets/rtl/publicize-rtl.css
@@ -1,11 +1,11 @@
-/* This file was automatically generated on Dec 18 2012 19:58:18 */
+/* This file was automatically generated on Jun 24 2013 19:39:49 */
 
 div#publicize-services-block {
 	display: inline-block;
 	clear: both;
 	margin-bottom: 25px;
 	background-color: #fff;
-	width: 100%;
+	padding: 25px 20px 5px 25px;
 }
 
 /* Add the logos for the Publicize services */
@@ -21,7 +21,6 @@ span.pub-logos {
 
 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; }
 
@@ -174,4 +173,4 @@ table#option-fb-fanpage td.details span.category {
 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/publicize-jetpack.php b/plugins/jetpack/modules/publicize/publicize-jetpack.php
index 58e2564..454f999 100644
--- a/plugins/jetpack/modules/publicize/publicize-jetpack.php
+++ b/plugins/jetpack/modules/publicize/publicize-jetpack.php
@@ -11,15 +11,15 @@ class Publicize extends Publicize_Base {
 		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_filter( 'publicize_checkbox_default', array( $this, 'publicize_checkbox_default' ), 10, 4 );
 
 		add_action( 'transition_post_status', array( $this, 'save_publicized' ), 10, 3 );
 	}
@@ -219,7 +219,7 @@ class Publicize extends Publicize_Base {
 		if ( 'on' == $_REQUEST['global'] ) {
 			$id = $_REQUEST['connection'];
 
-			if ( !current_user_can( Publicize::GLOBAL_CAP ) )
+			if ( !current_user_can( $this->GLOBAL_CAP ) )
 				return;
 
 			Jetpack::load_xml_rpc_client();
@@ -261,6 +261,17 @@ class Publicize extends Publicize_Base {
 		), menu_page_url( 'sharing', false ) );
 	}
 
+	function refresh_url( $service_name ) {
+		return add_query_arg( array(
+			'action'   => 'request',
+			'service'  =>  $service_name,
+			'kr_nonce' => wp_create_nonce( 'keyring-request' ),
+			'refresh'  => 1,
+			'for'      => 'publicize',
+			'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',
@@ -280,7 +291,6 @@ class Publicize extends Publicize_Base {
 				'twitter'  => array(),
 				'linkedin' => array(),
 				'tumblr'   => array(),
-				'yahoo'    => array(),
 		);
 
 		if ( 'all' == $filter ) {
@@ -327,8 +337,8 @@ class Publicize extends Publicize_Base {
 		// Nonce check
 		check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
 
-		$me = $options_to_show[0];
-		$pages = $options_to_show[1]['data'];
+		$me    = ( ! empty( $options_to_show[0] )         ? $options_to_show[0]         : false );
+		$pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false );
 
 		$profile_checked = true;
 		$page_selected = false;
@@ -389,7 +399,6 @@ class Publicize extends Publicize_Base {
 					<tbody>
 
 						<?php foreach ( $pages as $i => $page ) : ?>
-							<?php if ( ! isset( $page['perms'] ) ) { continue; } ?>
 							<?php if ( ! ( $i % 2 ) ) : ?>
 								<tr>
 							<?php endif; ?>
@@ -559,11 +568,9 @@ class Publicize extends Publicize_Base {
 
 	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
@@ -571,8 +578,74 @@ class Publicize extends Publicize_Base {
 		$this->globalization();
 	}
 
-	// stub
+	function is_expired( $expires  = false ) {
+		$hour_in_seconds = 3600;
+		if ( !$expires )
+			return false; // No expires value, assume it's a permanent token
+		if ( '0000-00-00 00:00:00' == $expires )
+			return false; // Doesn't expire
+		if ( ( time() + $hour_in_seconds ) > strtotime( $expires ) )
+			return true; // Token's expiry time has passed, or will pass before $window
+		return false;
+	}
+
 	function refresh_tokens_message() {
+		global $post;
+		$post_id = $post ? $post->ID : 0;
+
+		$services = $this->get_services( 'all' );
+
+		// Same core nonce works for all services
+		$keyring_nonce = wp_create_nonce( 'keyring-request' );
+		$expired_tokens = false;
+
+		if ( is_array( $services ) && count( $services ) ) {
+			foreach ( $services as $name => $service ) {
+				if ( $connections = $this->get_connections( $name ) ) {
+			
+					foreach ( $connections as $connection ) {
+
+						$cmeta = $this->get_connection_meta( $connection );
+
+						// If the token for this connection is expired, or expires soon, then warn
+						if ( !$this->is_expired( $cmeta['expires'] ) ) {
+							continue;
+						}
+
+						if ( !$expired_tokens ) {
+							?>
+							<div class="error below-h2 publicize-token-refresh-message">
+							<p><?php echo esc_html( __( 'Before you hit Publish, please refresh your connection to make sure we can Publicize your post:' , 'jetpack') ); ?></p>
+							<?php
+							$expired_tokens = true;
+						}
+						// No need to request for a specific token id, since the token store detects duplication and updates a single token per service
+						$nonce = wp_create_nonce( "keyring-request-" . $name );
+						$url = $this->refresh_url( $name );
+						?>
+						<p style="text-align: center;" id="publicize-token-refresh-<?php echo esc_attr( $name ); ?>" class="publicize-token-refresh-button">
+							<a href="<?php echo esc_url( $url ); ?>" class="button" target="_refresh_<?php echo esc_attr( $name ); ?>">
+								<?php printf( __( 'Refresh connection with %s' , 'jetpack'), Publicize::get_service_label( $name ) ); ?>
+							</a>
+						</p><?php
+					}
+				}
+			}
+		}
 
+		if ( $expired_tokens ) {
+			echo '</div>';
+		}
+	}
+	
+	/** 
+	* Already-published posts should not be Publicized by default. This filter sets checked to 
+	* false if a post has already been published. 
+	*/ 
+	function publicize_checkbox_default( $checked, $post_id, $name, $connection ) { 
+		if ( 'publish' == get_post_status( $post_id ) ) 
+			return false; 
+
+		return $checked; 
 	}
 }

diff --git a/plugins/jetpack/modules/publicize/publicize.php b/plugins/jetpack/modules/publicize/publicize.php
index 16d4541..0070e5e 100644
--- a/plugins/jetpack/modules/publicize/publicize.php
+++ b/plugins/jetpack/modules/publicize/publicize.php
@@ -39,7 +39,7 @@ abstract class Publicize_Base {
 	 * 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';
+	var $GLOBAL_CAP = 'edit_others_posts';
 
 	/**
 	* Sets up the basics of Publicize
@@ -61,6 +61,7 @@ abstract class Publicize_Base {
 			'url',
 		) );
 
+		$this->GLOBAL_CAP = apply_filters( 'jetpack_publicize_global_connections_cap', $this->GLOBAL_CAP );
 
 		// 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
@@ -100,8 +101,6 @@ abstract class Publicize_Base {
 			 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;
@@ -109,11 +108,15 @@ abstract class Publicize_Base {
 
 			$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'] ) ) {
+			if ( isset( $profile_url_query_args['key'] ) ) {
+				$id = $profile_url_query_args['key'];
+			} elseif ( isset( $profile_url_query_args['id'] ) ) {
+				$id = $profile_url_query_args['id'];
+			} else {
 				return false;
 			}
 
-			return esc_url_raw( add_query_arg( 'id', urlencode( $profile_url_query_args['key'] ), 'http://www.linkedin.com/profile/view' ) );
+			return esc_url_raw( add_query_arg( 'id', urlencode( $id ), 'http://www.linkedin.com/profile/view' ) );
 		} else {
 			return false; // no fallback. we just won't link it
 		}
@@ -139,11 +142,8 @@ abstract class Publicize_Base {
 		}
 	}
 
-	function get_service_label( $service_name ) {
+	public static function get_service_label( $service_name ) {
 		switch ( $service_name ) {
-			case 'yahoo':
-				return 'Yahoo!';
-				break;
 			case 'linkedin':
 				return 'LinkedIn';
 				break;
@@ -211,8 +211,7 @@ abstract class Publicize_Base {
 		$cron_user = null;
 		$submit_post = true;
 
-		// don't do anything if its not actually a post
-		if ( 'post' !== $post->post_type )
+		if ( ! $this->post_type_is_publicizeable( $post->post_type ) )
 			return;
 
 		// Don't Publicize during certain contexts:
@@ -285,7 +284,13 @@ abstract class Publicize_Base {
 		 */
 		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 ) ) {
+				$connection_data = '';
+				if ( method_exists( $connection, 'get_meta' ) )
+					$connection_data = $connection->get_meta( 'connection_data' );
+				elseif ( ! empty( $connection['connection_data'] ) )
+					$connection_data = $connection['connection_data'];
+
+				if ( false == apply_filters( 'wpas_submit_post?', $submit_post, $post_id, $service_name, $connection_data ) ) {
 					delete_post_meta( $post_id, $this->PENDING );
 					continue;
 				}
@@ -325,4 +330,20 @@ abstract class Publicize_Base {
 
 		// Next up will be ::publicize_post()
 	}
+
+	/**
+	 * Is a given post type Publicize-able?
+	 *
+	 * Not every CPT lends itself to Publicize-ation.  Allow CPTs to register by adding their CPT via
+	 * the publicize_post_types array filter.
+	 *
+	 * @param string $post_type The post type to check.
+	 * $return bool True if the post type can be Publicized.
+	 */
+	function post_type_is_publicizeable( $post_type ) {
+		if ( 'post' == $post_type )
+			return true;
+
+		return post_type_supports( $post_type, 'publicize' );
+	}
 }

diff --git a/plugins/jetpack/modules/publicize/ui.php b/plugins/jetpack/modules/publicize/ui.php
index d9d2b37..06d0d43 100644
--- a/plugins/jetpack/modules/publicize/ui.php
+++ b/plugins/jetpack/modules/publicize/ui.php
@@ -71,7 +71,7 @@ class Publicize_UI {
 		add_thickbox();
 	}
 
-	function connected_notice( $service_name ) { ?>
+	public static 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
@@ -91,14 +91,14 @@ class Publicize_UI {
 	  			<?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">
@@ -152,7 +152,7 @@ class Publicize_UI {
 											<?php if ( 0 == $cmeta['connection_data']['user_id'] ) : ?>
 												<small>(<?php esc_html_e( 'Shared', 'jetpack' ); ?>)</small>
 
-												<?php if ( current_user_can( Publicize::GLOBAL_CAP ) ) : ?>
+												<?php if ( current_user_can( $this->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; ?>
 
@@ -170,6 +170,18 @@ class Publicize_UI {
 			  			</div>
 			  		</div>
 				<?php endforeach; ?>
+				<script>
+  				(function($){
+  					$('.pub-disconnect-button').on('click', function(e){
+							if ( confirm( '<?php echo esc_js( __( 'Are you sure you want to stop Publicizing posts to this connection?', 'jetpack' ) ); ?>' ) ) {
+								return true;
+							} else {
+  							e.preventDefault();
+  							return false;
+  						}
+  					})
+  				})(jQuery);
+  				</script>
 	  		</div>
 
 			<?php wp_nonce_field( "wpas_posts_{$_blog_id}", "_wpas_posts_{$_blog_id}_nonce" ); ?>
@@ -178,8 +190,9 @@ class Publicize_UI {
 
 	}
 
-	function global_checkbox( $service_name, $id ) {
-		if ( current_user_can( Publicize::GLOBAL_CAP ) ) : ?>
+	public static function global_checkbox( $service_name, $id ) {
+		global $publicize;
+		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>
@@ -195,7 +208,7 @@ class Publicize_UI {
 		</div><?php
 	}
 
-	function options_page_other( $service_name ) {
+	public static function options_page_other( $service_name ) {
 		// Nonce check
 		check_admin_referer( "options_page_{$service_name}_" . $_REQUEST['connection'] );
 		?>
@@ -363,7 +376,7 @@ jQuery( function($) {
 	function post_page_metabox() {
 		global $post;
 
-		if ( 'post' != $post->post_type )
+		if ( ! $this->publicize->post_type_is_publicizeable( $post->post_type ) )
 			return;
 
 		$user_id = empty( $post->post_author ) ? $GLOBALS['user_ID'] : $post->post_author;
@@ -400,7 +413,13 @@ jQuery( function($) {
 
 					foreach ( $services as $name => $connections ) {
 						foreach ( $connections as $connection ) {
-							if ( !$continue = apply_filters( 'wpas_submit_post?', true, $post->ID, $name ) )
+							$connection_data = '';
+							if ( method_exists( $connection, 'get_meta' ) )
+								$connection_data = $connection->get_meta( 'connection_data' );
+							elseif ( ! empty( $connection['connection_data'] ) )
+								$connection_data = $connection['connection_data'];
+
+							if ( !$continue = apply_filters( 'wpas_submit_post?', true, $post->ID, $name, $connection_data ) )
 								continue;
 
 							if ( !empty( $connection->unique_id ) )
@@ -436,7 +455,7 @@ jQuery( function($) {
 							// 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 ) ) ) {
+							if ( !$done && ( 0 == $cmeta['connection_data']['user_id'] && !current_user_can( $this->publicize->GLOBAL_CAP ) ) ) {
 								$disabled = ' disabled="disabled"';
 								$hidden_checkbox = true;
 							}

diff --git a/plugins/jetpack/modules/sharedaddy.php b/plugins/jetpack/modules/sharedaddy.php
index f6f4ad6..924176f 100644
--- a/plugins/jetpack/modules/sharedaddy.php
+++ b/plugins/jetpack/modules/sharedaddy.php
@@ -1,10 +1,11 @@
-<?php 
+<?php
 /**
  * Module Name: Sharing
  * Module Description: The most super duper sharing tool on the interwebs. Share content with Facebook, Twitter, and many more.
  * Sort Order: 5
  * First Introduced: 1.1
  * Major Changes In: 1.2
+ * Requires Connection: No
  */
 
 if ( !function_exists( 'sharing_init' ) )

diff --git a/plugins/jetpack/modules/sharedaddy/admin-sharing.css b/plugins/jetpack/modules/sharedaddy/admin-sharing.css
index aea3079..5123453 100644
--- a/plugins/jetpack/modules/sharedaddy/admin-sharing.css
+++ b/plugins/jetpack/modules/sharedaddy/admin-sharing.css
@@ -6,7 +6,7 @@
 	-webkit-border-radius: 6px;
 	margin-top:15px;
 	min-width: 700px;
-	width: 100%;	
+	width: 100%;
 	float: left;
 	margin-bottom: 25px;
 }
@@ -34,7 +34,7 @@
 }
 
 .description{
-	width: 180px;	
+	width: 180px;
 	vertical-align: top;
 }
 
@@ -90,7 +90,9 @@
 .services ul li#linkedin, #available-services .preview-linkedin div.option-smart-off{background: #FFF url(images/linkedin.png) no-repeat 4px 5px;}
 .services ul li#tumblr,#available-services .preview-tumblr{background: #FFF url(images/tumblr.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.png) no-repeat 4px 5px; padding-right: 10px;}
-.services ul li#pinterest,#available-services .preview-pinterest{background: #FFF url(images/pinterest.png) no-repeat 4px 5px; padding-right: 10px;}
+.services ul li#pinterest,#available-services .preview-pinterest{background: #FFF url(images/pinterest.png) no-repeat 5px 6px; padding-right: 10px;}
+.services ul li#pocket,#available-services .preview-pocket{background: #FFF url(images/pocket.png) no-repeat 4px 5px; padding-right: 10px;}
+.services ul li#kindle,#available-services .preview-kindle{background: #FFF url(images/kindle.png) no-repeat 4px 5px; padding-right: 10px;}
 .services ul li.share-custom, #available-services .preview-custom{background: #FFF url(images/custom.png) no-repeat 4px 5px; no-repeat 4px 5px; padding-right: 10px;}
 
 
@@ -181,6 +183,20 @@
 	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;
+}
+
+.preview-pocket .option-smart-on {
+	background: #FFF url(images/smart-pocket.png) no-repeat top left;
+	background-size: 60px 20px;
+	width: 60px;
+	height: 20px;
+}
+
 .services .preview li.share-custom {
 	border-radius: 6px;
 	-moz-border-radius: 6px;
@@ -222,7 +238,7 @@
 #live-preview h2{
 	font-size:20px;
 	font-weight: normal !important;
-	color: #e3e3e3;		
+	color: #e3e3e3;
 }
 
 #live-preview{
@@ -230,17 +246,17 @@
 	border-bottom-left-radius:6px 6px;
 	border-bottom-right-radius:6px 6px;
 	-moz-border-radius-bottomleft: 6px;
-	-moz-border-radius-bottomright: 6px;	
+	-moz-border-radius-bottomright: 6px;
 }
 
 .clearing{
 	clear: both;
 }
-	
+
 	.options .options-left{
 		float: left;
 	}
-	
+
 	.input label{
 		font-size: 11px;
 		line-height: 16px;
@@ -253,20 +269,20 @@
 		border-top: 1px #e3e3e3 solid;
 		margin-top:4px;
 	}
-	
+
 	.utility{
 		float: right;
 		padding-top:10px;
 		padding-right: 10px;
 		font-size: 10px;
 	}
-	
+
 	.advanced input[type=submit]{
 		float: left;
 		margin-top:10px;
 		margin-right: 10px;
 	}
-	
+
 .services li.dropzone {
 	border: 1px dashed #999;
 	background: #e3e3e3;
@@ -297,7 +313,7 @@
 #hidden-drop-target p {
 	font-size: 10px;
 	margin: 0 0 10px 0;
-	
+
 }
 
 .sharing-hidden .inner {
@@ -370,6 +386,8 @@
 	.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#pocket,#available-services .preview-pocket{background: #FFF url(images/pocket@2x.png) no-repeat 4px 5px; padding-right: 10px;}
+	.services ul li#kindle,#available-services .preview-kindle{background: #FFF url(images/kindle@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,
@@ -385,6 +403,8 @@
 	.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#pocket,#available-services .preview-pocket,
+	.services ul li#kindle,#available-services .preview-kindle,
 	.services ul li.share-custom, #available-services .preview-custom{
 		background-size: 16px 16px;
 	}
@@ -425,4 +445,8 @@
 		background-image: url(images/smart-pinterest@2x.png);
 	}
 
+	.preview-pocket .option-smart-on {
+		background-image: url(images/smart-pocket@2x.png);
+	}
+
 }
\ No newline at end of file

diff --git a/plugins/jetpack/modules/sharedaddy/admin-sharing.js b/plugins/jetpack/modules/sharedaddy/admin-sharing.js
index a11d469..b396ef6 100644
--- a/plugins/jetpack/modules/sharedaddy/admin-sharing.js
+++ b/plugins/jetpack/modules/sharedaddy/admin-sharing.js
@@ -5,7 +5,7 @@
 				if ( $( this ).data( 'hasappeared' ) !== true ) {
 					var item     = $( '.sharing-hidden .inner' );
 					var original = $( this ).parents( 'li' );
-					
+
 					// Create a timer to make the area appear if the mouse hovers for a period
 					var timer = setTimeout( function() {
 						$( item ).css( {
@@ -14,47 +14,47 @@
 						} ).slideDown( 200, function() {
 							// Mark the item as have being appeared by the hover
 							$( original ).data( 'hasappeared', true ).data( 'hasoriginal', true ).data( 'hasitem', false );
-							
+
 							// Remove all special handlers
 							$( item ).mouseleave( handler_item_leave ).mouseenter( handler_item_enter );
 							$( original ).mouseleave( handler_original_leave ).mouseenter( handler_original_enter );
-							
+
 							// Add a special handler to quickly close the item
 							$( original ).click( close_it );
 						} );
-						
+
 						// 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() {
 							$( original ).data( 'hasitem', false );
-							
+
 							if ( $( original ).data( 'hasoriginal' ) === false ) {
 								var timer = setTimeout( close_it, 800 );
 								$( original ).data( 'timer2', timer );
 							}
 						};
-	
+
 						var handler_item_enter = function() {
 							$( original ).data( 'hasitem', true );
 							clearTimeout( $( original ).data( 'timer2' ) );
-						} 
-						
+						}
+
 						var handler_original_leave = function() {
 							$( original ).data( 'hasoriginal', false );
-							
+
 							if ( $( original ).data( 'hasitem' ) === false ) {
 								var timer = setTimeout( close_it, 800 );
 								$( original ).data( 'timer2', timer );
 							}
 						};
-						
+
 						var handler_original_enter = function() {
 							$( original ).data( 'hasoriginal', true );
 							clearTimeout( $( original ).data( 'timer2' ) );
 						};
-		
+
 						var close_it = function() {
 							item.slideUp( 200 );
-	
+
 							// Clear all hooks
 							$( original ).unbind( 'mouseleave', handler_original_leave ).unbind( 'mouseenter', handler_original_enter );
 							$( item ).unbind( 'mouseleave', handler_item_leave ).unbind( 'mouseenter', handler_item_leave );
@@ -63,7 +63,7 @@
 							return false;
 						};
 					}, 200 );
-					
+
 					// Remember the timer so we can detect it on the mouseout
 					$( this ).data( 'timer', timer );
 				}
@@ -73,14 +73,14 @@
 				$( this ).data( 'timer', false );
 			} );
 		}
-		
+
 		function update_preview() {
 			var item;
 			var button_style = $( '#button_style' ).val();
-			
+
 			// Clear the live preview
 			$( '#live-preview ul.preview li' ).remove();
-			
+
 			// Add label
 			if ( $( '#save-enabled-shares input[name=visible]' ).val() != '' || $( '#save-enabled-shares input[name=hidden]' ).val() != '' )
 				$( '#live-preview ul.preview' ).append( $( '#live-preview ul.archive .sharing-label' ).clone() );
@@ -92,14 +92,14 @@
 					$( '#live-preview ul.preview' ).append( $( '#live-preview ul.archive li.preview-' + service ).clone() );
 				}
 			} );
-			
+
 			// Add any hidden items
 			if ( $( '#save-enabled-shares input[name=hidden]' ).val() != '' ) {
 				// Add share button
 				$( '#live-preview ul.preview' ).append( $( '#live-preview ul.archive .share-more' ).parent().clone() );
-				
+
 				$( '.sharing-hidden ul li' ).remove();
-				
+
 				// Add hidden items into the inner panel
 				$( 'ul.services-hidden li' ).each( function( pos, item ) {
 					if ( $( this ).hasClass( 'service' ) ) {
@@ -107,10 +107,10 @@
 						$( '.sharing-hidden .inner ul' ).append( $( '#live-preview ul.archive .preview-' + service ).clone() );
 					}
 				} );
-				
+
 				enable_share_button();
 			}
-			
+
 			$( '#live-preview div.sharedaddy' ).removeClass( 'sd-social-icon' );
 			$( '#live-preview li.advanced' ).removeClass( 'no-icon' );
 
@@ -126,8 +126,8 @@
 				} );
 			} else if ( 'text' == button_style ) {
 				$( '#live-preview li.advanced' ).addClass( 'no-icon' );
-			} 
-			
+			}
+
 		}
 
 		function sharing_option_changed() {
@@ -135,25 +135,25 @@
 
 			// Loading icon
 			$( this ).parents( 'li:first' ).css( 'backgroundImage', 'url("' + sharing_loading_icon + '")' );
-			
+
 			// Save
 			$( this ).parents( 'form' ).ajaxSubmit( function( response ) {
 				if ( response.indexOf( '<!---' ) >= 0 ) {
 					var button = response.substring( 0, response.indexOf( '<!--->' ) );
 					var preview = response.substring( response.indexOf( '<!--->' ) + 6 );
-				
+
 					if ( $( item ).is( ':submit' ) === true ) {
 						// Update the DOM using a bit of cut/paste technology
-		
+
 						$( item ).parents( 'li:first' ).replaceWith( button );
 					}
 
 					$( '#live-preview ul.archive li.preview-' + $( item ).parents( 'form' ).find( 'input[name=service]' ).val() ).replaceWith( preview );
 				}
-				
+
 				// Update preview
 				update_preview();
-				
+
 				// Restore the icon
 				$( item ).parents( 'li:first' ).removeAttr( 'style' );
 			} );
@@ -163,9 +163,17 @@
 			return true;
 		}
 
+		function showExtraOptions( service ) {
+			jQuery( '.' + service + '-extra-options' ).css( { backgroundColor: '#ffffcc' } ).fadeIn();
+		}
+
+		function hideExtraOptions( service ) {
+			jQuery( '.' + service + '-extra-options' ).fadeOut( 'slow' );
+		}
+
 		function save_services() {
 			$( '#enabled-services h3 img' ).show();
-			
+
 			// Toggle various dividers/help texts
 			if ( $( '#enabled-services ul.services-enabled li.service' ).length > 0 ) {
 				$( '#drag-instructions' ).hide();
@@ -173,21 +181,28 @@
 			else {
 				$( '#drag-instructions' ).show();
 			}
-			
+
 			if ( $( '#enabled-services li.service' ).length > 0 ) {
 				$( '#live-preview .services h2' ).hide();
 			}
 			else {
 				$( '#live-preview .services h2' ).show();
 			}
-			
+
 			// Gather the modules
 			var visible = [], hidden = [];
-			
+
 			$( 'ul.services-enabled li' ).each( function() {
 				if ( $( this ).hasClass( 'service' ) ) {
 					// Ready for saving
 					visible[visible.length] = $( this ).attr( 'id' );
+					showExtraOptions( $( this ).attr( 'id' ) );
+				}
+			} );
+
+			$( 'ul.services-available li' ).each( function() {
+				if ( $( this ).hasClass( 'service' ) ) {
+					hideExtraOptions( $( this ).attr( 'id' ) );
 				}
 			} );
 
@@ -195,15 +210,16 @@
 				if ( $( this ).hasClass( 'service' ) ) {
 					// Ready for saving
 					hidden[hidden.length] = $( this ).attr( 'id' );
+					showExtraOptions( $( this ).attr( 'id' ) );
 				}
 			} );
 
 			// Set the hidden element values
 			$( '#save-enabled-shares input[name=visible]' ).val( visible.join( ',' ) );
 			$( '#save-enabled-shares input[name=hidden]' ).val( hidden.join( ',' ) );
-			
+
 			update_preview();
-			
+
 			// Save it
 			$( '#save-enabled-shares' ).ajaxSubmit( function() {
 				$( '#enabled-services h3 img' ).hide();
@@ -234,7 +250,7 @@
 			},
 			helper: function( event, ui ) {
 				ui.find( '.advanced-form' ).hide();
-				
+
 				return ui.clone();
 			},
 			start: function( event, ui ) {
@@ -262,13 +278,13 @@
 				$( '.advanced-form' ).hide();
 			}
 		} );
-				
+
 		// Live preview 'hidden' button
 		$( '.preview-hidden a' ).click( function() {
 			$( this ).parent().find( '.preview' ).toggle();
 			return false;
 		} );
-		
+
 		// Add service
 		$( '#new-service form' ).ajaxForm( {
 				beforeSubmit: function() {
@@ -278,7 +294,7 @@
 				},
 				success: function( response ) {
 					$( '#new-service-form img' ).hide();
-					
+
 					if ( response == '1' ) {
 						$( '#new-service-form .inerror' ).removeClass( 'inerror' ).addClass( 'error' );
 						$( '#new-service-form .error' ).show();
@@ -290,38 +306,38 @@
 				}
 			}
 		);
-		
+
 		function init_handlers() {
 			$( '#services-config a.remove' ).unbind( 'click' ).click( function() {
 				var form = $( this ).parent().next();
-				
+
 				// Loading icon
 				$( this ).parents( 'li:first' ).css( 'backgroundImage', 'url("' + sharing_loading_icon + '")' );
-				
+
 				// Save
 				form.ajaxSubmit( function( response ) {
 					// Remove the item
 					form.parents( 'li:first' ).fadeOut( function() {
 						$( this ).remove();
-						
+
 						// Update preview
 						update_preview();
 					} );
 				} );
-				
+
 				return false;
 			} );
 		}
-		
+
 		$( '#button_style' ).change( function() {
 			update_preview();
 			return true;
 		} ).change();
-		
+
 		$( 'input[name=sharing_label]' ).blur( function() {
 			$('#live-preview h3.sd-title').html( $( '<div/>' ).text( $( this ).val() ).html() );
 		} );
-		
+
 		init_handlers();
 		enable_share_button();
 	} );

diff --git a/plugins/jetpack/modules/sharedaddy/images/facebook.png b/plugins/jetpack/modules/sharedaddy/images/facebook.png
index 8850a80..91d3702 100644
Binary files a/plugins/jetpack/modules/sharedaddy/images/facebook.png and b/plugins/jetpack/modules/sharedaddy/images/facebook.png differ

diff --git a/plugins/jetpack/modules/sharedaddy/images/facebook@2x.png b/plugins/jetpack/modules/sharedaddy/images/facebook@2x.png
index a88a52f..10b3680 100644
Binary files a/plugins/jetpack/modules/sharedaddy/images/facebook@2x.png and b/plugins/jetpack/modules/sharedaddy/images/facebook@2x.png differ

diff --git a/plugins/jetpack/modules/sharedaddy/images/googleplus1.png b/plugins/jetpack/modules/sharedaddy/images/googleplus1.png
index 5f0a05e..ee687af 100644
Binary files a/plugins/jetpack/modules/sharedaddy/images/googleplus1.png and b/plugins/jetpack/modules/sharedaddy/images/googleplus1.png differ

diff --git a/plugins/jetpack/modules/sharedaddy/images/googleplus1@2x.png b/plugins/jetpack/modules/sharedaddy/images/googleplus1@2x.png
index 2605439..60dd1c0 100644
Binary files a/plugins/jetpack/modules/sharedaddy/images/googleplus1@2x.png and b/plugins/jetpack/modules/sharedaddy/images/googleplus1@2x.png differ

diff --git a/plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.png b/plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.png
index a5c7194..10b3680 100644
Binary files a/plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.png and b/plugins/jetpack/modules/sharedaddy/images/icon-facebook-2x.png differ

diff --git a/plugins/jetpack/modules/sharedaddy/images/icon-facebook.png b/plugins/jetpack/modules/sharedaddy/images/icon-facebook.png
index de6a8a1..91d3702 100644
Binary files a/plugins/jetpack/modules/sharedaddy/images/icon-facebook.png and b/plugins/jetpack/modules/sharedaddy/images/icon-facebook.png differ

diff --git a/plugins/jetpack/modules/sharedaddy/recaptchalib.php b/plugins/jetpack/modules/sharedaddy/recaptchalib.php
index a971677..205a4a2 100644
--- a/plugins/jetpack/modules/sharedaddy/recaptchalib.php
+++ b/plugins/jetpack/modules/sharedaddy/recaptchalib.php
@@ -108,7 +108,7 @@ function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
 	if ($pubkey == null || $pubkey == '') {
 		die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
 	}
-	
+
 	if ($use_ssl) {
                 $server = RECAPTCHA_API_SECURE_SERVER;
         } else {
@@ -159,8 +159,8 @@ function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $ex
 		die ("For security reasons, you must pass the remote ip to reCAPTCHA");
 	}
 
-	
-	
+
+
         //discard spam submissions
         if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
                 $recaptcha_response = new ReCaptchaResponse();
@@ -215,7 +215,7 @@ function _recaptcha_aes_encrypt($val,$ky) {
 	if (! function_exists ("mcrypt_encrypt")) {
 		die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
 	}
-	$mode=MCRYPT_MODE_CBC;   
+	$mode=MCRYPT_MODE_CBC;
 	$enc=MCRYPT_RIJNDAEL_128;
 	$val=_recaptcha_aes_pad($val);
 	return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
@@ -232,11 +232,11 @@ function recaptcha_mailhide_url($pubkey, $privkey, $email) {
 		die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
 		     "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
 	}
-	
+
 
 	$ky = pack('H*', $privkey);
 	$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
-	
+
 	return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
 }
 
@@ -267,7 +267,7 @@ function _recaptcha_mailhide_email_parts ($email) {
 function recaptcha_mailhide_html($pubkey, $privkey, $email) {
 	$emailparts = _recaptcha_mailhide_email_parts ($email);
 	$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
-	
+
 	return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
 		"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
 

diff --git a/plugins/jetpack/modules/sharedaddy/sharedaddy.php b/plugins/jetpack/modules/sharedaddy/sharedaddy.php
index ab8085c..cefecf7 100644
--- a/plugins/jetpack/modules/sharedaddy/sharedaddy.php
+++ b/plugins/jetpack/modules/sharedaddy/sharedaddy.php
@@ -59,14 +59,14 @@ function sharing_meta_box_save( $post_id ) {
 			}
 		}
 	}
-  	
+
   	return $post_id;
 }
 
 function sharing_meta_box_protected( $protected, $meta_key, $meta_type ) {
 	if ( 'sharing_disabled' == $meta_key )
 		$protected = true;
-		
+
 	return $protected;
 }
 
@@ -83,7 +83,7 @@ function sharing_add_plugin_settings($links, $file) {
 		$links[] = '<a href="options-general.php?page=sharing.php">' . __( 'Settings', 'jetpack' ) . '</a>';
 		$links[] = '<a href="http://support.wordpress.com/sharing/">' . __( 'Support', 'jetpack' ) . '</a>';
 	}
-	
+
 	return $links;
 }
 

diff --git a/plugins/jetpack/modules/sharedaddy/sharing-service.php b/plugins/jetpack/modules/sharedaddy/sharing-service.php
index c8efee3..8b10b6e 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing-service.php
+++ b/plugins/jetpack/modules/sharedaddy/sharing-service.php
@@ -54,6 +54,7 @@ class Sharing_Service {
 			'google-plus-1' => 'Share_GooglePlus1',
 			'tumblr'        => 'Share_Tumblr',
 			'pinterest'     => 'Share_Pinterest',
+			'pocket'        => 'Share_Pocket',
 		);
 
 		// Add any custom services in
@@ -416,7 +417,9 @@ function sharing_add_footer() {
 			endif;
 		endif;
 
-		wp_print_scripts( 'sharing-js' );
+		wp_enqueue_script( 'sharing-js' );
+		$recaptcha__options = array( 'lang' => get_base_recaptcha_lang_code() );
+		wp_localize_script('sharing-js', 'recaptcha_options', $recaptcha__options);
 	}
 
 	$sharer = new Sharing_Service();
@@ -452,9 +455,9 @@ function sharing_process_requests() {
 		}
 	}
 }
-add_action( 'template_redirect', 'sharing_process_requests' );
+add_action( 'template_redirect', 'sharing_process_requests', 9 );
 
-function sharing_display( $text = '' ) {
+function sharing_display( $text = '', $echo = false ) {
 	global $post, $wp_current_filter;
 
 	if ( is_preview() ) {
@@ -518,7 +521,7 @@ function sharing_display( $text = '' ) {
 	$sharing_content = '';
 
 	if ( $show ) {
-		$enabled = $sharer->get_blog_services();
+		$enabled = apply_filters( 'sharing_enabled', $sharer->get_blog_services() );
 
 		if ( count( $enabled['all'] ) > 0 ) {
 			global $post;
@@ -584,7 +587,7 @@ function sharing_display( $text = '' ) {
 				$sharing_content .= '<li class="share-end"></li></ul></div></div>';
 			}
 
-			$sharing_content .= '<div class="sharing-clear"></div></div></div></div>';
+			$sharing_content .= '</div></div></div>';
 
 			// Register our JS
 			wp_register_script( 'sharing-js', plugin_dir_url( __FILE__ ).'sharing.js', array( 'jquery' ), '20121205' );
@@ -592,8 +595,35 @@ function sharing_display( $text = '' ) {
 		}
 	}
 
-	return $text.$sharing_content;
+	if ( $echo )
+		echo $text.$sharing_content;
+	else
+		return $text.$sharing_content;
 }
 
 add_filter( 'the_content', 'sharing_display', 19 );
 add_filter( 'the_excerpt', 'sharing_display', 19 );
+function get_base_recaptcha_lang_code() {
+
+	$base_recaptcha_lang_code_mapping = array(
+		'en'    => 'en',
+		'nl'    => 'nl',
+		'fr'    => 'fr',
+		'fr-be' => 'fr',
+		'fr-ca' => 'fr',
+		'fr-ch' => 'fr',
+		'de'    => 'de',
+		'pt'    => 'pt',
+		'pt-br' => 'pt',
+		'ru'    => 'ru',
+		'es'    => 'es',
+		'tr'    => 'tr'
+	);
+
+	$blog_lang_code = function_exists( 'get_blog_lang_code' ) ? get_blog_lang_code() : get_bloginfo( 'language' ); 
+	if( isset( $base_recaptcha_lang_code_mapping[ $blog_lang_code ] ) )
+		return $base_recaptcha_lang_code_mapping[ $blog_lang_code ];
+
+	// if no base mapping is found return default 'en'
+	return 'en';
+}

diff --git a/plugins/jetpack/modules/sharedaddy/sharing-sources.php b/plugins/jetpack/modules/sharedaddy/sharing-sources.php
index 256513c..5316474 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing-sources.php
+++ b/plugins/jetpack/modules/sharedaddy/sharing-sources.php
@@ -197,7 +197,7 @@ class Share_Email extends Sharing_Source {
 	}
 
 	public function get_name() {
-		return __( 'Email', 'jetpack' );
+		return _x( 'Email', 'as sharing source', 'jetpack' );
 	}
 
 	// Default does nothing
@@ -317,6 +317,9 @@ class Share_Email extends Sharing_Source {
 
 class Share_Twitter extends Sharing_Source {
 	var $shortname = 'twitter';
+	// 'https://dev.twitter.com/docs/api/1.1/get/help/configuration' ( 2013/06/24 ) short_url_length is 22
+	var $short_url_length = 24;
+
 	public function __construct( $id, array $settings ) {
 		parent::__construct( $id, $settings );
 
@@ -402,8 +405,8 @@ class Share_Twitter extends Sharing_Source {
 			$sig     = '';
 		}
 
-		$suffix_length = $strlen( " {$post_link}{$sig}" );
 
+		$suffix_length = $this->short_url_length + $strlen( " {$sig}" );
 		// $sig is handled by twitter in their 'via' argument.
 		// $post_link is handled by twitter in their 'url' argument.
 		if ( 140 < $strlen( $post_title ) + $suffix_length ) {
@@ -600,28 +603,14 @@ class Share_LinkedIn extends Sharing_Source {
 
 	public function process_request( $post, array $post_data ) {
 
-		setup_postdata( $post );
-
 		$post_link = $this->get_share_url( $post->ID );
 
-		// http://www.linkedin.com/shareArticle?mini=true&url={articleUrl}&title={articleTitle}&summary={articleSummary}&source={articleSource}
-
-		$encoded_title = rawurlencode( $post->post_title );
-		if( strlen( $encoded_title ) > 200 )
-			$encoded_title = substr( $encoded_title, 0, 197 ) . '...';
-
-		$encoded_summary = rawurlencode( strip_tags( get_the_excerpt() ) );
-		if( strlen( $encoded_summary ) > 256 )
-			$encoded_summary = substr( $encoded_summary, 0, 253 ) . '...';
-
-		$source = get_bloginfo( 'name' );
+		// Using the same URL as the official button, which is *not* LinkedIn's documented sharing link
+		// http://www.linkedin.com/cws/share?url={url}&token=&isFramed=false
 
 		$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' );
+		), 'http://www.linkedin.com/cws/share?token=&isFramed=false' );
 
 		// Record stats
 		parent::process_request( $post, $post_data );
@@ -1214,6 +1203,8 @@ class Share_Pinterest extends Sharing_Source {
 				s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
 				var x = document.getElementsByTagName("script")[0];
 				x.parentNode.insertBefore(s, x);
+				// if 'Pin it' button has 'counts' make container wider
+				jQuery(window).load( function(){ jQuery( 'li.share-pinterest a span:visible' ).closest( '.share-pinterest' ).width( '80px' ); } );
 			</script>
 		<?php else : ?>
 			<script type="text/javascript">
@@ -1240,3 +1231,65 @@ class Share_Pinterest extends Sharing_Source {
 		<?php endif;
 	}
 }
+
+class Share_Pocket extends Sharing_Source {
+	var $shortname = 'pocket';
+
+	public function __construct( $id, array $settings ) {
+		parent::__construct( $id, $settings );
+
+		if ( 'official' == $this->button_style )
+			$this->smart = true;
+		else
+			$this->smart = false;
+	}
+
+	public function get_name() {
+		return __( 'Pocket', 'jetpack' );
+	}
+
+	public function process_request( $post, array $post_data ) {
+		// Record stats
+		parent::process_request( $post, $post_data );
+
+		$pocket_url = esc_url_raw( 'https://getpocket.com/save/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $post->post_title ) );
+		wp_redirect( $pocket_url );
+		exit;
+	}
+
+	public function get_display( $post ) {
+		if ( $this->smart ) {
+			$post_count = 'horizontal';
+
+			$button = '';
+			$button .= '<div class="pocket_button">';
+			$button .= sprintf( '<a href="https://getpocket.com/save" class="pocket-btn" data-lang="%s" data-save-url="%s" data-pocket-count="%s" >%s</a>', 'en', esc_attr( $this->get_share_url( $post->ID ) ), $post_count, esc_attr__( 'Pocket', 'jetpack' ) );
+			$button .= '</div>';
+
+			return $button;
+		} else {
+			return $this->get_link( get_permalink( $post->ID ), _x( 'Pocket', 'share to', 'jetpack' ), __( 'Click to share on Pocket', 'jetpack' ), 'share=pocket' );
+		}
+
+	}
+
+	function display_footer() {
+		if ( $this->smart ) :
+		?>
+		<script>
+		// Don't use Pocket's default JS as it we need to force init new Pocket share buttons loaded via JS.
+		function jetpack_sharing_pocket_init() {
+			jQuery.getScript( 'https://widgets.getpocket.com/v1/j/btn.js?v=1' );
+		}
+		jQuery( document ).on( 'ready', jetpack_sharing_pocket_init );
+		jQuery( document.body ).on( 'post-load', jetpack_sharing_pocket_init );
+		</script>
+		<?php
+		else :
+			$this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
+		endif;
+
+	}
+
+}
+

diff --git a/plugins/jetpack/modules/sharedaddy/sharing.css b/plugins/jetpack/modules/sharedaddy/sharing.css
index 95a09d0..1d1719c 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing.css
+++ b/plugins/jetpack/modules/sharedaddy/sharing.css
@@ -1,4 +1,4 @@
-div.sharedaddy ul, 
+li.share-print a.sd-button > spandiv.sharedaddy ul,
 div.sharedaddy li {
 	margin: 0;
 	padding: 0;
@@ -7,15 +7,15 @@ div.sharedaddy li {
 	background: none;
 }
 
-div.sharedaddy, 
-#content div.sharedaddy, 
+div.sharedaddy,
+#content div.sharedaddy,
 #main div.sharedaddy {
 	font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
 	font-size: 12px;
 	clear: both;
 }
 
-div.sharedaddy, 
+div.sharedaddy,
 div.sharedaddy div {
 	-webkit-border-radius: 0 !important;
 	-moz-border-radius: 0 !important;
@@ -41,7 +41,7 @@ div.sharedaddy h3,
 }
 
 /* @noflip */
-.rtl div.sharedaddy h3, 
+.rtl div.sharedaddy h3,
 .rtl #content div.sharedaddy h3,
 .rtl #main div.sharedaddy h3,
 .rtl #primary div.sharedaddy h3 {
@@ -49,7 +49,7 @@ div.sharedaddy h3,
 	text-align: right;
 }
 
-div.sharedaddy ul, 
+div.sharedaddy ul,
 div.sharedaddy li {
 	margin: 0 !important;
 	padding: 0 !important;
@@ -60,29 +60,24 @@ div.sharedaddy li::before {
 	content: "";
 }
 
-div.sharedaddy div.sharing-clear {
-	margin: 0 !important;
-	padding: 0 !important;
-}
-
 div.sharedaddy div.pd-rating {
 	margin: 0;
 	min-height: 23px;
 }
 
-div.sharedaddy a, 
-div.sharedaddy a:link, 
+div.sharedaddy a,
+div.sharedaddy a:link,
 div.sharedaddy a:visited {
 	font-style: normal;
 }
 
 /* ClearFix trick */
 
-div.sharedaddy:before, 
+div.sharedaddy:before,
 div.sharedaddy:after,
-div.sharedaddy .sd-block:before, 
+div.sharedaddy .sd-block:before,
 div.sharedaddy .sd-block:after,
-div.sharedaddy ul:before, 
+div.sharedaddy ul:before,
 div.sharedaddy ul:after {
 	content: "\0020";
 	display: block;
@@ -120,7 +115,7 @@ div.sharedaddy.sharedaddy-dark .sd-block {
 }
 
 div.sharedaddy .sd-content {
-	width: 82.125%; /* 530px / 640px */ 
+	width: 82.125%; /* 530px / 640px */
 	float: right;
 	margin: -2px 0 0 0;
 }
@@ -315,6 +310,14 @@ li.share-pinterest a.sd-button > span {
 	background-image: url('images/pinterest.png');
 }
 
+li.share-pocket a.sd-button > span {
+	background-image: url('images/pocket.png');
+}
+
+li.share-kindle a.sd-button > span {
+	background-image: url('images/kindle.png');
+}
+
 li.share-email a.sd-button > span {
 	background-image: url('images/email.png');
 }
@@ -327,23 +330,23 @@ a.sd-button.share-more span {
 	background-image: url('images/more.png');
 }
 
-@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) {
+@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), only screen and (min-resolution: 120dpi) {
 
 	li.share-facebook a.sd-button > span {
 		background-image: url('images/facebook@2x.png');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-tumblr a.sd-button > span {
 		background-image: url('images/tumblr@2x.png');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-twitter a.sd-button > span {
 		background-image: url('images/twitter@2x.png?1');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-google-plus-1 a.sd-button > span {
 		background-image: url('images/googleplus1@2x.png');
 		background-size: 16px 16px;
@@ -353,42 +356,52 @@ a.sd-button.share-more span {
 		background-image: url('images/linkedin@2x.png');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-press-this a.sd-button > span {
 		background-image: url('images/wordpress@2x.png');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-digg a.sd-button > span {
 		background-image: url('images/digg@2x.png?1');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-stumbleupon a.sd-button > span {
 		background-image: url('images/stumbleupon@2x.png');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-reddit a.sd-button > span {
 		background-image: url('images/reddit@2x.png');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-pinterest a.sd-button > span {
 		background-image: url('images/pinterest@2x.png');
 		background-size: 16px 16px;
 	}
-	
+
+	li.share-pocket a.sd-button > span {
+		background-image: url('images/pocket@2x.png');
+		background-size: 16px 16px;
+	}
+
+	li.share-kindle a.sd-button > span {
+		background-image: url('images/kindle@2x.png');
+		background-size: 16px 16px;
+	}
+
 	li.share-email a.sd-button > span {
 		background-image: url('images/email@2x.png?1');
 		background-size: 16px 16px;
 	}
-	
+
 	li.share-print a.sd-button > span {
 		background-image: url('images/print@2x.png');
 		background-size: 16px 16px;
 	}
-	
+
 	a.sd-button.share-more span {
 		background-image: url('images/more@2x.png?1');
 		background-size: 16px 16px;

diff --git a/plugins/jetpack/modules/sharedaddy/sharing.js b/plugins/jetpack/modules/sharedaddy/sharing.js
index 68482c6..c996bb6 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing.js
+++ b/plugins/jetpack/modules/sharedaddy/sharing.js
@@ -71,7 +71,7 @@ var WPCOMSharing = {
 
 		// Touchscreen device: use click.
 		// Non-touchscreen device: use click if not already appearing due to a hover event
-		$more_sharing_buttons.click( function() {
+		$more_sharing_buttons.on( 'click', function() {
 			var $more_sharing_button = $( this ),
 			    $more_sharing_pane = $more_sharing_button.parents( 'div:first' ).find( '.inner' );
 
@@ -183,6 +183,11 @@ var WPCOMSharing = {
 
 		// Add click functionality
 		$( '.sharedaddy ul' ).each( function( item ) {
+
+			if ( 'yep' == $( this ).data( 'has-click-events' ) )
+				return;
+			$( this ).data( 'has-click-events', 'yep' );
+
 			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>' )
 			};
@@ -233,7 +238,7 @@ var WPCOMSharing = {
 			} );
 
 			// Email button
-			$( this ).find( 'a.share-email' ).click( function() {
+			$( 'a.share-email', this ).on( 'click', function() {
 				var url = $( this ).attr( 'href' ), key;
 
 				if ( $( '#sharing_email' ).is( ':visible' ) )
@@ -251,7 +256,7 @@ var WPCOMSharing = {
 						key = $( '#recaptcha_public_key' ).val();
 
 					// Update the recaptcha
-					Recaptcha.create( key, 'sharing_recaptcha' );
+					Recaptcha.create( key, 'sharing_recaptcha', { lang : recaptcha_options.lang } );
 
 					// Show dialog
 					$( '#sharing_email' ).css( {

diff --git a/plugins/jetpack/modules/sharedaddy/sharing.php b/plugins/jetpack/modules/sharedaddy/sharing.php
index 118f851..974fe74 100644
--- a/plugins/jetpack/modules/sharedaddy/sharing.php
+++ b/plugins/jetpack/modules/sharedaddy/sharing.php
@@ -281,7 +281,6 @@ class Sharing_Admin {
 									endforeach; ?>
 									<li class="advanced"><a href="#" class="sharing-anchor sd-button share-more"><span><?php _e( 'More', 'jetpack' ); ?></span></a></li>
 								</ul>
-								<div class="sharing-clear"></div>
 							</div>
 						</div>
 						<br class="clearing" />

diff --git a/plugins/jetpack/modules/shortcodes.php b/plugins/jetpack/modules/shortcodes.php
index e10805c..ce54d63 100644
--- a/plugins/jetpack/modules/shortcodes.php
+++ b/plugins/jetpack/modules/shortcodes.php
@@ -6,6 +6,7 @@
  * Sort Order: 11
  * First Introduced: 1.1
  * Major Changes In: 1.2
+ * Requires Connection: No
  */
 
 /**
@@ -21,7 +22,7 @@
  */
 function shortcode_new_to_old_params( $params, $old_format_support = false ) {
 	$str = '';
-	
+
 	if ( $old_format_support && isset( $params[0] ) ) {
 		$str = ltrim( $params[0], '=' );
 	} elseif ( is_array( $params ) ) {
@@ -30,13 +31,39 @@ function shortcode_new_to_old_params( $params, $old_format_support = false ) {
 				$str = $key . '=' . $params[$key];
 		}
 	}
-	
-	return str_replace( array( '&amp;', '&#038;' ), '&', $str );  
+
+	return str_replace( array( '&amp;', '&#038;' ), '&', $str );
 }
 
 function jetpack_load_shortcodes() {
+	global $wp_version;
+
+	$shortcode_includes = array();
+
 	foreach ( Jetpack::glob_php( dirname( __FILE__ ) . '/shortcodes' ) as $file ) {
-		include $file;
+		$shortcode_includes[] = $file;
+	}
+
+	$shortcode_includes = apply_filters( 'jetpack_shortcodes_to_include', $shortcode_includes );
+
+	foreach ( $shortcode_includes as $include ) {
+                if ( version_compare( $wp_version, '3.6-z', '>=' ) && stristr( $include, 'audio.php' ) )
+			continue;
+
+		include $include;
+	}
+}
+
+global $wp_version;
+
+if ( version_compare( $wp_version, '3.6-z', '>=' ) ) {
+	add_filter( 'shortcode_atts_audio', 'jetpack_audio_atts_handler', 10, 3 );
+
+	function jetpack_audio_atts_handler( $out, $pairs, $atts ) {
+		if( isset( $atts[0] ) )
+			$out['src'] = $atts[0];
+
+		return $out;
 	}
 }
 

diff --git a/plugins/jetpack/modules/shortcodes/archives.php b/plugins/jetpack/modules/shortcodes/archives.php
index b4c78f3..c407978 100644
--- a/plugins/jetpack/modules/shortcodes/archives.php
+++ b/plugins/jetpack/modules/shortcodes/archives.php
@@ -3,7 +3,7 @@
 /*
  * Archives shortcode
  * @author bubel & nickmomrik
- * [archives limit=10] 
+ * [archives limit=10]
  */
 
 add_shortcode( 'archives', 'archives_shortcode' );

diff --git a/plugins/jetpack/modules/shortcodes/audio.php b/plugins/jetpack/modules/shortcodes/audio.php
index 9c6b49e..744cf49 100644
--- a/plugins/jetpack/modules/shortcodes/audio.php
+++ b/plugins/jetpack/modules/shortcodes/audio.php
@@ -17,6 +17,16 @@ class AudioShortcode {
 	}
 
 	/**
+	 * Return the $url of the audio
+	 */
+	static function get_audio_id( $atts ) {
+		if ( isset( $atts[0] ) )
+			return $atts[0];
+		else
+			return 0;
+	}
+
+	/**
 	 * Shortcode for audio
 	 * [audio http://wpcom.files.wordpress.com/2007/01/mattmullenweg-interview.mp3|width=180|titles=1|artists=2]
 	 *
@@ -31,7 +41,12 @@ class AudioShortcode {
 		}
 
 		if ( ! isset( $atts[0] ) ) {
-			return '<!-- Audio shortcode source not set -->';
+			if ( isset( $atts['src'] ) ) {
+				$atts[0] = $atts['src'];
+				unset( $atts['src'] );
+			} else {
+				return '<!-- Audio shortcode source not set -->';
+			}
 		}
 
 		// add the special .js
@@ -79,6 +94,13 @@ class AudioShortcode {
 		$data = preg_split( "/\|/", $src );
 		$sound_file = $data[0];
 		$sound_files = explode( ',', $sound_file );
+
+		if ( is_ssl() ) {
+			for ( $i = 0; $i < count( $sound_files ); $i++ ) {
+				$sound_files[ $i ] = preg_replace( '#^http://([^.]+).files.wordpress.com/#', 'https://$1.files.wordpress.com/', $sound_files[ $i ] );
+			}
+		}
+
 		$sound_files = array_map( 'trim', $sound_files );
 		$sound_files = array_map( array( $this, 'rawurlencode_spaces' ), $sound_files );
 		$sound_files = array_map( 'esc_url_raw', $sound_files ); // Ensure each is a valid URL
@@ -232,9 +254,14 @@ CONTROLS;
 		}
 		$html5_audio .= "<span id='wp-as-{$post->ID}_{$ap_playerID}-playing'></span>";
 
+		if ( is_ssl() )
+			$protocol = 'https';
+		else
+			$protocol = 'http';
+
 		$swfurl = apply_filters(
 			'jetpack_static_url',
-			'http://en.wordpress.com/wp-content/plugins/audio-player/player.swf' );
+			"$protocol://en.wordpress.com/wp-content/plugins/audio-player/player.swf" );
 
 		// all the fancy javascript is causing Google Reader to break, just include flash in GReader
 		// override html5 audio code w/ just not supported code

diff --git a/plugins/jetpack/modules/shortcodes/blip.php b/plugins/jetpack/modules/shortcodes/blip.php
index e757dc4..0245522 100644
--- a/plugins/jetpack/modules/shortcodes/blip.php
+++ b/plugins/jetpack/modules/shortcodes/blip.php
@@ -2,10 +2,10 @@
 
 /**
  * Blip.tv embed code:
- * <embed src="http://blip.tv/play/g8sVgpfaCgI%2Em4v" type="application/x-shockwave-flash" width="480" height="255" allowscriptaccess="always" allowfullscreen="true"></embed> 
+ * <embed src="http://blip.tv/play/g8sVgpfaCgI%2Em4v" type="application/x-shockwave-flash" width="480" height="255" allowscriptaccess="always" allowfullscreen="true"></embed>
  * Blip.tv shortcode is: [blip.tv url-or-something-else]
  * */
-  
+
 function blip_embed_to_shortcode( $content ) {
 	if ( false === stripos( $content, '/blip.tv/play/' ) )
 		return $content;
@@ -47,7 +47,7 @@ function blip_shortcode( $atts ) {
 		return "<script type='text/javascript' src='http://blip.tv/syndication/write_player?skin=js&posts_id={$matches[1]}&cross_post_destination={$matches[2]}&view=full_js'></script>";
 	elseif ( preg_match( '|^http://blip.tv/play/[.\w]+$|', urldecode( $src ) ) ) // WLS
 		return "<embed src='$src' type='application/x-shockwave-flash' width='480' height='300' allowscriptaccess='never' allowfullscreen='true'></embed>";
-	
+
 
 	return "<!--blip.tv pattern not matched -->";
 }

diff --git a/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css b/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css
index 167ec70..eea868a 100644
--- a/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css
+++ b/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css
@@ -1,4 +1,4 @@
-/* This file was automatically generated on Jan 06 2013 05:39:50 */
+/* This file was automatically generated on Mar 25 2013 08:14:36 */
 
 .slideshow-window {
 	background-color: #222;
@@ -25,6 +25,8 @@
 body div.slideshow-window * img {
     /* Override any styles that might be present in the page stylesheet */
     border-width: 0 !important;
+    margin-left: auto !important;
+    margin-right: auto !important;
     padding: 0 !important;
     background-color: transparent !important;
     background-image: none !important;

diff --git a/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css b/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css
index e6d05b2..13cef49 100644
--- a/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css
+++ b/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css
@@ -23,6 +23,8 @@
 body div.slideshow-window * img {
     /* Override any styles that might be present in the page stylesheet */
     border-width: 0 !important;
+    margin-right: auto !important;
+    margin-left: auto !important;
     padding: 0 !important;
     background-color: transparent !important;
     background-image: none !important;

diff --git a/plugins/jetpack/modules/shortcodes/dailymotion.php b/plugins/jetpack/modules/shortcodes/dailymotion.php
index a6daed9..fe2e6ab 100644
--- a/plugins/jetpack/modules/shortcodes/dailymotion.php
+++ b/plugins/jetpack/modules/shortcodes/dailymotion.php
@@ -6,13 +6,13 @@
 
 /**
  * Original codes:
- * 
+ *
  * <embed height="270" type="application/x-shockwave-flash" width="480" src="http&#58;//www.dailymotion.com/swf/video/xekmrq?additionalInfos=0" wmode="opaque" pluginspage="http&#58;//www.macromedia.com/go/getflashplayer" allowscriptaccess="never" allownetworking="internal" />
  *
  * <object width="480" height="240"><param name="movie" value="http://www.dailymotion.com/swf/video/xen4ms_ghinzu-cold-love-mirror-mirror_music?additionalInfos=0"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"></param>
  * 	<embed type="application/x-shockwave-flash" src="http://www.dailymotion.com/swf/video/xen4ms_ghinzu-cold-love-mirror-mirror_music?additionalInfos=0" width="480" height="240" allowfullscreen="true" allowscriptaccess="always"></embed>
  * </object><br /><b><a href="http://www.dailymotion.com/video/xen4ms_ghinzu-cold-love-mirror-mirror_music">Ghinzu - Cold Love (Mirror Mirror)</a></b><br /><i>Uploaded by <a href="http://www.dailymotion.com/GhinzuTV">GhinzuTV</a>. - <a href="http://www.dailymotion.com/us/channel/music">Watch more music videos, in HD!</a></i>
- *   
+ *
  * Code as of 01.01.11:
  * <object width="560" height="421"><param name="movie" value="http://www.dailymotion.com/swf/video/xaose5?width=560&theme=denim&foreground=%2392ADE0&highlight=%23A2ACBF&background=%23202226&start=&animatedTitle=&iframe=0&additionalInfos=0&autoPlay=0&hideInfos=0"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"></param><embed type="application/x-shockwave-flash" src="http://www.dailymotion.com/swf/video/xaose5?width=560&theme=denim&foreground=%2392ADE0&highlight=%23A2ACBF&background=%23202226&start=&animatedTitle=&iframe=0&additionalInfos=0&autoPlay=0&hideInfos=0" width="560" height="421" allowfullscreen="true" allowscriptaccess="always"></embed></object><br /><b><a href="http://www.dailymotion.com/video/xaose5_sexy-surprise_na">Sexy Surprise</a></b><br /><i>Uploaded by <a href="http://www.dailymotion.com/GilLavie">GilLavie</a>. - <a target="_self" href="http://www.dailymotion.com/channel/sexy/featured/1">Find more steamy, sex
 y videos.</a></i>
  * movie param enforces anti-xss protection
@@ -53,29 +53,29 @@ add_filter( 'pre_kses', 'dailymotion_embed_to_shortcode' );
 
 /**
  * DailyMotion shortcode
- * 
- * The documented shortcode is: 
- * [dailymotion id=x8oma9] 
- * 
+ *
+ * The documented shortcode is:
+ * [dailymotion id=x8oma9]
+ *
  * Possibilities, according to the old parsing regexp:
  * [dailymotion x8oma9]
- * [dailymotion=x8oma9]    
- * 
+ * [dailymotion=x8oma9]
+ *
  * Hypothetical option, according to the old shortcode function is
  * [dailymotion id=1&title=2&user=3&video=4]
- *  
- * The new style is now: 
- * [dailymotion id=x8oma9 title=2 user=3 video=4] 
- *   
+ *
+ * The new style is now:
+ * [dailymotion id=x8oma9 title=2 user=3 video=4]
+ *
  * @param array $atts
- * @return string html 
+ * @return string html
  *
- */  
+ */
 
 function dailymotion_shortcode( $atts ) {
 	global $content_width;
 
-	if ( isset( $atts[0] ) ) { 
+	if ( isset( $atts[0] ) ) {
 		$id = ltrim( $atts[0], '=' );
 		$atts['id'] = $id;
 	} else {
@@ -85,7 +85,7 @@ function dailymotion_shortcode( $atts ) {
 
 	if ( isset( $atts['id'] ) )
 		$id = $atts['id'];
-	else 
+	else
 		return '<!--Dailymotion error: bad or missing ID-->';
 
 	if ( !empty( $content_width ) )

diff --git a/plugins/jetpack/modules/shortcodes/diggthis.php b/plugins/jetpack/modules/shortcodes/diggthis.php
index ee1195f..0077a46 100644
--- a/plugins/jetpack/modules/shortcodes/diggthis.php
+++ b/plugins/jetpack/modules/shortcodes/diggthis.php
@@ -1,17 +1,17 @@
 <?php
 
 /**
- * Digg changed their button API. 
- * 
+ * Digg changed their button API.
+ *
  * The old style button was something like this:
  * [digg=http://digg.com/some-digg-permalink] - uses digg permalink as id.
- * 
+ *
  * The new style is:
- * [digg class="wide"] # The class options are: 'wide', 'medium', 'compact', 'icon' 
+ * [digg class="wide"] # The class options are: 'wide', 'medium', 'compact', 'icon'
  * and uses get_permalink() as id.
- * 
- * @author Veselin Nikolov  
- */ 
+ *
+ * @author Veselin Nikolov
+ */
 
 function digg_shortcode_js() {
 	echo '

diff --git a/plugins/jetpack/modules/shortcodes/flickr.php b/plugins/jetpack/modules/shortcodes/flickr.php
index 6a85f4c..3f1b13c 100644
--- a/plugins/jetpack/modules/shortcodes/flickr.php
+++ b/plugins/jetpack/modules/shortcodes/flickr.php
@@ -12,8 +12,8 @@
 
 */
 
-/* 
- * <object type="application/x-shockwave-flash" width="400" height="300" data="http://www.flickr.com/apps/video/stewart.swf?v=71377" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param name="flashvars" value="intl_lang=en-us&photo_secret=846d9c1be9&photo_id=2345938910"></param> <param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=71377"></param> <param name="bgcolor" value="#000000"></param> <param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=71377" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&photo_secret=846d9c1be9&photo_id=2345938910" height="300" width="400"></embed></object>  
+/*
+ * <object type="application/x-shockwave-flash" width="400" height="300" data="http://www.flickr.com/apps/video/stewart.swf?v=71377" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param name="flashvars" value="intl_lang=en-us&photo_secret=846d9c1be9&photo_id=2345938910"></param> <param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=71377"></param> <param name="bgcolor" value="#000000"></param> <param name="allowFullScreen" value="true"></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=71377" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&photo_secret=846d9c1be9&photo_id=2345938910" height="300" width="400"></embed></object>
  */
 
 function flickr_embed_to_shortcode( $content ) {
@@ -94,7 +94,7 @@ function flickr_shortcode_handler( $atts ) {
 
 	if ( isset( $atts['video'] ) ) {
 		$showing = 'video';
-		$src = $atts['video'];	
+		$src = $atts['video'];
 	} elseif ( isset( $atts['photo'] ) ) {
 		$showing = 'photo';
 		$src = $atts['photo'];
@@ -113,7 +113,7 @@ function flickr_shortcode_handler( $atts ) {
 		elseif ( in_array( $atts['show_info'], array( 'false', 'no' ) ) )
 			$atts['show_info'] = 'false';
 
-    	if ( isset( $atts['secret'] ) ) 
+    	if ( isset( $atts['secret'] ) )
 		$atts['secret'] = preg_replace( '![^\w]+!i', '', $atts['secret'] );
 
 		return flickr_shortcode_video_markup( $atts );
@@ -125,7 +125,7 @@ function flickr_shortcode_handler( $atts ) {
 function flickr_shortcode_video_markup( $atts ) {
 	$atts = array_map( 'esc_attr', $atts );
 
-	$photo_vars = "photo_id=$atts[photo_id]";	
+	$photo_vars = "photo_id=$atts[photo_id]";
 	if ( isset( $atts['secret'] ) )
 		$photo_vars .= "&amp;photo_secret=$atts[secret]";
 

diff --git a/plugins/jetpack/modules/shortcodes/googlemaps.php b/plugins/jetpack/modules/shortcodes/googlemaps.php
index fe79a9e..224654f 100644
--- a/plugins/jetpack/modules/shortcodes/googlemaps.php
+++ b/plugins/jetpack/modules/shortcodes/googlemaps.php
@@ -75,6 +75,10 @@ function jetpack_googlemaps_shortcode( $atts ) {
 			}
 		}
 		$url = substr( $url, 0, -5 );
+
+		if( is_ssl() )
+			$url = str_replace( 'http://', 'https://', $url );
+
 		$link_url = preg_replace( '!output=embed!', 'source=embed', $url );
 
 		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>';

diff --git a/plugins/jetpack/modules/shortcodes/googlevideo.php b/plugins/jetpack/modules/shortcodes/googlevideo.php
index 83074fb..cbd709c 100644
--- a/plugins/jetpack/modules/shortcodes/googlevideo.php
+++ b/plugins/jetpack/modules/shortcodes/googlevideo.php
@@ -2,7 +2,7 @@
 
 /**
  * google video is replaced by youtube, but its embeds will probably continue working indefinitely.
- * [googlevideo=http://video.google.com/googleplayer.swf?docId=-6006084025483872237]    
+ * [googlevideo=http://video.google.com/googleplayer.swf?docId=-6006084025483872237]
  */
 
 function googlevideo_shortcode( $atts ) {
@@ -10,7 +10,7 @@ function googlevideo_shortcode( $atts ) {
 		return '';
 
 	$src = ltrim( $atts[0], '=' );
-  
+
 	if ( 0 !== strpos( $src, 'http://video.google.com/googleplayer.swf' ) ) {
 		if ( !preg_match( '|^http://(video\.google\.[a-z]{2,3}(?:.[a-z]{2})?)/|', $src ) || !preg_match( '|.*docid=([0-9-]+).*|i', $src, $match ) || !is_numeric( $match[1] ) )
 			return '<!--Google Video Error: bad URL entered-->';

diff --git a/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js b/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js
index 7697258..400219e 100644
--- a/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js
+++ b/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js
@@ -50,7 +50,7 @@ window.audioshortcode = {
 		}
 
 		// bail if there are no more good files
-		if ( 0 == this[player_id].files.length ) {
+		if ( 0 === this[player_id].files.length ) {
 			return;
 		}
 		player.src = this[player_id].files[0];
@@ -64,7 +64,7 @@ window.audioshortcode = {
 			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 );	
+				audioshortcode.next_track( player_id, false, loop );
 			}
 		}, false );
 
@@ -91,7 +91,7 @@ window.audioshortcode = {
 		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 ) {
+		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 ) {
@@ -115,9 +115,9 @@ window.audioshortcode = {
 	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 
-		};
+		if ( player.paused || 0 === this[player_id].i ) {
+			return;
+		}
 
 		player.pause();
 		if ( 0 < this[player_id].i ) {

diff --git a/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js b/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js
index 89d583e..d12df1b 100644
--- a/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js
+++ b/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js
@@ -22,7 +22,7 @@ if ($.support === undefined) {
 function debug(s) {
 	if ($.fn.cycle.debug)
 		log(s);
-}		
+}
 function log() {
 	if (window.console && console.log)
 		console.log('[cycle] ' + Array.prototype.join.call(arguments,' '));
@@ -66,7 +66,7 @@ $.fn.cycle = function(options, arg2) {
 			return;
 
 		opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink;
-		
+
 		// stop existing slideshow for this container (if there is one)
 		if (this.cycleTimeout)
 			clearTimeout(this.cycleTimeout);
@@ -184,7 +184,7 @@ function handleArguments(cont, options, arg2) {
 		return false;
 	}
 	return options;
-	
+
 	function checkInstantResume(isPaused, arg2, cont) {
 		if (!isPaused && arg2 === true) { // resume now!
 			var options = $(cont).data('cycle.opts');
@@ -214,7 +214,7 @@ function destroy(cont, opts) {
 		$(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();
@@ -268,7 +268,7 @@ function buildOptions($cont, $slides, els, options, o) {
 		opts.startingSlide = parseInt(opts.startingSlide,10);
 		if (opts.startingSlide >= els.length || opts.startSlide < 0)
 			opts.startingSlide = 0; // catch bogus input
-		else 
+		else
 			startingSlideSpecified = true;
 	}
 	else if (opts.backwards)
@@ -361,7 +361,7 @@ function buildOptions($cont, $slides, els, options, o) {
 			});
 		});
 	}
-		
+
 	// stretch container
 	var reshape = (opts.containerResize || opts.containerResizeHeight) && !$cont.innerHeight();
 	if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9
@@ -447,7 +447,7 @@ function buildOptions($cont, $slides, els, options, o) {
 			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;
@@ -705,7 +705,7 @@ function go(els, opts, manual, fwd) {
 		};
 
 		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?
@@ -760,7 +760,7 @@ function go(els, opts, manual, fwd) {
 	}
 	if (changed && opts.pager)
 		opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass);
-	
+
 	function queueNext() {
 		// stage the next transition
 		var ms = 0, timeout = opts.timeout;
@@ -857,7 +857,7 @@ $.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
 	}
 	else
 		a = '<a href="#">'+(i+1)+'</a>';
-		
+
 	if (!a)
 		return;
 	var $a = $(a);
@@ -879,7 +879,7 @@ $.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
 
 	opts.pagerAnchors =  opts.pagerAnchors || [];
 	opts.pagerAnchors.push($a);
-	
+
 	var pagerFn = function(e) {
 		e.preventDefault();
 		opts.nextSlide = i;
@@ -894,30 +894,30 @@ $.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) {
 		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() { 
+			function() {
 				pauseFlag = true;
-				cont.cyclePause++; 
+				cont.cyclePause++;
 				triggerPause(cont,true,true);
-			}, function() { 
+			}, function() {
 				if (pauseFlag)
-					cont.cyclePause--; 
+					cont.cyclePause--;
 				triggerPause(cont,true,true);
-			} 
+			}
 		);
 	}
 };
@@ -990,7 +990,7 @@ $.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) {
 	};
 	$l.animate(opts.animOut, speedOut, easeOut, function() {
 		$l.css(opts.cssAfter);
-		if (!opts.sync) 
+		if (!opts.sync)
 			fn();
 	});
 	if (opts.sync) fn();

diff --git a/plugins/jetpack/modules/shortcodes/polldaddy.php b/plugins/jetpack/modules/shortcodes/polldaddy.php
index 7eb30ed..6b46da7 100644
--- a/plugins/jetpack/modules/shortcodes/polldaddy.php
+++ b/plugins/jetpack/modules/shortcodes/polldaddy.php
@@ -8,7 +8,7 @@ class PolldaddyShortcode {
 
 	static $add_script = false;
 	static $scripts = false;
-	
+
 	/**
 	 * Add all the actions & resgister the shortcode
 	 */
@@ -27,7 +27,7 @@ class PolldaddyShortcode {
 	function polldaddy_shortcode( $atts ) {
 		global $post;
 		global $content_width;
-	
+
 		extract( shortcode_atts( array(
 			'survey'     => null,
 			'link_text'  => 'Take Our Survey',
@@ -52,48 +52,48 @@ class PolldaddyShortcode {
 			'domain'     => '',
 			'id'         => ''
 		), $atts ) );
-		
+
 		if ( ! is_array( $atts ) ) {
 			return '<!-- Polldaddy shortcode passed invalid attributes -->';
 		}
-		
+
 		$inline          = false;
 		$no_script       = false;
 		$infinite_scroll = false;
-		
+
 		if ( is_home() && current_theme_supports( 'infinite-scroll' ) )
 			$infinite_scroll = true;
-	
+
 		if ( defined( 'PADPRESS_LOADED' ) )
 			$inline = true;
-	
+
 		if ( function_exists( 'get_option' ) && get_option( 'polldaddy_load_poll_inline' ) )
 			$inline = true;
-	
+
 		if ( is_feed() || ( defined( 'DOING_AJAX' ) && !$infinite_scroll ) )
 			$no_script = false;
-		
+
 		self::$add_script = $infinite_scroll;
-		
-		if ( intval( $rating ) > 0 && !$no_script ) { //rating embed		
-		
+
+		if ( intval( $rating ) > 0 && !$no_script ) { //rating embed
+
 			if ( empty( $unique_id ) )
 				$unique_id = is_page() ? 'wp-page-'.$post->ID : 'wp-post-'.$post->ID;
-			
+
 			if ( empty( $item_id ) )
 				$item_id = is_page() ? '_page_'.$post->ID : '_post_'.$post->ID;
-	
+
 			if ( empty( $title ) )
 				$title = apply_filters( 'wp_title', $post->post_title, '', '' );
-	
+
 			if ( empty( $permalink ) )
 				$permalink = get_permalink( $post->ID );
-				
+
 			$rating    = intval( $rating );
 			$unique_id = wp_strip_all_tags( $unique_id );
 			$item_id   = wp_strip_all_tags( $item_id );
 			$item_id   = preg_replace( '/[^_a-z0-9]/i', '', $item_id );
-			
+
 			$settings = json_encode( array(
 				'id'        => $rating,
 				'unique_id' => $unique_id,
@@ -101,10 +101,10 @@ class PolldaddyShortcode {
 				'permalink' => esc_url( $permalink ),
 				'item_id'   => $item_id
 			) );
-			
+
 			$item_id = esc_js( $item_id );
-			
-			if ( $inline ) {		
+
+			if ( $inline ) {
 				return <<<SCRIPT
 <div class="pd-rating" id="pd_rating_holder_{$rating}{$item_id}"></div>
 <script type="text/javascript" charset="UTF-8"><!--//--><![CDATA[//><!--
@@ -113,18 +113,18 @@ PDRTJS_settings_{$rating}{$item_id}={$settings};
 <script type="text/javascript" charset="UTF-8" src="http://i.polldaddy.com/ratings/rating.js"></script>
 SCRIPT;
 			}
-			else {				
+			else {
 				if ( self::$scripts === false )
 					self::$scripts = array();
-					
+
 				$data = array( 'id' => $rating, 'item_id' => $item_id, 'settings' => $settings );
-					
+
 				self::$scripts['rating'][] = $data;
-				
+
 				add_action( 'wp_footer', array( $this, 'generate_scripts' ) );
-				
+
 				$data = esc_attr( json_encode( $data ) );
-				
+
 				if ( $infinite_scroll )
 					return <<<CONTAINER
 <div class="pd-rating" id="pd_rating_holder_{$rating}{$item_id}" data-settings="{$data}"></div>
@@ -134,22 +134,22 @@ CONTAINER;
 <div class="pd-rating" id="pd_rating_holder_{$rating}{$item_id}"></div>
 CONTAINER;
 			}
-		} 
+		}
 		elseif ( intval( $poll ) > 0 ) { //poll embed
-		
+
 			$poll      = intval( $poll );
 			$poll_url  = sprintf( 'http://polldaddy.com/poll/%d', $poll );
 			$poll_js   = sprintf( '%s.polldaddy.com/p/%d.js', ( is_ssl() ? 'https://secure' : 'http://static' ), $poll );
 			$poll_link = sprintf( '<a href="%s">Take Our Poll</a>', $poll_url );
-	
+
 			if ( $no_script )
 				return $poll_link;
 			else {
 				if ( $type == 'slider' && !$inline ) {
-				
+
 					if( !in_array( $visit, array( 'single', 'multiple' ) ) )
 						$visit = 'single';
-						
+
 					$settings = json_encode( array(
 						'type'  => 'slider',
 						'embed' => 'poll',
@@ -157,7 +157,7 @@ CONTAINER;
 						'visit' => $visit,
 						'id'    => intval( $poll )
 					) );
-					
+
 					return <<<SCRIPT
 <script type="text/javascript" charset="UTF-8" src="http://i0.poll.fm/survey.js"></script>
 <script type="text/javascript" charset="UTF-8"><!--//--><![CDATA[//><!--
@@ -170,28 +170,28 @@ SCRIPT;
 					$cb      = ( $cb == 1 ? '?cb='.mktime() : false );
 					$margins = '';
 					$float   = '';
-					
+
 					if ( in_array( $align, array( 'right', 'left' ) ) ) {
-						$float = sprintf( 'float: %s;', $align );					
-						
+						$float = sprintf( 'float: %s;', $align );
+
 						if ( $align == 'left')
 							$margins = 'margin: 0px 10px 0px 0px;';
 						elseif ( $align == 'right' )
 							$margins = 'margin: 0px 0px 0px 10px';
-					}									
-			
+					}
+
 					if ( $cb === false && !$inline ) {
 						if ( self::$scripts === false )
 							self::$scripts = array();
-							
+
 						$data = array( 'url' => $poll_js );
-							
+
 						self::$scripts['poll'][] = $data;
-						
+
 						add_action( 'wp_footer', array( $this, 'generate_scripts' ) );
-						
+
 						$data = esc_attr( json_encode( $data ) );
-						
+
 						return <<<CONTAINER
 <a id="pd_a_{$poll}"></a>
 <div class="PDS_Poll" id="PDI_container{$poll}" data-settings="{$data}" style="display:inline-block;{$float}{$margins}"></div>
@@ -202,7 +202,7 @@ CONTAINER;
 					else {
 						if ( $inline )
 							$cb = '';
-							
+
 						return <<<CONTAINER
 <a id="pd_a_{$poll}"></a>
 <div class="PDS_Poll" id="PDI_container{$poll}" style="display:inline-block;{$float}{$margins}"></div>
@@ -210,60 +210,60 @@ CONTAINER;
 <script type="text/javascript" charset="UTF-8" src="{$poll_js}{$cb}"></script>
 <noscript>{$poll_link}</noscript>
 CONTAINER;
-					}				
-				}		
+					}
+				}
 			}
 		}
 		elseif ( !empty( $survey ) ) { //survey embed
-	
+
 			if ( in_array( $type, array( 'iframe', 'button', 'banner', 'slider' ) ) ) {
-				
+
 				if ( empty( $title ) ) {
 					$title = 'Take Our Survey';
 					if( !empty( $link_text ) )
 						$title = $link_text;
 				}
-				
+
 				$survey      = preg_replace( '/[^a-f0-9]/i', '', $survey );
-				$survey_url  = esc_url( "http://polldaddy.com/s/{$survey}" );			
-				$survey_link = sprintf( '<a href="%s">%s</a>', $survey_url, esc_html( $title ) );	
-				
+				$survey_url  = esc_url( "http://polldaddy.com/s/{$survey}" );
+				$survey_link = sprintf( '<a href="%s">%s</a>', $survey_url, esc_html( $title ) );
+
 				if ( $no_script || $inline || $infinite_scroll )
-					return $survey_link;			
-							
-				if ( $type == 'iframe' ) {	
+					return $survey_link;
+
+				if ( $type == 'iframe' ) {
 					if ( $height != 'auto' ) {
-						if ( isset( $content_width ) && is_numeric( $width ) && $width > $content_width ) 
+						if ( isset( $content_width ) && is_numeric( $width ) && $width > $content_width )
 							$width = $content_width;
-					
+
 						if ( !$width )
 							$width = '100%';
 						else
 							$width = (int) $width;
-					
+
 						if ( !$height )
 							$height = '600';
 						else
-							$height = (int) $height;		
-										
+							$height = (int) $height;
+
 						return <<<CONTAINER
-<iframe src="{$survey_url}?iframe=1" frameborder="0" width="{$width}" height="{$height}" scrolling="auto" allowtransparency="true" marginheight="0" marginwidth="0">{$survey_link}</iframe> 
+<iframe src="{$survey_url}?iframe=1" frameborder="0" width="{$width}" height="{$height}" scrolling="auto" allowtransparency="true" marginheight="0" marginwidth="0">{$survey_link}</iframe>
 CONTAINER;
-					}	
+					}
 					elseif ( !empty( $domain ) && !empty( $id ) ) {
-					
-						$auto_src = esc_url( "http://{$domain}.polldaddy.com/s/{$id}" );					
+
+						$auto_src = esc_url( "http://{$domain}.polldaddy.com/s/{$id}" );
 						$auto_src = parse_url( $auto_src );
-						
+
 						if ( !is_array( $auto_src ) || count( $auto_src ) == 0 )
 							return '<!-- no polldaddy output -->';
-							
+
 						if ( !isset( $auto_src['host'] ) || !isset( $auto_src['path'] ) )
 							return '<!-- no polldaddy output -->';
-						
+
 						$domain   = $auto_src['host'].'/s/';
 						$id       = str_ireplace( '/s/', '', $auto_src['path'] );
-						
+
 						$settings = json_encode( array(
 							'type'       => $type,
 							'auto'       => true,
@@ -271,21 +271,21 @@ CONTAINER;
 							'id'         => $id
 						) );
 					}
-				}			
-				else {				
+				}
+				else {
 					$text_color = preg_replace( '/[^a-f0-9]/i', '', $text_color );
 					$back_color = preg_replace( '/[^a-f0-9]/i', '', $back_color );
-					
+
 					if ( !in_array( $align, array( 'right', 'left', 'top-left', 'top-right', 'middle-left', 'middle-right', 'bottom-left', 'bottom-right' ) ) )
 						$align = '';
-						
+
 					if ( !in_array( $style, array( 'inline', 'side', 'corner', 'rounded', 'square' ) ) )
 						$style = '';
-				
+
 					$title  = wp_strip_all_tags( $title );
 					$body   = wp_strip_all_tags( $body );
 					$button = wp_strip_all_tags( $button );
-					
+
 					$settings = json_encode( array_filter( array(
 						'title'      => $title,
 						'type'       => $type,
@@ -296,7 +296,7 @@ CONTAINER;
 						'align'      => $align,
 						'style'      => $style,
 						'id'         => $survey
-					) ) );	
+					) ) );
 				}
 				return <<<CONTAINER
 <script type="text/javascript" charset="UTF-8" src="http://i0.poll.fm/survey.js"></script>
@@ -305,15 +305,15 @@ polldaddy.add( {$settings} );
 //--><!]]></script>
 <noscript>{$survey_link}</noscript>
 CONTAINER;
-			} 
+			}
 		}
 		else
 			return '<!-- no polldaddy output -->';
 	}
-	
+
 	function generate_scripts() {
 		$script = '';
-		
+
 		if ( is_array( self::$scripts ) ) {
 			if ( isset( self::$scripts['rating'] ) ) {
 				$script = "<script type='text/javascript' charset='UTF-8' id='polldaddyRatings'><!--//--><![CDATA[//><!--\n";
@@ -321,16 +321,16 @@ CONTAINER;
 					$script .= "PDRTJS_settings_{$rating['id']}{$rating['item_id']}={$rating['settings']}; if ( typeof PDRTJS_RATING !== 'undefined' ){if ( typeof PDRTJS_{$rating['id']}{$rating['item_id']} == 'undefined' ){PDRTJS_{$rating['id']}{$rating['item_id']} = new PDRTJS_RATING( PDRTJS_settings_{$rating['id']}{$rating['item_id']} );}}";
 				}
 				$script .= "\n//--><!]]></script><script type='text/javascript' charset='UTF-8' src='http://i.polldaddy.com/ratings/rating.js'></script>";
-			
+
 			}
-			
+
 			if ( isset( self::$scripts['poll'] ) ) {
 				foreach( self::$scripts['poll'] as $poll ) {
 					$script .= "<script type='text/javascript' charset='UTF-8' src='{$poll['url']}'></script>";
 				}
 			}
 		}
-			
+
 		self::$scripts = false;
 		echo $script;
 	}
@@ -365,8 +365,8 @@ CONTAINER;
 					wp_pd_js.type = 'text/javascript';
 					wp_pd_js.src = $script_url;
 					wp_pd_js.async = true;
-					wp_pd_js.onload = function() { 
-						jQuery( document.body ).trigger( 'pd-script-load' ); 
+					wp_pd_js.onload = function() {
+						jQuery( document.body ).trigger( 'pd-script-load' );
 					};
 					document.getElementsByTagName( 'head' )[0].appendChild( wp_pd_js );
 				} else {
@@ -375,7 +375,7 @@ CONTAINER;
 				//]]>
 				</script>
 SCRIPT;
-	
+
 		}
 	}
 }
@@ -388,7 +388,7 @@ if ( !function_exists( 'polldaddy_link' ) ) {
 	function polldaddy_link( $content ) {
 		return preg_replace( '!(?:\n|\A)http://polldaddy.com/poll/([0-9]+?)/(.+)?(?:\n|\Z)!i', "\n<script type='text/javascript' language='javascript' charset='utf-8' src='http://static.polldaddy.com/p/$1.js'></script><noscript> <a href='http://polldaddy.com/poll/$1/'>View Poll</a></noscript>\n", $content );
 	}
-	
+
 	// higher priority because we need it before auto-link and autop get to it
 	add_filter( 'the_content', 'polldaddy_link', 1 );
 	add_filter( 'the_content_rss', 'polldaddy_link', 1 );

diff --git a/plugins/jetpack/modules/shortcodes/slideshare.php b/plugins/jetpack/modules/shortcodes/slideshare.php
index 012b9c7..97d9d44 100644
--- a/plugins/jetpack/modules/shortcodes/slideshare.php
+++ b/plugins/jetpack/modules/shortcodes/slideshare.php
@@ -1,8 +1,8 @@
 <?php
 /*
- * Slideshare shortcode format: 
+ * Slideshare shortcode format:
  * [slideshare id=5342235&doc=camprock-101002163655-phpapp01&w=300&h=200]
- **/  
+ **/
 
 function slideshare_shortcode( $atts ) {
 	global $content_width;

diff --git a/plugins/jetpack/modules/shortcodes/slideshow.php b/plugins/jetpack/modules/shortcodes/slideshow.php
index ab1145d..f57802b 100644
--- a/plugins/jetpack/modules/shortcodes/slideshow.php
+++ b/plugins/jetpack/modules/shortcodes/slideshow.php
@@ -102,7 +102,7 @@ class Jetpack_Slideshow_Shortcode {
 		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 ) );
+			$caption = apply_filters( 'jetpack_slideshow_slide_caption', wptexturize( strip_tags( $attachment->post_excerpt ) ), $attachment->ID );
 
 			$gallery[] = (object) array(
 				'src'     => (string) esc_url_raw( $attachment_image_src ),

diff --git a/plugins/jetpack/modules/shortcodes/ted.php b/plugins/jetpack/modules/shortcodes/ted.php
index afd3596..4edc288 100644
--- a/plugins/jetpack/modules/shortcodes/ted.php
+++ b/plugins/jetpack/modules/shortcodes/ted.php
@@ -13,6 +13,10 @@
 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 );
 
+function jetpack_shortcode_get_ted_id( $atts ) {
+	return ( ! empty( $atts['id'] ) ? $atts['id'] : 0 );
+}
+
 add_shortcode( 'ted', 'shortcode_ted' );
 function shortcode_ted( $atts, $content = '' ) {
 	global $wp_embed;

diff --git a/plugins/jetpack/modules/shortcodes/videopress.php b/plugins/jetpack/modules/shortcodes/videopress.php
index 6aebae0..6a3a75b 100644
--- a/plugins/jetpack/modules/shortcodes/videopress.php
+++ b/plugins/jetpack/modules/shortcodes/videopress.php
@@ -8,7 +8,7 @@
  * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  */
 
-/* 
+/*
 Plugin Name: VideoPress
 Plugin URI: http://wordpress.org/extend/plugins/video/
 Description: Upload new videos to <a href="http://videopress.com/">VideoPress</a>, edit metadata, and easily insert VideoPress videos into posts and pages using shortcodes. Requires a <a href="http://wordpress.com/">WordPress.com</a> account and a WordPress.com blog with the <a href="http://en.wordpress.com/products/#videopress">VideoPress upgrade</a> to store and serve uploaded videos.
@@ -113,7 +113,7 @@ class VideoPress {
 	public static function find_all_shortcodes( $content ) {
 		$r = preg_match_all( '/(.?)\[(wpvideo|videopress)\b(.*?)(?:(\/))?\](?:(.+?)\[\/\2\])?(.?)/s', $content, $matches, PREG_SET_ORDER );
 
-		if ( $r === false || $r === 0 ) 
+		if ( $r === false || $r === 0 )
 			return array();
 
 		$guids = array();
@@ -187,11 +187,11 @@ 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.09' );
-		
+
 		$this->js_loaded = true;
 		return true;
 	}
-	
+
 	/**
 	 * Print the VideoPress JS files now.
 	 * Used to load the JS in the footer, if it hasn't already been loaded in the header.
@@ -218,7 +218,7 @@ class VideoPress {
 		$guid = $attr[0];
 		if ( ! self::is_valid_guid( $guid ) )
 			return '';
-			
+
 		if ( array_key_exists( $guid, $this->shown ) )
 			$this->shown[$guid]++;
 		else
@@ -238,7 +238,7 @@ class VideoPress {
 		 */
 		if ( $freedom === false && (bool) get_option( 'video_player_freedom', false ) )
 			$freedom = true;
-			
+
 		$forcestatic = get_option( 'video_player_static', false );
 
 		/**
@@ -360,7 +360,7 @@ class VideoPress_Video {
 	 *
 	 * @var int
 	 * @since 1.3
-	 */	
+	 */
 	public $calculated_height;
 
 	/**
@@ -787,7 +787,7 @@ class VideoPress_Player {
 	public function asXML() {
 		if ( empty( $this->video ) || is_wp_error( $this->video ) )
 			return '';
-		
+
 		if ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true )
 			$content = $this->html5_static();
 		else
@@ -883,7 +883,7 @@ class VideoPress_Player {
 		 * @link https://developer.mozilla.org/en/JavaScript/Reference/global_objects/date Mozilla JavaScript Reference: Date
 		 */
 		$html .= '<select name="month" style="' . $inputs_style . '">';
-		
+
 		$months = array( __('January', 'jetpack'), __('February', 'jetpack'), __('March', 'jetpack'), __('April', 'jetpack'), __('May', 'jetpack'), __('June', 'jetpack'), __('July', 'jetpack'), __('August', 'jetpack'), __('September', 'jetpack'), __('October', 'jetpack'), __('November', 'jetpack'), __('December', 'jetpack') );
 		for( $i=0; $i<12; $i++ ) {
 			$html .= '<option value="' . esc_attr( $i ) . '">' . esc_html( $months[$i] )  . '</option>';

diff --git a/plugins/jetpack/modules/shortcodes/vimeo.php b/plugins/jetpack/modules/shortcodes/vimeo.php
index 02b417e..188c8e2 100644
--- a/plugins/jetpack/modules/shortcodes/vimeo.php
+++ b/plugins/jetpack/modules/shortcodes/vimeo.php
@@ -9,6 +9,20 @@
 <iframe src="http://player.vimeo.com/video/18427511" width="400" height="225" frameborder="0"></iframe><p><a href="http://vimeo.com/18427511">Eskmo 'We Got More' (Official Video)</a> from <a href="http://vimeo.com/ninjatune">Ninja Tune</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
 */
 
+function jetpack_shortcode_get_vimeo_id( $atts ) {
+	if ( isset( $atts[0] ) ) {
+		$atts[0] = trim( $atts[0] , '=' );
+		if ( is_numeric( $atts[0] ) )
+			$id = (int) $atts[0];
+		elseif ( preg_match( '|vimeo\.com/(\d+)/?$|i', $atts[0], $match ) )
+			$id = (int) $match[1];
+		elseif ( preg_match( '|player\.vimeo\.com/video/(\d+)/?$|i', $atts[0], $match ) )
+			$id = (int) $match[1];
+		return $id;
+	}
+	return 0;
+}
+
 /**
  * Convert a Vimeo shortcode into an embed code.
  *
@@ -24,13 +38,10 @@ function vimeo_shortcode( $atts ) {
 		'height' => 300
 	), $atts ) ) );
 
-	if ( isset( $atts[0] ) ) {
-		$atts[0] = trim( $atts[0] , '=' );
-		if ( is_numeric( $atts[0] ) )
-			$id = (int) $atts[0];
-		elseif ( preg_match( '|vimeo\.com/(\d+)/?$|i', $atts[0], $match ) )
-			$id = (int) $match[1];
-	}
+	if ( isset( $atts[0] ) )
+		$id = jetpack_shortcode_get_vimeo_id( $atts );
+
+	if ( ! $id ) return "<!-- vimeo error: not a vimeo video -->";
 
 	// [vimeo 141358 h=500&w=350]
 	$params = shortcode_new_to_old_params( $atts ); // h=500&w=350
@@ -61,8 +72,6 @@ function vimeo_shortcode( $atts ) {
 	if ( ! $height )
 		$height = round( ( $width / 640 ) * 360 );
 
-	if ( ! $id ) return "<!-- vimeo error: not a vimeo video -->";
-
 	$html = "<div class='embed-vimeo' style='text-align:center;'><iframe src='http://player.vimeo.com/video/$id' width='$width' height='$height' frameborder='0'></iframe></div>";
 	$html = apply_filters( 'video_embed_html', $html );
 	return $html;

diff --git a/plugins/jetpack/modules/shortcodes/youtube.php b/plugins/jetpack/modules/shortcodes/youtube.php
index 74c497e..df50af1 100644
--- a/plugins/jetpack/modules/shortcodes/youtube.php
+++ b/plugins/jetpack/modules/shortcodes/youtube.php
@@ -41,6 +41,11 @@ function youtube_embed_to_short_code( $content ) {
 	$ifr_regexp = '!<iframe((?:\s+\w+="[^"]*")*?)\s+src="https?://(?:www\.)*youtube.com/embed/([^"]+)".*?</iframe>!i';
 	$ifr_regexp_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $ifr_regexp, ENT_NOQUOTES ) );
 
+	if ( is_ssl() )
+		$protocol = 'https';
+	else
+		$protocol = 'http';
+
 	foreach ( array( 'regexp', 'regexp_ent', 'old_regexp', 'old_regexp_ent', 'ifr_regexp', 'ifr_regexp_ent' ) as $reg ) {
 		if ( ! preg_match_all( $$reg, $content, $matches, PREG_SET_ORDER ) )
 			continue;
@@ -69,11 +74,11 @@ function youtube_embed_to_short_code( $content ) {
 				if ( $width && $height )
 					$wh = "&w=$width&h=$height";
 
-				$url = esc_url_raw( "http://www.youtube.com/watch?v={$match[2]}{$wh}" );
+				$url = esc_url_raw( "$protocol://www.youtube.com/watch?v={$match[2]}{$wh}" );
 			} else {
 				$match[1] = str_replace( '?', '&', $match[1] );
 
-				$url = esc_url_raw( 'http://www.youtube.com/watch?v=' . html_entity_decode( $match[1] ) );
+				$url = esc_url_raw( "$protocol://www.youtube.com/watch?v=" . html_entity_decode( $match[1] ) );
 			}
 
 			$content = str_replace( $match[0], "[youtube $url]", $content );
@@ -94,7 +99,7 @@ add_filter('pre_kses', 'youtube_embed_to_short_code');
  * @return string The content with embeds instead of URLs
  */
 function youtube_link( $content ) {
-	return preg_replace_callback( '!(?:\n|\A)http://(?:www\.)?(?:youtube.com/(?:v/|playlist|watch[/\#?])|youtu\.be/)[^\s]+?(?:\n|\Z)!i', 'youtube_link_callback', $content );
+	return preg_replace_callback( '!(?:\n|\A)https?://(?:www\.)?(?:youtube.com/(?:v/|playlist|watch[/\#?])|youtu\.be/)[^\s]+?(?:\n|\Z)!i', 'youtube_link_callback', $content );
 }
 
 /**
@@ -137,7 +142,23 @@ function youtube_sanitize_url( $url ) {
  *    http://youtu.be/Rrohlqeir5E
  */
 
+/**
+ * Same as get_youtube_id(), but with the prefix that function should've had.
+ */
+function jetpack_shortcode_get_youtube_id( $url ) {
+	return get_youtube_id( $url );
+}
+
+/**
+ * @param $url Can be just the $url or the whole $atts array
+ * @return bool|mixed The Youtube video ID
+ */
 function get_youtube_id( $url ) {
+
+	// Do we have an $atts array?  Get first att
+	if ( is_array( $url ) )
+		$url = $url[0];
+
 	$url = youtube_sanitize_url( $url );
 	$url = parse_url( $url );
 	$id  = false;
@@ -225,10 +246,15 @@ function youtube_id( $url ) {
 
 	$fmt =    ( isset( $qargs['fmt'] )            && intval( $qargs['fmt'] )       ) ? '&fmt=' . (int) $qargs['fmt']     : '';
 	$start =  ( isset( $qargs['start'] )          && intval( $qargs['start'] )     ) ? '&start=' . (int) $qargs['start'] : '';
+	$end =    ( isset( $qargs['end'] )            && intval( $qargs['end'] )       ) ? '&end=' . (int) $qargs['end'] : '';
 	$hd =     ( isset( $qargs['hd'] )             && intval( $qargs['hd'] )        ) ? '&hd=' . (int) $qargs['hd']       : '';
 
 	$wmode =  ( isset( $qargs['wmode'] ) && in_array( strtolower( $qargs['wmode'] ), array( 'opaque', 'window', 'transparent' ) ) ) ? $qargs['wmode'] : 'transparent';
 
+	$autoplay = '';
+	if ( apply_filters( 'jetpack_youtube_allow_autoplay', false ) && isset( $qargs['autoplay'] ) )
+		$autoplay = '&autoplay=' . (int)$qargs['autoplay'];
+
 	$alignmentcss = 'text-align:center;';
 	if ( isset( $qargs['align'] ) ) {
 		switch ( $qargs['align'] ) {
@@ -241,10 +267,15 @@ function youtube_id( $url ) {
 		}
 	}
 
+	if ( is_ssl() )
+		$protocol = 'https';
+	else
+		$protocol = 'http';
+
 	if ( ( isset( $url['path'] ) && '/videoseries' == $url['path'] ) || isset( $qargs['list'] ) ) {
-		$html = "<span class='embed-youtube' style='$alignmentcss display: block;'><iframe class='youtube-player' type='text/html' width='$w' height='$h' src='" . esc_url( "http://www.youtube.com/embed/videoseries?list=$id&hl=en_US" ) . "' frameborder='0'></iframe></span>";
+		$html = "<span class='embed-youtube' style='$alignmentcss display: block;'><iframe class='youtube-player' type='text/html' width='$w' height='$h' src='" . esc_url( "$protocol://www.youtube.com/embed/videoseries?list=$id&hl=en_US" ) . "' frameborder='0'></iframe></span>";
 	} else {
-		$html = "<span class='embed-youtube' style='$alignmentcss display: block;'><iframe class='youtube-player' type='text/html' width='$w' height='$h' src='" . esc_url( "http://www.youtube.com/embed/$id?version=3&rel=$rel&fs=1$fmt&showsearch=$search&showinfo=$info&iv_load_policy=$iv$start$hd&wmode=$wmode" ) . "' frameborder='0'></iframe></span>";
+		$html = "<span class='embed-youtube' style='$alignmentcss display: block;'><iframe class='youtube-player' type='text/html' width='$w' height='$h' src='" . esc_url( "$protocol://www.youtube.com/embed/$id?version=3&rel=$rel&fs=1$fmt&showsearch=$search&showinfo=$info&iv_load_policy=$iv$start$end$hd&wmode=$wmode$autoplay" ) . "' frameborder='0'></iframe></span>";
 	}
 
 	$html = apply_filters( 'video_embed_html', $html );
@@ -267,7 +298,7 @@ function wpcom_youtube_embed_crazy_url( $matches, $attr, $url ) {
 }
 
 function wpcom_youtube_embed_crazy_url_init() {
-	wp_embed_register_handler( 'wpcom_youtube_embed_crazy_url', '#http://(?:www\.)?(?:youtube.com/(?:v/|playlist|watch[/\#?])|youtu\.be/).*#i', 'wpcom_youtube_embed_crazy_url' );
+	wp_embed_register_handler( 'wpcom_youtube_embed_crazy_url', '#https?://(?:www\.)?(?:youtube.com/(?:v/|playlist|watch[/\#?])|youtu\.be/).*#i', 'wpcom_youtube_embed_crazy_url' );
 }
 
 add_action( 'init', 'wpcom_youtube_embed_crazy_url_init' );

diff --git a/plugins/jetpack/modules/shortlinks.php b/plugins/jetpack/modules/shortlinks.php
index 98ec743..731a5c3 100644
--- a/plugins/jetpack/modules/shortlinks.php
+++ b/plugins/jetpack/modules/shortlinks.php
@@ -4,6 +4,7 @@
  * Module Description: Enable WP.me-powered shortlinks for all of your Posts and Pages for easier sharing.
  * Sort Order: 10
  * First Introduced: 1.1
+ * Requires Connection: Yes
  */
 
 add_filter( 'get_shortlink', 'wpme_get_shortlink_handler', 1, 4 );

diff --git a/plugins/jetpack/modules/stats.php b/plugins/jetpack/modules/stats.php
index 260b3f5..3ca38dd 100644
--- a/plugins/jetpack/modules/stats.php
+++ b/plugins/jetpack/modules/stats.php
@@ -4,13 +4,14 @@
  * Module Description: Simple, concise site stats with no additional load on your server.
  * Sort Order: 1
  * First Introduced: 1.1
+ * Requires Connection: Yes
  */
 
 if ( defined( 'STATS_VERSION' ) ) {
 	return;
 }
 
-define( 'STATS_VERSION', '8' );
+define( 'STATS_VERSION', '9' );
 defined( 'STATS_DASHBOARD_SERVER' ) or define( 'STATS_DASHBOARD_SERVER', 'dashboard.wordpress.com' );
 
 add_action( 'jetpack_modules_loaded', 'stats_load' );
@@ -51,6 +52,8 @@ function stats_load() {
 
 	add_action( 'wp_head', 'stats_admin_bar_head', 100 );
 
+	add_action( 'wp_head', 'stats_hide_smile_css' );
+
 	add_action( 'jetpack_admin_menu', 'stats_admin_menu' );
 
 	add_action( 'wp_dashboard_setup', 'stats_register_dashboard_widget' );
@@ -85,7 +88,6 @@ function stats_ignore_db_version( $version ) {
  * @return array Possibly mapped capabilities for meta capability
  */
 function stats_map_meta_caps( $caps, $cap, $user_id, $args ) {
-
 	// Map view_stats to exists
 	if ( 'view_stats' == $cap ) {
 		$user        = new WP_User( $user_id );
@@ -108,11 +110,13 @@ function stats_template_redirect() {
 		return;
 
 	$options = stats_get_options();
-	// Ensure this is always setup for the check below
-	$options['reg_users'] = empty( $options['reg_users'] ) ? false : true;
 
-	if ( !$options['reg_users'] && !empty( $current_user->ID ) )
-		return;
+	// Should we be counting this user's views?
+	if ( !empty( $current_user->ID ) ) {
+		$count_roles = stats_get_option( 'count_roles' );
+		if ( ! array_intersect( $current_user->roles, $count_roles ) )
+			return;
+	}
 
 	add_action( 'wp_footer', 'stats_footer', 101 );
 	add_action( 'wp_head', 'stats_add_shutdown_action' );
@@ -154,9 +158,6 @@ function stats_template_redirect() {
 	else load_cmc();
 	</script>
 END;
-	if ( isset( $options['hide_smile'] ) && $options['hide_smile'] ) {
-		$stats_footer .= "\n<style type='text/css'>img#wpstats{display:none}</style>";
-	}
 }
 
 function stats_add_shutdown_action() {
@@ -207,11 +208,20 @@ function stats_upgrade_options( $options ) {
 	$defaults = array(
 		'admin_bar'    => true,
 		'roles'        => array( 'administrator' ),
+		'count_roles'  => array(),
 		'blog_id'      => Jetpack::get_option( 'id' ),
 		'do_not_track' => true, // @todo
 		'hide_smile'   => false,
 	);
 
+	if ( isset( $options['reg_users'] ) ) {
+		if ( ! function_exists( 'get_editable_roles' ) )
+			require_once( ABSPATH . 'wp-admin/includes/user.php' );
+		if ( $options['reg_users'] )
+			$options['count_roles'] = array_keys( get_editable_roles() );
+		unset( $options['reg_users'] );
+	}
+
 	if ( is_array( $options ) && !empty( $options ) )
 		$new_options = array_merge( $defaults, $options );
 	else
@@ -447,7 +457,7 @@ function stats_convert_image_urls( $html ) {
 }
 
 function stats_convert_chart_urls( $html ) {
-	$html = preg_replace_callback( '|https?://[-.a-z0-9]+/wp-includes/charts/([-.a-z0-9]+).php(\??)|', 
+	$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
@@ -486,7 +496,6 @@ function stats_configuration_load() {
 	if ( isset( $_POST['action'] ) && $_POST['action'] == 'save_options' && $_POST['_wpnonce'] == wp_create_nonce( 'stats' ) ) {
 		$options = stats_get_options();
 		$options['admin_bar']  = isset( $_POST['admin_bar']  ) && $_POST['admin_bar'];
-		$options['reg_users']  = isset( $_POST['reg_users']  ) && $_POST['reg_users'];
 		$options['hide_smile'] = isset( $_POST['hide_smile'] ) && $_POST['hide_smile'];
 
 		$options['roles'] = array( 'administrator' );
@@ -494,6 +503,11 @@ function stats_configuration_load() {
 			if ( isset( $_POST["role_$role"] ) && $_POST["role_$role"] )
 				$options['roles'][] = $role;
 
+		$options['count_roles'] = array();
+		foreach ( get_editable_roles() as $role => $details )
+			if ( isset( $_POST["count_role_$role"] ) && $_POST["count_role_$role"] )
+				$options['count_roles'][] = $role;
+
 		stats_set_options( $options );
 		stats_update_blog();
 		Jetpack::state( 'message', 'module_configured' );
@@ -519,7 +533,6 @@ function stats_configuration_head() {
 
 function stats_configuration_screen() {
 	$options = stats_get_options();
-	$options['reg_users'] = empty( $options['reg_users'] ) ? false : true;
 	?>
 	<div class="narrow">
 		<p><?php printf( __( 'Visit <a href="%s">Site Stats</a> to see your stats.', 'jetpack' ), esc_url( menu_page_url( 'stats', false ) ) ); ?></p>
@@ -529,8 +542,18 @@ function stats_configuration_screen() {
 		<table id="menu" class="form-table">
 		<tr valign="top"><th scope="row"><label for="admin_bar"><?php _e( 'Admin bar' , 'jetpack' ); ?></label></th>
 		<td><label><input type='checkbox'<?php checked( $options['admin_bar'] ); ?> name='admin_bar' id='admin_bar' /> <?php _e( "Put a chart showing 48 hours of views in the admin bar.", 'jetpack' ); ?></label></td></tr>
-		<tr valign="top"><th scope="row"><label for="reg_users"><?php _e( 'Registered users', 'jetpack' ); ?></label></th>
-		<td><label><input type='checkbox'<?php checked( $options['reg_users'] ); ?> name='reg_users' id='reg_users' /> <?php _e( "Count the page views of registered users who are logged in.", 'jetpack' ); ?></label></td></tr>
+		<tr valign="top"><th scope="row"><?php _e( 'Registered users', 'jetpack' ); ?></th>
+		<td>
+			<?php _e( "Count the page views of registered users who are logged in.", 'jetpack' ); ?><br/>
+			<?php
+			$count_roles = stats_get_option( 'count_roles' );
+			foreach ( get_editable_roles() as $role => $details ) {
+				?>
+				<label><input type='checkbox' name='count_role_<?php echo $role; ?>'<?php checked( in_array( $role, $count_roles ) ); ?> /> <?php echo translate_user_role( $details['name'] ); ?></label><br/>
+				<?php
+			}
+			?>
+		</td></tr>
 		<tr valign="top"><th scope="row"><?php _e( 'Smiley' , 'jetpack' ); ?></th>
 		<td><label><input type='checkbox'<?php checked( isset( $options['hide_smile'] ) && $options['hide_smile'] ); ?> name='hide_smile' id='hide_smile' /> <?php _e( 'Hide the stats smiley face image.', 'jetpack' ); ?></label><br /> <span class="description"><?php _e( 'The image helps collect stats and <strong>makes the world a better place</strong> but should still work when hidden', 'jetpack' ); ?> <img class="stats-smiley" alt="<?php esc_attr_e( 'Smiley face', 'jetpack' ); ?>" src="<?php echo esc_url( plugins_url( '_inc/images/stats-smiley.gif', dirname( __FILE__ ) ) ); ?>" width="6" height="5" /></span></td></tr>
 		<tr valign="top"><th scope="row"><?php _e( 'Report visibility' , 'jetpack' ); ?></th>
@@ -544,7 +567,7 @@ function stats_configuration_screen() {
 				<?php
 			}
 			?>
-		</tr>
+		</td></tr>
 		</table>
 		<p class="submit"><input type='submit' class='button-primary' value='<?php echo esc_attr( __( 'Save configuration', 'jetpack' ) ); ?>' /></p>
 		</form>
@@ -552,6 +575,14 @@ function stats_configuration_screen() {
 	<?php
 }
 
+function stats_hide_smile_css() {
+	$options = stats_get_options();
+	if ( isset( $options['hide_smile'] ) && $options['hide_smile'] ) {
+	?>
+<style type='text/css'>img#wpstats{display:none}</style><?php
+	}
+}
+
 function stats_admin_bar_head() {
 	if ( !stats_get_option( 'admin_bar' ) )
 		return;
@@ -889,15 +920,23 @@ function stats_dashboard_widget_content() {
 	/* translators: Stats dashboard widget postviews list: "$post_title $views Views" */
 	$printf = __( '%1$s %2$s Views' , 'jetpack' );
 
-	foreach ( $top_posts = stats_get_csv( 'postviews', "days=$options[top]$csv_args[top]" ) as $post )
+	foreach ( $top_posts = stats_get_csv( 'postviews', "days=$options[top]$csv_args[top]" ) as $i => $post ) {
+		if ( $post['post_id'] == 0 ) {
+			unset( $top_posts[$i] );
+			continue;
+		}
 		$post_ids[] = $post['post_id'];
+	}
 
 	// cache
 	get_posts( array( 'include' => join( ',', array_unique( $post_ids ) ) ) );
 
 	$searches = array();
-	foreach ( $search_terms = stats_get_csv( 'searchterms', "days=$options[search]$csv_args[search]" ) as $search_term )
+	foreach ( $search_terms = stats_get_csv( 'searchterms', "days=$options[search]$csv_args[search]" ) as $search_term ) {
+		if ( $search_term['searchterm'] == 'encrypted_search_terms' )
+			continue;
 		$searches[] = esc_html( $search_term['searchterm'] );
+	}
 
 ?>
 <a class="button" href="admin.php?page=stats"><?php _e( 'View All', 'jetpack' ); ?></a>

diff --git a/plugins/jetpack/modules/subscriptions.php b/plugins/jetpack/modules/subscriptions.php
index 39c639f..22366d0 100644
--- a/plugins/jetpack/modules/subscriptions.php
+++ b/plugins/jetpack/modules/subscriptions.php
@@ -4,10 +4,11 @@
  * Module Description: Allow users to subscribe to your posts and comments to receive a notification via email.
  * Sort Order: 3
  * First Introduced: 1.2
+ * Requires Connection: Yes
  */
 
 add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
- 
+
 Jetpack_Sync::sync_options( __FILE__,
 	'home',
 	'blogname',
@@ -42,7 +43,7 @@ class Jetpack_Subscriptions {
 	 * Singleton
 	 * @static
 	 */
-	function init() {
+	static function init() {
 		static $instance = false;
 
 		if ( !$instance ) {
@@ -101,7 +102,7 @@ class Jetpack_Subscriptions {
 	 *
 	 * Jetpack Subscriptions configuration screen.
 	 */
-	function configure() {	
+	function configure() {
 		// Create the section
 		add_settings_section(
 			'jetpack_subscriptions',
@@ -139,37 +140,37 @@ class Jetpack_Subscriptions {
 			'discussion',
 			'stc_enabled'
 		);
-		
+
 		/** Subscription Messaging Options ******************************************************/
-		
-		register_setting( 
-			'reading', 
-			'subscription_options', 
-			array( $this, 'validate_settings' ) 
+
+		register_setting(
+			'reading',
+			'subscription_options',
+			array( $this, 'validate_settings' )
 		);
 
-		add_settings_section( 
-			'email_settings', 
-			__( 'Follower Settings', 'jetpack' ), 
-			array( $this, 'reading_section' ), 
+		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', 
+			__( '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', 
+			__( 'Comment follow email text', 'jetpack' ),
+			array( $this, 'setting_comment_follow' ),
+			'reading',
 			'email_settings'
-		);		
+		);
 	}
 
 	/**
@@ -255,11 +256,11 @@ class Jetpack_Subscriptions {
 			'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()
 	 *
@@ -658,7 +659,7 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
 		return $instance;
 	}
 
-	function defaults() {
+	public static function defaults() {
 		return array(
 			'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' ),
@@ -680,7 +681,7 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
 
 		if ( 'failed' == $subs_fetch['status'] ) {
 			printf( '<div class="error inline"><p>' . __( '%s: %s', 'jetpack' ) . '</p></div>', esc_html( $subs_fetch['code'] ), esc_html( $subs_fetch['message'] ) );
-			
+
 		}
 		$subscribers_total = number_format_i18n( $subs_fetch['value'] );
 
@@ -706,7 +707,7 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
 <p>
 	<label for="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>">
 		<input type="checkbox" id="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>" name="<?php echo $this->get_field_name( 'show_subscribers_total' ); ?>" value="1"<?php echo $show_subscribers_total; ?> />
-		<?php echo esc_html( sprintf( _n( 'Show total number of subscribers? (%s subscriber)', 'Show total number of subscribers? (%s subscribers)', $subscribers_total, 'jetpack' ), number_format_i18n( $subscribers_total ) ) ); ?>
+		<?php echo esc_html( sprintf( _n( 'Show total number of subscribers? (%s subscriber)', 'Show total number of subscribers? (%s subscribers)', $subscribers_total, 'jetpack' ), $subscribers_total ) ); ?>
 	</label>
 </p>
 <?php

diff --git a/plugins/jetpack/modules/tiled-gallery.php b/plugins/jetpack/modules/tiled-gallery.php
index 6db8714..f88cc68 100644
--- a/plugins/jetpack/modules/tiled-gallery.php
+++ b/plugins/jetpack/modules/tiled-gallery.php
@@ -4,6 +4,7 @@
  * 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
+ * Requires Connection: Yes
  */
 
 function jetpack_load_tiled_gallery() {

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
index dab5fd2..f2cf2e5 100644
--- a/plugins/jetpack/modules/tiled-gallery/math/class-constrained-array-rounding.php
+++ b/plugins/jetpack/modules/tiled-gallery/math/class-constrained-array-rounding.php
@@ -2,7 +2,7 @@
 
 /**
  * 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 )
@@ -20,14 +20,14 @@ class Jetpack_Constrained_Array_Rounding {
 		$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' );

diff --git a/plugins/jetpack/modules/tiled-gallery/tiled-gallery.php b/plugins/jetpack/modules/tiled-gallery/tiled-gallery.php
index 342e8a6..7855da8 100644
--- a/plugins/jetpack/modules/tiled-gallery/tiled-gallery.php
+++ b/plugins/jetpack/modules/tiled-gallery/tiled-gallery.php
@@ -9,6 +9,7 @@ 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 );
+		add_filter( 'jetpack_default_gallery_type', array( $this, 'jetpack_default_gallery_type' ) );
 	}
 
 	public function tiles_enabled() {
@@ -213,7 +214,15 @@ class Jetpack_Tiled_Gallery {
 
 		$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 ) ) );
+
+		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+			$likes_blog_id = $blog_id;
+		} else {
+			$jetpack = Jetpack::init();
+			$likes_blog_id = $jetpack->get_option( 'id' );
+		}
+
+		$extra_data = array( 'data-carousel-extra' => array( 'blog_id' => $blog_id, 'permalink' => get_permalink( $post->ID ), 'likes_blog_id' => $likes_blog_id ) );
 
 		foreach ( (array) $extra_data as $data_key => $data_values ) {
 			$html = str_replace( '<div ', '<div ' . esc_attr( $data_key ) . "='" . json_encode( $data_values ) . "' ", $html );
@@ -264,7 +273,7 @@ class Jetpack_Tiled_Gallery {
 	}
 
 	public function gallery_classes() {
-		$classes = 'class="tiled-gallery type-' . esc_attr( $this->atts['type'] ) . '"';
+		$classes = 'class="tiled-gallery type-' . esc_attr( $this->atts['type'] ) . ' tiled-gallery-unresized"';
 		return $classes;
 	}
 
@@ -283,9 +292,7 @@ class Jetpack_Tiled_Gallery {
 	}
 
 	public static function get_content_width() {
-		global $content_width;
-
-		$tiled_gallery_content_width = $content_width;
+		$tiled_gallery_content_width = Jetpack::get_content_width();
 
 		if ( ! $tiled_gallery_content_width )
 			$tiled_gallery_content_width = 500;
@@ -297,12 +304,24 @@ class Jetpack_Tiled_Gallery {
 	 * Media UI integration
 	 */
 	function jetpack_gallery_types( $types ) {
-		$types['rectangular'] = __( 'Tiles', 'jetpack' );
+		if ( get_option( 'tiled_galleries' ) && isset( $types['default'] ) ) {
+			// Tiled is set as the default, meaning that type='default'
+			// will still display the mosaic.
+			$types['thumbnails'] = $types['default'];
+			unset( $types['default'] );
+		}
+
+		$types['rectangular'] = __( 'Tiled Mosaic', 'jetpack' );
 		$types['square'] = __( 'Square Tiles', 'jetpack' );
 		$types['circle'] = __( 'Circles', 'jetpack' );
+
 		return $types;
 	}
 
+	function jetpack_default_gallery_type( $default ) {
+		return ( get_option( 'tiled_galleries' ) ? 'rectangular' : 'default' );
+	}
+
 	/**
 	 * Add a checkbox field to the Carousel section in Settings > Media
 	 * for setting tiled galleries as the default.
@@ -348,8 +367,7 @@ class Jetpack_Tiled_Gallery_Shape {
 	}
 
 	public function is_wide_theme() {
-		global $content_width;
-		return $content_width > 1000;
+		return Jetpack::get_content_width() > 1000;
 	}
 
 	public static function set_last_shape( $last_shape ) {

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
index 007c0cc..a6b7aef 100644
--- 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
@@ -1,4 +1,4 @@
-/* This file was automatically generated on Jan 05 2013 15:45:53 */
+/* This file was automatically generated on Jul 03 2013 18:11:40 */
 
 /* =Tiled Gallery Default Styles
 -------------------------------------------------------------- */
@@ -13,13 +13,13 @@
 }
 .tiled-gallery .gallery-group {
 	float: right;
-	overflow-y: hidden;
 	position: relative;
 }
 .tiled-gallery .tiled-gallery-item {
 	float: right;
 	margin: 0;
 	position: relative;
+	width: inherit; /* prevents ie8 bug with inline width styles */
 }
 .tiled-gallery .gallery-row {
 	 overflow: hidden;
@@ -62,6 +62,14 @@
 	font-size: 11px;
 }
 
+/* Hide galleries in widgets until they've been resized to fit.
+   Gallery widgets are almost guaranteed to need resizing, and
+   the jump is a little more obvious than galleries in content. */
+.widget-gallery .tiled-gallery-unresized {
+	visibility: hidden;
+	height: 0px;
+	overflow: hidden;
+}
 
 /* =Greyscale
 -------------------------------------------------------------- */
@@ -85,4 +93,5 @@
 .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
index 3a1924d..c80a5b0 100644
--- a/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.css
+++ b/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.css
@@ -17,6 +17,7 @@
 	float: left;
 	margin: 0;
 	position: relative;
+	width: inherit; /* prevents ie8 bug with inline width styles */
 }
 .tiled-gallery .gallery-row {
 	 overflow: hidden;
@@ -59,6 +60,14 @@
 	font-size: 11px;
 }
 
+/* Hide galleries in widgets until they've been resized to fit.
+   Gallery widgets are almost guaranteed to need resizing, and
+   the jump is a little more obvious than galleries in content. */
+.widget-gallery .tiled-gallery-unresized {
+	visibility: hidden;
+	height: 0px;
+	overflow: hidden;
+}
 
 /* =Greyscale
 -------------------------------------------------------------- */
@@ -82,4 +91,5 @@
 .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
index 90f8ed7..bedb5b5 100644
--- a/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.js
+++ b/plugins/jetpack/modules/tiled-gallery/tiled-gallery/tiled-gallery.js
@@ -9,13 +9,13 @@ var TiledGallery = function() {
 
 	$( 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 ) );
 
@@ -51,9 +51,10 @@ TiledGallery.prototype.Captions = function() {
 	/* Hide captions */
 	this.caption.hide();
 
-	this.item.on( 'hover', function() {
-		$( this ).find( '.tiled-gallery-caption' ).slideToggle( 'fast' );
-	});
+	this.item.hover(
+		function() { $( this ).find( '.tiled-gallery-caption' ).slideDown( 'fast' ); },
+		function() { $( this ).find( '.tiled-gallery-caption' ).slideUp( 'fast' ); }
+	);
 };
 
 TiledGallery.prototype.resize = function() {
@@ -61,7 +62,7 @@ TiledGallery.prototype.resize = function() {
 
 	this.gallery.each( function ( galleryIndex, galleryElement ) {
 		var thisGallery = $( galleryElement );
-		
+
 		// All images must be loaded before proceeding.
 		var imagesLoaded = true;
 
@@ -134,6 +135,8 @@ TiledGallery.prototype.resize = function() {
 				.width( Math.floor( resizeRatio * thisGalleryElement.data( 'original-width' ) ) - thisGalleryElement.data( 'extra-width' ) )
 				.height( Math.floor( resizeRatio * thisGalleryElement.data( 'original-height' ) ) - thisGalleryElement.data( 'extra-height' ) );
 		} );
+
+		thisGallery.removeClass( 'tiled-gallery-unresized' );
 	} );
 };
 

diff --git a/plugins/jetpack/modules/vaultpress.php b/plugins/jetpack/modules/vaultpress.php
index a9b809c..7766f53 100644
--- a/plugins/jetpack/modules/vaultpress.php
+++ b/plugins/jetpack/modules/vaultpress.php
@@ -1,4 +1,4 @@
-<?php 
+<?php
 /**
  * Module Name: VaultPress
  * Module Description: Realtime backup and security scanning for your WordPress site.
@@ -6,6 +6,7 @@
  * Sort Order: 7
  * Deactivate: false
  * Free: false
+ * Requires Connection: Yes
  */
 
 add_action( 'jetpack_modules_loaded', 'vaultpress_jetpack_stub' );
@@ -16,7 +17,7 @@ function vaultpress_jetpack_stub() {
 		Jetpack::module_configuration_load( __FILE__, 'vaultpress_jetpack_configure' );
 		add_filter( 'jetpack_module_free_text_vaultpress', 'vaultpress_jetpack_module_free_text' );
 	}
-}	
+}
 
 function vaultpress_jetpack_module_free_text() {
 	return __( 'Active', 'jetpack' );

diff --git a/plugins/jetpack/modules/widgets.php b/plugins/jetpack/modules/widgets.php
index 5771cdb..4d0f509 100644
--- a/plugins/jetpack/modules/widgets.php
+++ b/plugins/jetpack/modules/widgets.php
@@ -4,11 +4,20 @@
  * Module Description: Easily add images, Twitter updates, and your site's RSS links to your theme's sidebar.
  * Sort Order: 13
  * First Introduced: 1.2
+ * Requires Connection: No
  */
 
 function jetpack_load_widgets() {
+	$widgets_include = array();
+
 	foreach ( Jetpack::glob_php( dirname( __FILE__ ) . '/widgets' ) as $file ) {
-		include $file;
+		$widgets_include[] = $file;
+	}
+
+	$widgets_include = apply_filters( 'jetpack_widgets_to_include', $widgets_include );
+
+	foreach( $widgets_include as $include ) {
+		include $include;
 	}
 }
 

diff --git a/plugins/jetpack/modules/widgets/facebook-likebox.php b/plugins/jetpack/modules/widgets/facebook-likebox.php
index f8ab251..8cb7e02 100644
--- a/plugins/jetpack/modules/widgets/facebook-likebox.php
+++ b/plugins/jetpack/modules/widgets/facebook-likebox.php
@@ -37,11 +37,11 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 	}
 
 	function widget( $args, $instance ) {
-		
+
 		extract( $args );
-		
+
 		$like_args = $this->normalize_facebook_args( $instance['like_args'] );
-		
+
 		if ( empty( $like_args['href'] ) || ! $this->is_valid_facebook_url( $like_args['href'] ) ) {
 			if ( current_user_can('edit_theme_options') ) {
 				echo $before_widget;
@@ -51,7 +51,7 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 			echo '<!-- Invalid Facebook Page URL -->';
 			return;
 		}
-		
+
 
 		$title    = apply_filters( 'widget_title', $instance['title'] );
 		$page_url = ( is_ssl() ) ? str_replace( 'http://', 'https://', $like_args['href'] ) : $like_args['href'];
@@ -59,16 +59,17 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 		$like_args['show_faces'] = (bool) $like_args['show_faces']         ? 'true' : 'false';
 		$like_args['stream']     = (bool) $like_args['stream']             ? 'true' : 'false';
 		$like_args['force_wall'] = (bool) $like_args['force_wall']         ? 'true' : 'false';
+		$like_args['show_border']= (bool) $like_args['show_border']        ? 'true' : 'false';
 		$like_args['header']     = (bool) $like_args['header']             ? 'true' : 'false';
-		$like_bg_colour          = ( 'dark' == $like_args['colorscheme'] ) ? '#000' : '#fff';
-		
+		$like_bg_colour          = apply_filters( 'jetpack_fb_likebox_bg', ( 'dark' == $like_args['colorscheme'] ? '#000' : '#fff' ), $like_args['colorscheme'] );
+
 		$locale = $this->get_locale();
 		if ( $locale && 'en_US' != $locale )
 			$like_args['locale'] = $locale;
 
 		$like_args = urlencode_deep( $like_args );
 		$like_url  = add_query_arg( $like_args,  sprintf( '%swww.facebook.com/plugins/likebox.php', ( is_ssl() ) ? 'https://' : 'http://' ) );
-		
+
 		echo $before_widget;
 
 		if ( ! empty( $title ) ) :
@@ -85,13 +86,13 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 	}
 
 	function update( $new_instance, $old_instance ) {
-		$instance = array( 
+		$instance = array(
 			'title' => '',
 			'like_args' => $this->get_default_args(),
 		);
 
 		$instance['title'] = trim( strip_tags( stripslashes( $new_instance['title'] ) ) );
-		
+
 		// Set up widget values
 		$instance['like_args'] = array(
 			'href'        => trim( strip_tags( stripslashes( $new_instance['href'] ) ) ),
@@ -100,30 +101,31 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 			'colorscheme' => $new_instance['colorscheme'],
 			'show_faces'  => (bool) $new_instance['show_faces'],
 			'stream'      => (bool) $new_instance['stream'],
+			'show_border' => (bool) $new_instance['show_border'],
 			'header'      => false, // The header just displays "Find us on Facebook"; it's redundant with the title
 			'force_wall'  => (bool) $new_instance['force_wall'],
 		);
-		
+
 		$instance['like_args'] = $this->normalize_facebook_args( $instance['like_args'] );
 
 		return $instance;
 	}
 
 	function form( $instance ) {
-		$instance = wp_parse_args( (array) $instance, array( 
+		$instance = wp_parse_args( (array) $instance, array(
 			'title'     => '',
 			'like_args' => $this->get_default_args()
 		) );
 		$like_args = $this->normalize_facebook_args( $instance['like_args'] );
 		?>
-		
+
 		<p>
 			<label for="<?php echo $this->get_field_id( 'title' ); ?>">
 				<?php _e( 'Title', 'jetpack' ); ?>
 				<input type="text" name="<?php echo $this->get_field_name( 'title' ); ?>" id="<?php echo $this->get_field_id( 'title' ); ?>" value="<?php echo esc_attr( $instance['title'] ); ?>" class="widefat" />
 			</label>
 		</p>
-		
+
 		<p>
 			<label for="<?php echo $this->get_field_id( 'href' ); ?>">
 				<?php _e( 'Facebook Page URL', 'jetpack' ); ?>
@@ -132,21 +134,21 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 				<small><?php _e( 'The Like Box only works with <a href="http://www.facebook.com/help/?faq=174987089221178">Facebook Pages</a>.', 'jetpack' ); ?></small>
 			</label>
 		</p>
-		
+
 		<p>
 			<label for="<?php echo $this->get_field_id( 'width' ); ?>">
 				<?php _e( 'Width', 'jetpack' ); ?>
-				<input type="text" maxlength="3" name="<?php echo $this->get_field_name( 'width' ); ?>" id="<?php echo $this->get_field_id( 'width' ); ?>" value="<?php echo esc_attr( $like_args['width'] ); ?>" style="width: 30px; text-align: center;" />px
+				<input type="number" class="smalltext" min="1" max="999" maxlength="3" name="<?php echo $this->get_field_name( 'width' ); ?>" id="<?php echo $this->get_field_id( 'width' ); ?>" value="<?php echo esc_attr( $like_args['width'] ); ?>" style="text-align: center;" />px
 			</label>
 		</p>
 
 		<p>
 			<label for="<?php echo $this->get_field_id( 'height' ); ?>">
 				<?php _e( 'Height', 'jetpack' ); ?>
-				<input type="text" maxlength="3" name="<?php echo $this->get_field_name( 'height' ); ?>" id="<?php echo $this->get_field_id( 'height' ); ?>" value="<?php echo esc_attr( $like_args['height'] ); ?>" style="width: 30px; text-align: center;" />px
+				<input type="number" class="smalltext" min="1" max="999" maxlength="3" name="<?php echo $this->get_field_name( 'height' ); ?>" id="<?php echo $this->get_field_id( 'height' ); ?>" value="<?php echo esc_attr( $like_args['height'] ); ?>" style="text-align: center;" />px
 			</label>
 		</p>
-		
+
 		<p>
 			<label for="<?php echo $this->get_field_id( 'colorscheme' ); ?>">
 				<?php _e( 'Color Scheme', 'jetpack' ); ?>
@@ -156,8 +158,7 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 				</select>
 			</label>
 		</p>
-		
-		
+
 		<p>
 			<label for="<?php echo $this->get_field_id( 'show_faces' ); ?>">
 				<input type="checkbox" name="<?php echo $this->get_field_name( 'show_faces' ); ?>" id="<?php echo $this->get_field_id( 'show_faces' ); ?>" <?php checked( $like_args['show_faces'] ); ?> />
@@ -166,7 +167,7 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 				<small><?php _e( 'Show profile photos in the plugin.', 'jetpack' ); ?></small>
 			</label>
 		</p>
-		
+
 		<p>
 			<label for="<?php echo $this->get_field_id( 'stream' ); ?>">
 				<input type="checkbox" name="<?php echo $this->get_field_name( 'stream' ); ?>" id="<?php echo $this->get_field_id( 'stream' ); ?>" <?php checked( $like_args['stream'] ); ?> />
@@ -177,6 +178,15 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 		</p>
 
 		<p>
+			<label for="<?php echo $this->get_field_id( 'show_border' ); ?>">
+				<input type="checkbox" name="<?php echo $this->get_field_name( 'show_border' ); ?>" id="<?php echo $this->get_field_id( 'show_border' ); ?>" <?php checked( $like_args['show_border'] ); ?> />
+				<?php _e( 'Show Border', 'jetpack' ); ?>
+				<br />
+				<small><?php _e( 'Show a border around the plugin.', 'jetpack' ); ?></small>
+			</label>
+		</p>
+
+		<p>
 			<label for="<?php echo $this->get_field_id( 'force_wall' ); ?>">
 				<input type="checkbox" name="<?php echo $this->get_field_name( 'force_wall' ); ?>" id="<?php echo $this->get_field_id( 'force_wall' ); ?>" <?php checked( $like_args['force_wall'] ); ?> />
 				<?php _e( 'Show Wall', 'jetpack' ); ?>
@@ -184,10 +194,10 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 				<small><?php _e( 'Show the wall for a Places page rather than friend activity.', 'jetpack' ); ?></small>
 			</label>
 		</p>
-		
+
 		<?php
 	}
-	
+
 	function get_default_args() {
 		$defaults = array(
 			'href'        => '',
@@ -196,13 +206,14 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 			'colorscheme' => $this->default_colorscheme,
 			'show_faces'  => true,
 			'stream'      => false,
+			'show_border' => true,
 			'header'      => false,
 			'force_wall'  => false,
 		);
 
 		return apply_filters( 'jetpack_facebook_likebox_defaults', $defaults );
 	}
-	
+
 	function normalize_facebook_args( $args ) {
 		$args = wp_parse_args( (array) $args, $this->get_default_args() );
 
@@ -219,6 +230,7 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 		$args['colorscheme'] = $this->normalize_text_value( $args['colorscheme'], $this->default_colorscheme, $this->allowed_colorschemes        );
 		$args['show_faces']  = (bool) $args['show_faces'];
 		$args['stream']      = (bool) $args['stream'];
+		$args['show_border'] = (bool) $args['show_border'];
 		$args['force_wall']  = (bool) $args['force_wall'];
 
 		// The height used to be dependent on other widget settings
@@ -233,32 +245,32 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
 				$args['height'] = 432;
 			}
 		}
-		
+
 		return $args;
 	}
-	
+
 	function is_valid_facebook_url( $url ) {
 		return ( FALSE !== strpos( $url, 'facebook.com' ) ) ? TRUE : FALSE;
 	}
-	
+
 	function normalize_int_value( $value, $default = 0, $max = 0, $min = 0 ) {
 		$value = (int) $value;
-		
+
 		if ( $max < $value || $min > $value )
 			$value = $default;
-			
+
 		return (int) $value;
 	}
-	
+
 	function normalize_text_value( $value, $default = '', $allowed = array() ) {
 		$allowed = (array) $allowed;
-		
+
 		if ( empty( $value ) || ( ! empty( $allowed ) && ! in_array( $value, $allowed ) ) )
 			$value = $default;
-		
-		return $value; 
+
+		return $value;
 	}
-	
+
 	function guess_locale_from_lang( $lang ) {
 		if ( 'en' == $lang || 'en_US' == $lang || !$lang ) {
 			return 'en_US';

diff --git a/plugins/jetpack/modules/widgets/gravatar-profile.css b/plugins/jetpack/modules/widgets/gravatar-profile.css
index 1663ae0..9b1e70c 100644
--- a/plugins/jetpack/modules/widgets/gravatar-profile.css
+++ b/plugins/jetpack/modules/widgets/gravatar-profile.css
@@ -11,7 +11,7 @@
 			list-style: none;
 			display: inline;
 		}
-		
+
 		.widget-grofile ul.grofile-accounts li::before {
 			content: "" !important; /* Kubrick :( */
 		}

diff --git a/plugins/jetpack/modules/widgets/readmill.php b/plugins/jetpack/modules/widgets/readmill.php
index 7729ed3..2fe189e 100644
--- a/plugins/jetpack/modules/widgets/readmill.php
+++ b/plugins/jetpack/modules/widgets/readmill.php
@@ -44,7 +44,7 @@ class Jetpack_Readmill_Widget extends WP_Widget {
 		$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><?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>.", 'jetpack' ), '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>

diff --git a/plugins/jetpack/modules/widgets/rsslinks-widget.php b/plugins/jetpack/modules/widgets/rsslinks-widget.php
index 1530915..cd930cc 100644
--- a/plugins/jetpack/modules/widgets/rsslinks-widget.php
+++ b/plugins/jetpack/modules/widgets/rsslinks-widget.php
@@ -136,7 +136,7 @@ class Jetpack_RSS_Links_Widget extends WP_Widget {
 			$type_text = __( 'Comments', 'jetpack' );
 			$rss_type = 'comments_rss2_url';
 		}
-		
+
 		$subscribe_to = sprintf( __( 'Subscribe to %s', 'jetpack'), $type_text );
 
 		$link_item = '';

diff --git a/plugins/jetpack/modules/widgets/top-posts.php b/plugins/jetpack/modules/widgets/top-posts.php
index b6f2c8d..ec55fe7 100644
--- a/plugins/jetpack/modules/widgets/top-posts.php
+++ b/plugins/jetpack/modules/widgets/top-posts.php
@@ -57,7 +57,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
 		}
 
 		$count = isset( $instance['count'] ) ? (int) $instance['count'] : 10;
-		if ( $count < 1 || 20 < $count ) {
+		if ( $count < 1 || 10 < $count ) {
 			$count = 10;
 		}
 
@@ -75,8 +75,8 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
 		</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" />
+			<label for="<?php echo $this->get_field_id( 'count' ); ?>"><?php esc_html_e( 'Maximum number of posts to show (no more than 10):', 'jetpack' ); ?></label>
+			<input id="<?php echo $this->get_field_id( 'count' ); ?>" name="<?php echo $this->get_field_name( 'count' ); ?>" type="number" value="<?php echo (int) $count; ?>" min="1" max="10" />
 		</p>
 
 		<p>
@@ -101,7 +101,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
 		}
 
 		$instance['count'] = (int) $new_instance['count'];
-		if ( $instance['count'] < 1 || 20 < $instance['count'] ) {
+		if ( $instance['count'] < 1 || 10 < $instance['count'] ) {
 			$instance['count'] = 10;
 		}
 
@@ -121,7 +121,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
 		$title = apply_filters( 'widget_title', $title );
 
 		$count = isset( $instance['count'] ) ? (int) $instance['count'] : false;
-		if ( $count < 1 || 20 < $count ) {
+		if ( $count < 1 || 10 < $count ) {
 			$count = 10;
 		}
 
@@ -175,7 +175,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
 		case 'grid' :
 			wp_enqueue_style( 'widget-grid-and-list' );
 			foreach ( $posts as &$post ) {
-				$image = Jetpack_PostImages::get_image( $post['post_id'] );
+				$image = Jetpack_PostImages::get_image( $post['post_id'], array( 'fallback_to_avatars' => true ) );
 				$post['image'] = $image['src'];
 				if ( 'blavatar' != $image['from'] && 'gravatar' != $image['from'] ) {
 					$size = (int) $get_image_options['avatar_size'];
@@ -268,6 +268,10 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
 			if ( !$post )
 				continue;
 
+			// Only posts and pages, no attachments
+			if ( 'attachment' == $post->post_type )
+				continue;
+
 			// hide private and password protected posts
 			if ( 'publish' != $post->post_status || !empty( $post->post_password ) || empty( $post->ID ) )
 				continue;

diff --git a/plugins/jetpack/readme.txt b/plugins/jetpack/readme.txt
index f4808dd..c66fce3 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, pento, cfinke, daniloercoli, chellycat, gibrown, jblz, jshreve, barry, alternatekev, azaozz, ethitter, johnjamesjacoby, lancewillett, martinremy, nickmomrik, stephdau, yoavf, matveb, jeherve
+Contributors: automattic, alternatekev, andy, apeatling, azaozz, barry, beaulebens, blobaugh, cfinke, chellycat, danielbachhuber, daniloercoli, designsimply, eoigal, ethitter, gibrown, georgestephanis, hew, hugobaeta, iammattthomas, jblz, jeherve, jkudish, Joen, johnjamesjacoby, jshreve, lancewillett, martinremy, matt, matveb, mdawaffe, migueluy, nickmomrik, pento, stephdau, tmoorewp, Viper007Bond, westi, yoavf
 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
+Stable tag: 2.3.3
 
 Supercharge your WordPress site with powerful features previously only available to WordPress.com users.
 
@@ -36,6 +36,8 @@ Features include:
 * 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.
+* Add post sliders and other highlights to your theme with Featured Content.
+* Search once, get results from everything! A single search box that lets you search posts, pages, comments, and plugins
 * and *many* more to come!
 
 Note: The stats portion of Jetpack uses Quantcast to enhance its data.
@@ -58,25 +60,12 @@ Jetpack requires a connection to [WordPress.com](http://wordpress.com/) to enabl
 
 Once you've installed Jetpack, your stats will be available via the "Site Stats" menu which appears in the new Jetpack menu (under your Dashboard menu within WordPress).
 
-= How do I embed media? =
-
-Use [shortcodes](http://support.wordpress.com/shortcodes/) to embed your media.  Currently, Jetpack provides the following shortcodes.
-
-* [[archives]](http://support.wordpress.com/archives-shortcode/)
-* [[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/)
-* [[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/)
+= How do I contribute to Jetpack? =
+
+Easy! There are a couple of ways (more coming soon):
+
+* Give us a hand answering questions in our [support forum](http://wordpress.org/support/plugin/jetpack)
+* Report bugs, with reproduction steps, or post patches on our [Trac](http://plugins.trac.wordpress.org/newticket?component=jetpack)
 
 == Screenshots ==
 
@@ -91,6 +80,185 @@ Use [shortcodes](http://support.wordpress.com/shortcodes/) to embed your media.
 
 == Changelog ==
 
+= 2.3.3 =
+* Bug Fix: We were inadvertently overwriting cron schedules with our Jetpack heartbeat. This should now be fixed.
+* Enhancement: New Facebook Sharing icons.
+* Enhancement: Minor update to the Minileven stylesheet.
+
+= 2.3.2 =
+* Bug Fix: Fixed an issue where Facebook Pages were not available when connecting a Publicize account.
+* Bug Fix: For some web hosts, fixed an issue where 'Jetpack ID' error would occur consistently on connecting to WordPress.com.
+* Enhancement: Adding some new stats and heartbeat checking to Jetpack.
+
+= 2.3.1 =
+* Enhancement: Social Links: Retooling the class for better consistency and performance behind the scenes.
+* Enhancement: Omnisearch: Make it easier to search Custom Post Types.  No longer need to extend the class, if all you want is a basic display.  Just call `new Jetpack_Omnisearch_Posts( 'cpt' );`
+* Enhancement: Sharing Buttons: LinkedIn: Use the official button's sharing link on the Jetpack implementation for a more consistent sharing experience and produce better results on LinkedIn's end.
+* Enhancement: Debug / Connection: Better logic in determining whether the server can use SSL to connect to WPCOM servers.
+* Enhancement: Sharing: Twitter: Calculate the size of the Tweet based on the short URL rather than the full URL size.
+* Enhancement: Debug: More readable and understandable messages.
+* Enhancement: Likes: Including some MP6 styles.
+* Enhancement: Comments: Add new core classes to comment form.  See http://core.trac.wordpress.org/changeset/24525
+* Bug Fix: Omnisearch: Don't load everything initially, run the providers off admin_init, and then issue an action for folks to hook into.
+* Bug Fix: Omnisearch: Modify some child class functions to match the parent's parameters and avoid strict notices in newer versions of PHP.
+* Bug Fix: Omnisearch: Hide the search form in the module description if the current user can't use it.
+* Bug Fix: Comment Form: Use edit_pages, not edit_page (fixes glitch in previous beta, never publicly released).
+* Bug Fix: Twitter Timeline Widget: Additional testing of values and casting to default if they are nonconforming.
+* Bug Fix: Sharing: Pinterest: Make the button wider if there's a count to avoid overlapping with others.
+* Bug Fix: Post By Email: Change configuration_redirect to static.
+* Bug Fix: Likes: Don't call configuration_redirect as a static, do it as a method.
+* Bug Fix: Add some further security measures to module activation.
+
+= 2.3 =
+* Enhancement: Omnisearch: Search once, get results from everything! Omnisearch is a single search box that lets you search many different things
+* Enhancement: Debugger: this module helps you debug connection issues right from your dashboard, and contact the Jetpack support team if needed
+* Enhancement: Social Links: this module is a canonical source, based on Publicize, that themes can use to let users specify where social icons should link to
+* Enhancement: It’s now easier to find out if a module is active or note, thanks to the new Jetpack::is_module_active()
+* Enhancement: Contact Form: You are now able to customize the submit button text thanks to the submit_button_text parameter
+* Enhancement: Comments: We've added a filter to let users customize the Comment Reply label, and users can now also customize the prompt on the comment form again.
+* Enhancement: Mobile Theme: Add genericons.css and registering it so it’s easily accessible to other modules that may want it
+* Enhancement: Tiled Galleries: You can now customize the captions, thanks to the jetpack_slideshow_slide_caption filter
+* Enhancement: Widgets: Twitter Timeline: Add the noscrollbar option
+* Enhancement: Widgets: Facebook Like Box Widget: add a show_border attribute
+* Enhancement: Widgets: FB Like Box: let Jetpack users override the iframe background color set in an inline style attribute by using the jetpack_fb_likebox_bg filter
+* Bug Fix: Carousel: Fix a bug where double-clicking a gallery thumbnail broke the carousel functionality
+* Bug Fix: Comments: Change “must-log-in” to class from ID
+* Bug Fix: Contact Form: Make the Add Contact Form link a button, ala Add Media in core
+* Bug Fix: Contact Form: Fix encoding of field labels
+* Bug Fix: Contact Form: Remove references to missing images
+* Bug Fix: Fix 2 XSS vulnerabilities
+* Bug Fix: JSON API: Minor fixes for bbPress compatibility
+* Bug Fix: JSON API: Fix metadata bugs
+* Bug Fix: JSON API: Add a new hook that is fired when a post is posted using the API
+* Bug Fix: JSON API: Prefork/REST: update path normalizer to accept versions other than 1
+* Bug Fix: JSON API: Remove extra parenthesis in CSS
+* Bug Fix: Custom CSS: Move content width filters higher up so that they’re active for all users, not just logged-in admins.
+* Bug Fix: Custom CSS: All CSS properties that accept images as values need to be allowed to be declared multiple times so that cross-browser gradients work
+* Bug Fix: Infinite Scroll: Allow themes to define a custom function to render the IS footer
+* Bug Fix: Infinite Scroll: Fix up Twenty Thirteen styles for RTL and small viewports.
+* Bug Fix: Likes: Fix ‘Call to undefined function’
+* Bug Fix: Likes: Add scrolling no to iframe to make sure that like button in admin bar does not show scrollbars
+* Bug Fix: Likes: Remove setInterval( JetpackLikesWidgetQueueHandler, 250 ) call that was causing heavy CPU load
+* Bug Fix: Mobile Theme: Remove unused variable & function call
+* Bug Fix: Publicize: Fix LinkedIn profile URL generation
+* Bug Fix: Publicize: Better refresh handling for services such as LinkedIn and Facebook
+* Bug Fix: Shortcodes: Audio shortcode: Treat src as element 0. Fixes audio shortcodes created by wp_embed_register_handler when an audio url is on a line by itself
+* Bug Fix: Bandcamp: Updates to the Bandcamp shortcode
+* Bug Fix: Stats: Fix missing function get_editable_roles on non-admin page loads
+* Bug Fix: Widgets: Twitter Timeline: Fix HTML links in admin; set default values for width/height; change some of the sanitization functions
+* Bug Fix: Widgets: Top Posts Widget: Exclude attachments
+* Bug Fix: Widgets: Top Posts Widget: fix data validation for number of posts
+* Bug Fix: Fix PHP warnings non-static method called dynamically
+* Bug Fix: Fixed an issue in image extraction from HTML content
+* Bug Fix: Open Graph: Change default minimum size for og:image too 200×200
+* Note: The old Twitter widget was removed in favour of Twitter Timeline widget
+* Note: Add is_module_active() to make it easier to detect what is and what isn’t
+* Note: Compressing images via lossless methods
+* Note: Tidying up jetpack’s CSS
+* Note: Set the max DB version for our retina overrides that were meant to stop for WordPress 3.5
+* Note: Updating spin.js to the current version, and shifting to the canonical jquery.spin.js library
+* Note: Adding Jetpack_Options class, and abstracting out options functions to it
+
+= 2.2.5 =
+* Enhancement: Stats: Counting of registered users' views can now be enabled for specific roles
+* Bug Fix: Security tightening for metadata support in the REST API
+* Bug Fix: Update the method for checking Twitter Timeline widget_id and update coding standards
+* Bug Fix: Custom CSS: Allow the content width setting to be larger than the theme's content width
+* Bug Fix: Custom CSS: Fix possible missing argument warning.
+
+= 2.2.4 =
+* Bug Fix: JSON API compat file include was not assigning a variable correctly, thus throwing errors. This has been resolved.
+
+= 2.2.3 =
+* Enhancement: Comments - Add the reply-title H3 to the comment form so that themes or user CSS can style it
+* Enhancement: Custom CSS - Support for the CSS @viewport
+* Enhancement: JSON API - Support for i_like, is_following, and is_reblogged
+* Enhancement: JSON API: Custom Post Type Support
+* Enhancement: JSON API: Meta Data Support
+* Enhancement: JSON API: Bundled Support for bbPress
+* Enhancement: JSON API: Additions of following, reblog, and like status for post endpoints.
+* Enhancement: Shortcodes - Add Bandcamp shortcode
+* Enhancement: Tiled Galleries - Add code to get blog_id
+* Bug Fix: Carousel - Support relative image paths incase a plugin is filtering attachment URLs to be relative instead of absolute
+* Bug Fix: Carousel - Add likes widget to images / Respect comment settings for name/email
+* Bug Fix: Carousel - Make name and email optional if the setting in the admin area says they are
+* Bug Fix: Contact Form - Bug fixes, including a fix for WP-CLI
+* Bug Fix: Contact Form - Remove deprecated .live calls, delegate lazily to jQuery(document) since it's all in an iframe modal
+* Bug Fix: Contact Form - RTL styles
+* Bug Fix: Contact Form - Better handle MP6 icons
+* Bug Fix: Custom CSS - array_shift() took a variable by reference, so avoid passing it the result of a function
+* Bug Fix: Custom CSS - Allow case-insensitive CSS properties (<a href="http://wordpress.org/support/topic/two-issues-with-jetpack-css-module?replies=9">ref</a>)
+* Bug Fix: Infinite Scroll - Maintain main query's `post__not_in` values when querying posts for IS
+* Bug Fix: Infinite Scroll - Ensure that IS's `pre_get_posts` method isn't applied in the admin. Also fixes an incorrect use of `add_filter()` where `add_action()` was meant. Fixes #1696-plugins
+* Bug Fix: Infinite Scroll - CSS update - IS footer was too large in Firefox
+* Bug Fix: Infinite Scroll - Add bundled support for Twenty Thirteen default theme
+* Bug Fix: Infinite Scroll - Include posts table's prefix when modifying the SQL WordPress generates to retrieve posts for Infinite Scroll
+* Bug Fix: JSON API - Use wp_set_comment_status to change the comment status, to make sure actions are run where needed
+* Bug Fix: Likes - Update style and logic for matching id's
+* Bug Fix: Mobile Theme - Ensure that <code>minileven_actual_current_theme()</code> is child-theme compatible + other updates
+* Bug Fix: Mobile Theme - Update method for finding currently active theme.
+* Bug Fix: Notifications - Remove the postmessage.js enqueue since this feature solely supports native postMessage
+* Bug Fix: Notifications - Clean up script enqueues and use core versions of underscore and backbone on wpcom as fallbacks
+* Bug Fix: Notifications - Enqueue v2 scripts and style
+* Bug Fix: Notifications - Prefix module-specific scripts and style to prevent collision
+* Bug Fix: Notifications - Include lang and dir attributes on #wpnt-notes-panel so the notifications iframe can use these to display correctly
+* Bug Fix: Open Graph: Use the profile OG type instead of author. Add tags for first/last names
+* Bug Fix: Publicize - Remove the Yahoo! service because they stopped supporting that API entirely
+* Bug Fix: Publicize - fix fatal errors caused by using a method on a non-object. Props @ipstenu
+* Bug Fix: Sharing - Adding 2x graphics for Pocket sharing service
+* Bug Fix: Sharing - Bug fixes, and a new filter
+* Bug Fix: Shortcodes - Audio: make sure that the Jetpack audion shortcode does not override the 3.6 core audio shortcode. Also, we need to filter the old Jetpack-style shortcode to properly set the params for the Core audio shortcode.
+* Bug Fix: Shortcodes - Audio: Re-enable the flash player
+* Bug Fix: Shortcodes - Slideshow: RTL styling update
+* Bug Fix: Tiled Galleries - Fix IE8 display bug where it doesn't honor inline CSS for width on images
+* Bug Fix: Tiled Galleries - Remove depreacted hover call, use mouseenter mouseleave instead
+* Enhancement: Twitter Timeline Widget: New JavaScript based widget. Old one will discontinue May 7th. 
+
+= 2.2.2 =
+* Enhancement: Mobile Theme: Add controls for custom CSS.
+* Enhancement: Sharing: Add Pocket to the available services.
+* Bug Fix: Custom CSS: Update the method for generating content width setting.
+* Bug Fix: JSON API: Security updates.
+* Bug Fix: Likes: Add settings for email notifications and misc style updates.
+* Bug Fix: Notifications: Add the post types to sync after init.
+* Bug Fix: Publicize: RTL styling.
+* Bug Fix: Shortcodes: security fixes and function prefixing.
+* Bug Fix: Widgets: Update wording on the Top Posts widget for clarity.
+* Bug Fix: Jetpack Post Images security fixes.
+
+= 2.2.1 =
+* Enhancement: Development Mode: Define the `JETPACK_DEV_DEBUG` constant to `true` to enable an offline mode for localhost development. Only modules that don't require a WordPress.com connection can be enabled in this mode.
+* Enhancement: Likes: Added the number of likes to the wp-admin/edit.php screens.
+* Enhancement: Mobile Theme - design refresh
+* Enhancement: Shortcodes - Add a filter to the shortcode loading section so that a plugin can override what Jetpack loads for shortcodes
+* Enhancement: Widgets - Filter Jetpack's widgets so that a plugin can control which widgets get loaded
+* Bug Fix: Comments - Add in a wrapper div with id='commentform'
+* Bug Fix: Contact Form - Added date field with datepicker
+* Bug Fix: Contact Form - Allowed non-text widgets to use contact forms by running their output through the widget_text filter
+* Bug Fix: Custom CSS - Allowing color values to be defined multiple times
+* Bug Fix: Custom CSS - Dynamically loading the correct CSS/LESS/SCSS mode for the CSS editor if the user changes the preprocessor
+* Bug Fix: Custom CSS - Using the unminified worker CSS
+* Bug Fix: Custom CSS - Added rule: reminder about using .custom-background on body selector
+* Bug Fix: Custom CSS - Modified rule: Removed portion of overqualification rule that deems 'a.foo' overqualified if there are no other 'a' rules
+* Bug Fix: Custom CSS - Ensuring that the editor and the textarea behind it are using the same font so that the cursor appears in the correct location
+* Bug Fix: Custom CSS - Fix a bug that caused some sites to always ignore the base theme's CSS when in preview mode
+* Bug Fix: Custom CSS - Run stripslashes() before passing CSS to save()
+* Bug Fix: Custom CSS - Moving inline CSS and JavaScript into external files
+* Bug Fix: Infinite Scroll - Use the `is_main_query()` function and query method
+* Bug Fix: Infinite Scroll - Remove unused styles and an unnecessary margin setting
+* Bug Fix: Infinite Scroll - Allow the query used with IS to be filtered, so IS can be applied to a new query within a page template
+* Bug Fix: JSON API - Catch the 'User cannot view password protected post' error from can_view_post and bypass it for likes actions if the user has the password entered
+* Bug Fix: Likes - Bump cache buster, Don't show likes for password protected posts
+* Bug Fix: Notifications - Remove a redundant span closing tag
+* Bug Fix: Photon - If an image is already served from Photon but the anchor tag that surrounds it hasn't had its `href` value rewritten to use Photon, do so. Accounts for WP galleries whose individual items are linked to the original image files
+* Bug Fix: Publicize - Allows GLOBAL_CAP to be filtered, Adds an AYS to connection deletion, UI improvement for MP6 (and in general)
+* Bug Fix: Sharedaddy - Fire the sharing redirect earlier for increased plugin compatibility
+* Bug Fix: Stats - Move the display:none CSS output to wp_head so it gets written inside the HEAD tag if the option to hide the stats smilie is active
+* Bug Fix: Tiled Galleries - A more descriptive name for the default gallery type
+* Bug Fix: Tiled Galleries - Hide the Columns setting for gallery types that don't support it
+* Bug Fix: Run the admin_menu action late so that plugins hooking into it get a chance to run
+* Bug Fix: Prophylactic strict equality check
+
 = 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).

diff --git a/plugins/wordpress-importer/parsers.php b/plugins/wordpress-importer/parsers.php
index 7bd8ba4..f3cee6c 100644
--- a/plugins/wordpress-importer/parsers.php
+++ b/plugins/wordpress-importer/parsers.php
@@ -57,7 +57,24 @@ class WXR_Parser_SimpleXML {
 		$authors = $posts = $categories = $tags = $terms = array();
 
 		$internal_errors = libxml_use_internal_errors(true);
-		$xml = simplexml_load_file( $file );
+
+		$dom = new DOMDocument;
+		$old_value = null;
+		if ( function_exists( 'libxml_disable_entity_loader' ) ) {
+			$old_value = libxml_disable_entity_loader( true );
+		}
+		$success = $dom->loadXML( file_get_contents( $file ) );
+		if ( ! is_null( $old_value ) ) {
+			libxml_disable_entity_loader( $old_value );
+		}
+
+		if ( ! $success || isset( $dom->doctype ) ) {
+			return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this WXR file', 'wordpress-importer' ), libxml_get_errors() );
+		}
+
+		$xml = simplexml_import_dom( $dom );
+		unset( $dom );
+
 		// halt if loading produces an error
 		if ( ! $xml )
 			return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this WXR file', 'wordpress-importer' ), libxml_get_errors() );

diff --git a/plugins/wordpress-importer/readme.txt b/plugins/wordpress-importer/readme.txt
index b623469..b326c82 100644
--- a/plugins/wordpress-importer/readme.txt
+++ b/plugins/wordpress-importer/readme.txt
@@ -1,10 +1,12 @@
-=== Plugin Name ===
+=== WordPress Importer ===
 Contributors: wordpressdotorg
 Donate link: 
 Tags: importer, wordpress
 Requires at least: 3.0
-Tested up to: 3.4
+Tested up to: 3.6
 Stable tag: 0.6
+License: GPLv2 or later
+License URI: http://www.gnu.org/licenses/gpl-2.0.html
 
 Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file.
 

diff --git a/plugins/wordpress-importer/wordpress-importer.php b/plugins/wordpress-importer/wordpress-importer.php
index f0abbda..ab6814c 100644
--- a/plugins/wordpress-importer/wordpress-importer.php
+++ b/plugins/wordpress-importer/wordpress-importer.php
@@ -5,7 +5,7 @@ Plugin URI: http://wordpress.org/extend/plugins/wordpress-importer/
 Description: Import posts, pages, comments, custom fields, categories, tags and more from a WordPress export file.
 Author: wordpressdotorg
 Author URI: http://wordpress.org/
-Version: 0.6
+Version: 0.6.1
 Text Domain: wordpress-importer
 License: GPL version 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */
@@ -393,6 +393,8 @@ class WP_Import extends WP_Importer {
 	 * Doesn't create a new category if its slug already exists
 	 */
 	function process_categories() {
+		$this->categories = apply_filters( 'wp_import_categories', $this->categories );
+
 		if ( empty( $this->categories ) )
 			return;
 
@@ -437,6 +439,8 @@ class WP_Import extends WP_Importer {
 	 * Doesn't create a tag if its slug already exists
 	 */
 	function process_tags() {
+		$this->tags = apply_filters( 'wp_import_tags', $this->tags );
+
 		if ( empty( $this->tags ) )
 			return;
 
@@ -475,6 +479,8 @@ class WP_Import extends WP_Importer {
 	 * Doesn't create a term its slug already exists
 	 */
 	function process_terms() {
+		$this->terms = apply_filters( 'wp_import_terms', $this->terms );
+
 		if ( empty( $this->terms ) )
 			return;
 
@@ -522,11 +528,16 @@ class WP_Import extends WP_Importer {
 	 * Note that new/updated terms, comments and meta are imported for the last of the above.
 	 */
 	function process_posts() {
+		$this->posts = apply_filters( 'wp_import_posts', $this->posts );
+
 		foreach ( $this->posts as $post ) {
+			$post = apply_filters( 'wp_import_post_data_raw', $post );
+
 			if ( ! post_type_exists( $post['post_type'] ) ) {
 				printf( __( 'Failed to import &#8220;%s&#8221;: Invalid post type %s', 'wordpress-importer' ),
 					esc_html($post['post_title']), esc_html($post['post_type']) );
 				echo '<br />';
+				do_action( 'wp_import_post_exists', $post );
 				continue;
 			}
 
@@ -578,6 +589,9 @@ class WP_Import extends WP_Importer {
 					'post_type' => $post['post_type'], 'post_password' => $post['post_password']
 				);
 
+				$original_post_ID = $post['post_id'];
+				$postdata = apply_filters( 'wp_import_post_data_processed', $postdata, $post );
+
 				if ( 'attachment' == $postdata['post_type'] ) {
 					$remote_url = ! empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid'];
 
@@ -597,6 +611,7 @@ class WP_Import extends WP_Importer {
 					$comment_post_ID = $post_id = $this->process_attachment( $postdata, $remote_url );
 				} else {
 					$comment_post_ID = $post_id = wp_insert_post( $postdata, true );
+					do_action( 'wp_import_insert_post', $post_id, $original_post_ID, $postdata, $post );
 				}
 
 				if ( is_wp_error( $post_id ) ) {
@@ -615,6 +630,11 @@ class WP_Import extends WP_Importer {
 			// map pre-import ID to local ID
 			$this->processed_posts[intval($post['post_id'])] = (int) $post_id;
 
+			if ( ! isset( $post['terms'] ) )
+				$post['terms'] = array();
+
+			$post['terms'] = apply_filters( 'wp_import_post_terms', $post['terms'], $post_id, $post );
+
 			// add categories, tags and other terms
 			if ( ! empty( $post['terms'] ) ) {
 				$terms_to_set = array();
@@ -627,11 +647,13 @@ class WP_Import extends WP_Importer {
 						$t = wp_insert_term( $term['name'], $taxonomy, array( 'slug' => $term['slug'] ) );
 						if ( ! is_wp_error( $t ) ) {
 							$term_id = $t['term_id'];
+							do_action( 'wp_import_insert_term', $t, $term, $post_id, $post );
 						} else {
 							printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($taxonomy), esc_html($term['name']) );
 							if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
 								echo ': ' . $t->get_error_message();
 							echo '<br />';
+							do_action( 'wp_import_insert_term_failed', $t, $term, $post_id, $post );
 							continue;
 						}
 					}
@@ -640,10 +662,16 @@ class WP_Import extends WP_Importer {
 
 				foreach ( $terms_to_set as $tax => $ids ) {
 					$tt_ids = wp_set_post_terms( $post_id, $ids, $tax );
+					do_action( 'wp_import_set_post_terms', $tt_ids, $ids, $tax, $post_id, $post );
 				}
 				unset( $post['terms'], $terms_to_set );
 			}
 
+			if ( ! isset( $post['comments'] ) )
+				$post['comments'] = array();
+
+			$post['comments'] = apply_filters( 'wp_import_post_comments', $post['comments'], $post_id, $post );
+
 			// add/update comments
 			if ( ! empty( $post['comments'] ) ) {
 				$num_comments = 0;
@@ -674,6 +702,7 @@ class WP_Import extends WP_Importer {
 							$comment['comment_parent'] = $inserted_comments[$comment['comment_parent']];
 						$comment = wp_filter_comment( $comment );
 						$inserted_comments[$key] = wp_insert_comment( $comment );
+						do_action( 'wp_import_insert_comment', $inserted_comments[$key], $comment, $comment_post_ID, $post );
 
 						foreach( $comment['commentmeta'] as $meta ) {
 							$value = maybe_unserialize( $meta['value'] );
@@ -686,10 +715,15 @@ class WP_Import extends WP_Importer {
 				unset( $newcomments, $inserted_comments, $post['comments'] );
 			}
 
+			if ( ! isset( $post['postmeta'] ) )
+				$post['postmeta'] = array();
+
+			$post['postmeta'] = apply_filters( 'wp_import_post_meta', $post['postmeta'], $post_id, $post );
+
 			// add/update post meta
-			if ( isset( $post['postmeta'] ) ) {
+			if ( ! empty( $post['postmeta'] ) ) {
 				foreach ( $post['postmeta'] as $meta ) {
-					$key = apply_filters( 'import_post_meta_key', $meta['key'] );
+					$key = apply_filters( 'import_post_meta_key', $meta['key'], $post_id, $post );
 					$value = false;
 
 					if ( '_edit_last' == $key ) {


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-08-01  6:52 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-10 11:07 [gentoo-commits] proj/blogs-gentoo:master commit in: plugins/jetpack/modules/publicize/assets/rtl/, Theo Chatzimichos
  -- strict thread matches above, loose matches on Subject: below --
2013-08-01  6:51 Theo Chatzimichos

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox